| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /*
- ************************************************************************************************************************
- * uC/OS-III
- * The Real-Time Kernel
- *
- * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
- * All rights reserved. Protected by international copyright laws.
- *
- * ISR QUEUE MANAGEMENT
- *
- * File : OS_INT.C
- * By : JJL
- * Version : V3.02.00
- *
- * LICENSING TERMS:
- * ---------------
- * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
- * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
- * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
- * application/product. We provide ALL the source code for your convenience and to help you
- * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
- * it commercially without paying a licensing fee.
- *
- * Knowledge of the source code may NOT be used to develop a similar product.
- *
- * Please help us continue to provide the embedded community with the finest software available.
- * Your honesty is greatly appreciated.
- *
- * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
- ************************************************************************************************************************
- */
- #include <os.h>
- #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
- const CPU_CHAR *os_int__c = "$Id: $";
- #endif
- #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
- /*$PAGE*/
- /*
- ************************************************************************************************************************
- * POST TO ISR QUEUE
- *
- * Description: This function places contents of posts into an intermediate queue to help defer processing of interrupts
- * at the task level.
- *
- * Arguments : type is the type of kernel object the post is destined to:
- *
- * OS_OBJ_TYPE_SEM
- * OS_OBJ_TYPE_Q
- * OS_OBJ_TYPE_FLAG
- * OS_OBJ_TYPE_TASK_MSG
- * OS_OBJ_TYPE_TASK_SIGNAL
- *
- * p_obj is a pointer to the kernel object to post to. This can be a pointer to a semaphore,
- * ----- a message queue or a task control clock.
- *
- * p_void is a pointer to a message that is being posted. This is used when posting to a message
- * queue or directly to a task.
- *
- * msg_size is the size of the message being posted
- *
- * flags if the post is done to an event flag group then this corresponds to the flags being
- * posted
- *
- * ts is a timestamp as to when the post was done
- *
- * opt this corresponds to post options and applies to:
- *
- * OSFlagPost()
- * OSSemPost()
- * OSQPost()
- * OSTaskQPost()
- *
- * p_err is a pointer to a variable that will contain an error code returned by this function.
- *
- * OS_ERR_NONE if the post to the ISR queue was successful
- * OS_ERR_INT_Q_FULL if the ISR queue is full and cannot accepts any further posts. This
- * generally indicates that you are receiving interrupts faster than you
- * can process them or, that you didn't make the ISR queue large enough.
- *
- * Returns : none
- *
- * Note(s) : none
- ************************************************************************************************************************
- */
- void OS_IntQPost (OS_OBJ_TYPE type,
- void *p_obj,
- void *p_void,
- OS_MSG_SIZE msg_size,
- OS_FLAGS flags,
- OS_OPT opt,
- CPU_TS ts,
- OS_ERR *p_err)
- {
- CPU_SR_ALLOC();
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return;
- }
- #endif
- CPU_CRITICAL_ENTER();
- if (OSIntQNbrEntries < OSCfg_IntQSize) { /* Make sure we haven't already filled the ISR queue */
- OSIntQNbrEntries++;
- if (OSIntQMaxNbrEntries < OSIntQNbrEntries) {
- OSIntQMaxNbrEntries = OSIntQNbrEntries;
- }
- OSIntQInPtr->Type = type; /* Save object type being posted */
- OSIntQInPtr->ObjPtr = p_obj; /* Save pointer to object being posted */
- OSIntQInPtr->MsgPtr = p_void; /* Save pointer to message if posting to a message queue */
- OSIntQInPtr->MsgSize = msg_size; /* Save the message size if posting to a message queue */
- OSIntQInPtr->Flags = flags; /* Save the flags if posting to an event flag group */
- OSIntQInPtr->Opt = opt; /* Save post options */
- OSIntQInPtr->TS = ts; /* Save time stamp */
- OSIntQInPtr = OSIntQInPtr->NextPtr; /* Point to the next interrupt handler queue entry */
- OSRdyList[0].NbrEntries = (OS_OBJ_QTY)1; /* Make the interrupt handler task ready to run */
- OSRdyList[0].HeadPtr = &OSIntQTaskTCB;
- OSRdyList[0].TailPtr = &OSIntQTaskTCB;
- OS_PrioInsert(0u); /* Add task priority 0 in the priority table */
- OSPrioSaved = OSPrioCur; /* Save current priority */
- *p_err = OS_ERR_NONE;
- } else {
- OSIntQOvfCtr++; /* Count the number of ISR queue overflows */
- *p_err = OS_ERR_INT_Q_FULL;
- }
- CPU_CRITICAL_EXIT();
- }
- /*$PAGE*/
- /*
- ************************************************************************************************************************
- * INTERRUPT QUEUE MANAGEMENT TASK
- *
- * Description: This task is created by OS_IntQTaskInit().
- *
- * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
- * the argument is not used and will be a NULL pointer.
- *
- * Returns : none
- ************************************************************************************************************************
- */
- void OS_IntQRePost (void)
- {
- void *p_obj;
- void *p_void;
- OS_ERR err;
- OS_FLAGS flags;
- CPU_TS ts;
- OS_OBJ_TYPE type;
- OS_OPT opt;
- OS_MSG_SIZE msg_size;
- CPU_SR_ALLOC();
- CPU_CRITICAL_ENTER();
- type = OSIntQOutPtr->Type; /* Get local copy of queue item contents */
- p_obj = OSIntQOutPtr->ObjPtr;
- p_void = OSIntQOutPtr->MsgPtr;
- msg_size = OSIntQOutPtr->MsgSize;
- flags = OSIntQOutPtr->Flags;
- opt = OSIntQOutPtr->Opt;
- ts = OSIntQOutPtr->TS;
- OSIntQOutPtr = OSIntQOutPtr->NextPtr; /* Point to next item in the ISR queue */
- CPU_CRITICAL_EXIT();
- switch (type) { /* Re-post to task */
- case OS_OBJ_TYPE_FLAG:
- #if OS_CFG_FLAG_EN > 0u
- (void)OS_FlagPost((OS_FLAG_GRP *)p_obj,
- (OS_FLAGS )flags,
- (OS_OPT )opt,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- #endif
- break;
- case OS_OBJ_TYPE_Q:
- #if OS_CFG_Q_EN > 0u
- OS_QPost((OS_Q *)p_obj,
- (void *)p_void,
- (OS_MSG_SIZE)msg_size,
- (OS_OPT )opt,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- #endif
- break;
- case OS_OBJ_TYPE_SEM:
- #if OS_CFG_SEM_EN > 0u
- (void)OS_SemPost((OS_SEM *)p_obj,
- (OS_OPT )opt,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- #endif
- break;
- case OS_OBJ_TYPE_TASK_MSG:
- #if OS_CFG_TASK_Q_EN > 0u
- OS_TaskQPost((OS_TCB *)p_obj,
- (void *)p_void,
- (OS_MSG_SIZE)msg_size,
- (OS_OPT )opt,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- #endif
- break;
- case OS_OBJ_TYPE_TASK_SIGNAL:
- (void)OS_TaskSemPost((OS_TCB *)p_obj,
- (OS_OPT )opt,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- break;
- case OS_OBJ_TYPE_TICK:
- #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
- OS_SchedRoundRobin(&OSRdyList[OSPrioSaved]);
- #endif
- (void)OS_TaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
- (OS_OPT )OS_OPT_POST_NONE,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- #if OS_CFG_TMR_EN > 0u
- OSTmrUpdateCtr--;
- if (OSTmrUpdateCtr == (OS_CTR)0u) {
- OSTmrUpdateCtr = OSTmrUpdateCnt;
- ts = OS_TS_GET(); /* Get timestamp */
- (void)OS_TaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
- (OS_OPT )OS_OPT_POST_NONE,
- (CPU_TS )ts,
- (OS_ERR *)&err);
- }
- #endif
- break;
- default:
- break;
- }
- }
- /*$PAGE*/
- /*
- ************************************************************************************************************************
- * INTERRUPT QUEUE MANAGEMENT TASK
- *
- * Description: This task is created by OS_IntQTaskInit().
- *
- * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
- * the argument is not used and will be a NULL pointer.
- *
- * Returns : none
- ************************************************************************************************************************
- */
- void OS_IntQTask (void *p_arg)
- {
- CPU_BOOLEAN done;
- CPU_TS ts_start;
- CPU_TS ts_end;
- CPU_SR_ALLOC();
- p_arg = p_arg; /* Not using 'p_arg', prevent compiler warning */
- while (DEF_ON) {
- done = DEF_FALSE;
- while (done == DEF_FALSE) {
- if (OSIntQNbrEntries == (OS_OBJ_QTY)0u) {
- CPU_CRITICAL_ENTER();
- OSRdyList[0].NbrEntries = (OS_OBJ_QTY)0u; /* Remove from ready list */
- OSRdyList[0].HeadPtr = (OS_TCB *)0;
- OSRdyList[0].TailPtr = (OS_TCB *)0;
- OS_PrioRemove(0u); /* Remove from the priority table */
- CPU_CRITICAL_EXIT();
- OSSched();
- done = DEF_TRUE; /* No more entries in the queue, we are done */
- } else {
- ts_start = OS_TS_GET();
- OS_IntQRePost();
- ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
- if (ts_end > OSIntQTaskTimeMax) {
- OSIntQTaskTimeMax = ts_end;
- }
- CPU_CRITICAL_ENTER();
- OSIntQNbrEntries--;
- CPU_CRITICAL_EXIT();
- }
- }
- }
- }
- /*$PAGE*/
- /*
- ************************************************************************************************************************
- * INITIALIZE THE ISR QUEUE
- *
- * Description: This function is called by OSInit() to initialize the ISR queue.
- *
- * Arguments : p_err is a pointer to a variable that will contain an error code returned by this function.
- *
- * OS_ERR_INT_Q If you didn't provide an ISR queue in OS_CFG.C
- * OS_ERR_INT_Q_SIZE If you didn't specify a large enough ISR queue.
- * OS_ERR_STK_INVALID If you specified a NULL pointer for the task of the ISR task
- * handler
- * OS_ERR_STK_SIZE_INVALID If you didn't specify a stack size greater than the minimum
- * specified by OS_CFG_STK_SIZE_MIN
- * OS_ERR_??? An error code returned by OSTaskCreate().
- *
- * Returns : none
- *
- * Note(s) : none
- ************************************************************************************************************************
- */
- void OS_IntQTaskInit (OS_ERR *p_err)
- {
- OS_INT_Q *p_int_q;
- OS_INT_Q *p_int_q_next;
- OS_OBJ_QTY i;
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return;
- }
- #endif
- OSIntQOvfCtr = (OS_QTY)0u; /* Clear the ISR queue overflow counter */
- if (OSCfg_IntQBasePtr == (OS_INT_Q *)0) {
- *p_err = OS_ERR_INT_Q;
- return;
- }
- if (OSCfg_IntQSize < (OS_OBJ_QTY)2u) {
- *p_err = OS_ERR_INT_Q_SIZE;
- return;
- }
- OSIntQTaskTimeMax = (CPU_TS)0;
- p_int_q = OSCfg_IntQBasePtr; /* Initialize the circular ISR queue */
- p_int_q_next = p_int_q;
- p_int_q_next++;
- for (i = 0u; i < OSCfg_IntQSize; i++) {
- p_int_q->Type = OS_OBJ_TYPE_NONE;
- p_int_q->ObjPtr = (void *)0;
- p_int_q->MsgPtr = (void *)0;
- p_int_q->MsgSize = (OS_MSG_SIZE)0u;
- p_int_q->Flags = (OS_FLAGS )0u;
- p_int_q->Opt = (OS_OPT )0u;
- p_int_q->NextPtr = p_int_q_next;
- p_int_q++;
- p_int_q_next++;
- }
- p_int_q--;
- p_int_q_next = OSCfg_IntQBasePtr;
- p_int_q->NextPtr = p_int_q_next;
- OSIntQInPtr = p_int_q_next;
- OSIntQOutPtr = p_int_q_next;
- OSIntQNbrEntries = (OS_OBJ_QTY)0u;
- OSIntQMaxNbrEntries = (OS_OBJ_QTY)0u;
- /* -------------- CREATE THE ISR QUEUE TASK ------------- */
- if (OSCfg_IntQTaskStkBasePtr == (CPU_STK *)0) {
- *p_err = OS_ERR_STK_INVALID;
- return;
- }
- if (OSCfg_IntQTaskStkSize < OSCfg_StkSizeMin) {
- *p_err = OS_ERR_STK_SIZE_INVALID;
- return;
- }
- OSTaskCreate((OS_TCB *)&OSIntQTaskTCB,
- (CPU_CHAR *)((void *)"uC/OS-III ISR Queue Task"),
- (OS_TASK_PTR )OS_IntQTask,
- (void *)0,
- (OS_PRIO )0u, /* This task is ALWAYS at priority '0' (i.e. highest) */
- (CPU_STK *)OSCfg_IntQTaskStkBasePtr,
- (CPU_STK_SIZE)OSCfg_IntQTaskStkLimit,
- (CPU_STK_SIZE)OSCfg_IntQTaskStkSize,
- (OS_MSG_QTY )0u,
- (OS_TICK )0u,
- (void *)0,
- (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
- (OS_ERR *)p_err);
- }
- #endif
|