_mqx_uint _taskq_resume ( /* [IN] the task queue handle */ pointer users_task_queue_ptr, /* [IN] TRUE if all tasks on the queue to be resumed */ boolean all_tasks ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; register TD_STRUCT_PTR td_ptr; register TASK_QUEUE_STRUCT_PTR task_queue_ptr = (TASK_QUEUE_STRUCT_PTR)users_task_queue_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_taskq_resume, users_task_queue_ptr, all_tasks); #if MQX_CHECK_ERRORS if (task_queue_ptr == NULL){ _KLOGX2(KLOG_taskq_resume, MQX_INVALID_TASK_QUEUE); return(MQX_INVALID_TASK_QUEUE); } /* Endif */ #endif _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (task_queue_ptr->VALID != TASK_QUEUE_VALID) { _int_enable(); _KLOGX2(KLOG_taskq_resume, MQX_INVALID_TASK_QUEUE); return(MQX_INVALID_TASK_QUEUE); } /* Endif */ #endif if (_QUEUE_GET_SIZE(&task_queue_ptr->TD_QUEUE) == 0) { /* Task queue is empty */ _int_enable(); _KLOGX2(KLOG_taskq_resume, MQX_TASK_QUEUE_EMPTY); return(MQX_TASK_QUEUE_EMPTY); } /* Endif */ if (all_tasks) { while (_QUEUE_GET_SIZE(&task_queue_ptr->TD_QUEUE)) { _QUEUE_DEQUEUE(&task_queue_ptr->TD_QUEUE, td_ptr); _TASK_READY(td_ptr, kernel_data); } /* Endwhile */ } else { _QUEUE_DEQUEUE(&task_queue_ptr->TD_QUEUE, td_ptr); _TASK_READY(td_ptr, kernel_data); } /* Endif */ _INT_ENABLE(); _CHECK_RUN_SCHEDULER();/* Let higher priority task run */ _KLOGX2(KLOG_taskq_resume, MQX_OK); return( MQX_OK ); } /* Endbody */
boolean _watchdog_stop ( void ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE1(KLOG_watchdog_stop); td_ptr = kernel_data->ACTIVE_PTR; if (td_ptr->FLAGS & TASK_WATCHDOG_STARTED) { _INT_DISABLE(); /* Start CR 333 */ /* td_ptr->FLAGS &= ~(TASK_WATCHDOG_STARTED | TASK_WATCHDOG_RUNNING); */ td_ptr->FLAGS &= ~TASK_WATCHDOG_RUNNING; /* End CR 333 */ _INT_ENABLE(); _KLOGX2(KLOG_watchdog_stop, TRUE); return(TRUE); } /* Endif */ _KLOGX2(KLOG_watchdog_stop, FALSE); return(FALSE); } /* Endbody */
/*! * \brief Used by a task to clear the specified event bits in the ligtweight event. * * \param[in] event_ptr Pointer to the event. * \param[in] bit_mask Bit mask. Each bit represents an event bit to clear. * * \return MQX_OK * \return MQX_LWEVENT_INVALID (Lightweight event is not valid.) * * \see _lwevent_create * \see _lwevent_destroy * \see _lwevent_set * \see _lwevent_set_auto_clear * \see _lwevent_test * \see _lwevent_wait_for * \see _lwevent_wait_ticks * \see _lwevent_wait_until * \see _lwevent_get_signalled * \see LWEVENT_STRUCT */ _mqx_uint _lwevent_clear ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint bit_mask ) { _KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data); #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwevent_clear(event_ptr, bit_mask); } #endif _KLOGM(_GET_KERNEL_DATA(kernel_data)); _KLOGE3(KLOG_lwevent_clear, event_ptr, bit_mask); _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); _KLOGX2(KLOG_lwevent_clear, MQX_LWEVENT_INVALID); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif event_ptr->VALUE &= ~bit_mask; _INT_ENABLE(); _KLOGX2(KLOG_lwevent_clear, MQX_OK); return (MQX_OK); }
_mqx_uint _lwsem_wait_for ( /* [IN] the semaphore address */ LWSEM_STRUCT_PTR sem_ptr, /* [IN] the number of ticks to delay */ MQX_TICK_STRUCT_PTR ticks ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwsem_wait_for, sem_ptr, ticks); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwsem_wait_for, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif #if MQX_CHECK_VALIDITY if (sem_ptr->VALID != LWSEM_VALID) { _KLOGX2(KLOG_lwsem_wait_for, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ #endif _INT_DISABLE(); if (sem_ptr->VALUE <= 0) { td_ptr = kernel_data->ACTIVE_PTR; /* Calculate time to wake up the task */ PSP_ADD_TICKS(ticks, &kernel_data->TIME, &td_ptr->TIMEOUT); result = _lwsem_wait_timed_internal(sem_ptr, td_ptr); } else { --sem_ptr->VALUE; /* Start CR 788 */ result = MQX_OK; /* End CR 788 */ } /* Endif */ //#if MQX_COMPONENT_DESTRUCTION /* We must check for component destruction */ if (sem_ptr->VALID != LWSEM_VALID) { _int_enable(); /* The semaphore has been deleted */ _KLOGX2(KLOG_lwsem_wait_for, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ //#endif _INT_ENABLE(); _KLOGX2(KLOG_lwsem_wait_for, result); return(result); } /* Endbody */
void _time_delay_for ( /* [IN] the number of ticks to delay */ register MQX_TICK_STRUCT_PTR ticks ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; register TD_STRUCT_PTR td_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_time_delay_for, ticks); #if MQX_CHECK_ERRORS if (ticks == NULL) { _task_set_error(MQX_INVALID_PARAMETER); _KLOGX2(KLOG_time_delay_for, MQX_INVALID_PARAMETER); return; } /* Endif */ #endif td_ptr = kernel_data->ACTIVE_PTR; _INT_DISABLE(); /* Calculate time to wake up the task */ PSP_ADD_TICKS(ticks, &kernel_data->TIME, &td_ptr->TIMEOUT); _time_delay_internal(td_ptr); _INT_ENABLE(); _KLOGX1(KLOG_time_delay_for); } /* Endbody */
void _time_set ( /* [IN] the address where the new time is to be taken from */ register TIME_STRUCT_PTR time_ptr ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; MQX_TICK_STRUCT ticks; _GET_KERNEL_DATA(kernel_data); _KLOGE4(KLOG_time_set, time_ptr, time_ptr->SECONDS, time_ptr->MILLISECONDS); /* Normalize time */ MQX_NORMALIZE_TIME_STRUCT(time_ptr); /* First convert old time struct into the tick struct */ PSP_TIME_TO_TICKS(time_ptr, &ticks); _INT_DISABLE(); /* Calculate offset */ PSP_SUB_TICKS(&ticks, &kernel_data->TIME, &kernel_data->TIME_OFFSET); _INT_ENABLE(); _KLOGX1(KLOG_time_set); } /* Endbody */
/*FUNCTION*----------------------------------------------------- * * Function Name : _mem_alloc_align * Returned Value : pointer. NULL is returned upon error. * Comments : allocates an aligned block of memory * *END*---------------------------------------------------------*/ pointer _mem_alloc_align ( /* [IN] the size of the memory block */ _mem_size size, /* [IN] the alignment of the memory block */ _mem_size align ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; _mqx_uint error; pointer result; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_mem_alloc, size); _INT_DISABLE(); result = _mem_alloc_internal_align(size, align, kernel_data->ACTIVE_PTR, (MEMPOOL_STRUCT_PTR)&kernel_data->KD_POOL, &error); /* update the memory allocation pointer in case a lower priority ** task was preempted inside _mem_alloc_internal */ kernel_data->KD_POOL.POOL_ALLOC_CURRENT_BLOCK = kernel_data->KD_POOL.POOL_FREE_LIST_PTR; _INT_ENABLE(); #if MQX_CHECK_ERRORS if (error != MQX_OK) { _task_set_error(error); } /* Endif */ #endif _KLOGX3(KLOG_mem_alloc_align, result, kernel_data->KD_POOL.POOL_BLOCK_IN_ERROR); return(result); }
void _klog_log ( /* [IN] what type of log is this */ _mqx_uint type, /* [IN] parameter 1 */ _mqx_max_type p1, /* [IN] parameter 2 */ _mqx_max_type p2, /* [IN] parameter 3 */ _mqx_max_type p3, /* [IN] parameter 4 */ _mqx_max_type p4, /* [IN] parameter 5 */ _mqx_max_type p5 ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; _mqx_max_type calling_pc; _GET_KERNEL_DATA(kernel_data); if ( !(kernel_data->LOG_CONTROL & KLOG_ENABLED) ) { return; } /* Endif */ if ( kernel_data->LOG_CONTROL & KLOG_TASK_QUALIFIED ) { if (! (kernel_data->ACTIVE_PTR->FLAGS & TASK_LOGGING_ENABLED) ) { return; } /* Endif */ } /* Endif */ if ((type == KLOG_FUNCTION_ENTRY) || (type == KLOG_FUNCTION_EXIT)) { if ( !(kernel_data->LOG_CONTROL & KLOG_FUNCTIONS_ENABLED) ) { return; } /* Endif */ /* Functions enabled, now lets check function group enabled */ if (((p1 & KLOG_FUNCTION_MASK) & kernel_data->LOG_CONTROL) == 0) { return; } /* Endif */ } /* Endif */ if (type == KLOG_FUNCTION_ENTRY) { calling_pc = (_mqx_max_type)_PSP_GET_CALLING_PC(); } else { calling_pc = 0; } /* Endif */ _INT_DISABLE(); _lwlog_write(LOG_KERNEL_LOG_NUMBER, (_mqx_max_type)type, p1, p2, p3, p4, p5, calling_pc); _INT_ENABLE(); } /* Endbody */
_mqx_uint _taskq_suspend ( /* [IN] the task queue handle */ pointer users_task_queue_ptr ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; register TD_STRUCT_PTR td_ptr; register TASK_QUEUE_STRUCT_PTR task_queue_ptr = (TASK_QUEUE_STRUCT_PTR)users_task_queue_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_taskq_suspend, users_task_queue_ptr); #if MQX_CHECK_ERRORS if (task_queue_ptr == NULL){ _KLOGX2(KLOG_taskq_suspend, MQX_INVALID_PARAMETER); return(MQX_INVALID_PARAMETER); } /* Endif */ if (kernel_data->IN_ISR) { _KLOGX2(KLOG_taskq_suspend, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); }/* Endif */ #endif td_ptr = kernel_data->ACTIVE_PTR; _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (task_queue_ptr->VALID != TASK_QUEUE_VALID) { _int_enable(); _KLOGX2(KLOG_taskq_suspend, MQX_INVALID_TASK_QUEUE); return(MQX_INVALID_TASK_QUEUE); } /* Endif */ #endif td_ptr->STATE = TASK_QUEUE_BLOCKED; _QUEUE_UNLINK(td_ptr); /* Remove task from ready to run queue */ td_ptr->INFO = (_mqx_uint)&task_queue_ptr->TD_QUEUE; if (task_queue_ptr->POLICY & MQX_TASK_QUEUE_BY_PRIORITY) { _sched_insert_priorityq_internal(&task_queue_ptr->TD_QUEUE, td_ptr); } else { _QUEUE_ENQUEUE(&task_queue_ptr->TD_QUEUE, td_ptr); } /* Endif */ _sched_execute_scheduler_internal(); /* Let the other tasks run */ _INT_ENABLE(); _KLOGX2(KLOG_taskq_suspend, MQX_OK); return( MQX_OK ); } /* Endbody */
/*! * \brief Marks the message as "free". * * Only the task that has the message as its resource can free the message. A * message becomes a task's resource when the task allocates the message, and it * continues to be a resource until the task either frees it or puts it in a * message queue. A message becomes a resource of the task that got it from a * message queue. * \n The function returns the message to the message pool from which it was * allocated. * * \param[in] msg_ptr Pointer to a message struct which is to be freed. * * \warning On failure, calls _task_set_error() to set one the following task * error codes: * \li MQX_INVALID_POINTER (Msg_ptr does not point to a valid message.) * \li MQX_NOT_RESOURCE_OWNER (Message is already freed.) * \li MSGQ_MESSAGE_IS_QUEUED (Message is in a queue.) * * \see _msgpool_create * \see _msgpool_create_system * \see _msgpool_destroy * \see _msg_alloc_system * \see _msg_alloc * \see _task_set_error * \see MESSAGE_HEADER_STRUCT */ void _msg_free ( pointer msg_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MSGPOOL_STRUCT_PTR msgpool_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_msg_free, msg_ptr); imsg_ptr = GET_INTERNAL_MESSAGE_PTR(msg_ptr); #if MQX_CHECK_VALIDITY if ( imsg_ptr->VALID != MSG_VALID ) { _KLOGX2(KLOG_msg_free, MQX_INVALID_POINTER); _task_set_error(MQX_INVALID_POINTER); return; } /* Endif */ #endif #if MQX_CHECK_ERRORS if (imsg_ptr->FREE) { _KLOGX2(KLOG_msg_free, MQX_NOT_RESOURCE_OWNER); _task_set_error(MQX_NOT_RESOURCE_OWNER); return; } /* Endif */ if (imsg_ptr->QUEUED) { _KLOGX2(KLOG_msg_free, MSGQ_MESSAGE_IS_QUEUED); _task_set_error(MSGQ_MESSAGE_IS_QUEUED); return; } /* Endif */ #endif msgpool_ptr = imsg_ptr->MSGPOOL_PTR; imsg_ptr->FREE = TRUE; imsg_ptr->QUEUED = FALSE; _INT_DISABLE(); /* Link onto the free list */ imsg_ptr->NEXT = msgpool_ptr->MSG_FREE_LIST_PTR; msgpool_ptr->MSG_FREE_LIST_PTR = imsg_ptr; ++msgpool_ptr->SIZE; _INT_ENABLE(); _KLOGX2(KLOG_msg_free, MQX_OK); } /* Endbody */
/*! * \brief An MQX-provided default ISR for unhandled interrupts. The function * depends on the PSP. * * The function changes the state of the active task to UNHANDLED_INT_BLOCKED and * blocks the task. * \n The function uses the default I/O channel to display at least: * \li Vector number that caused the unhandled exception. * \li Task ID and task descriptor of the active task. * * \n Depending on the PSP, more information might be displayed. * * \param[in] parameter Parameter passed to the default ISR. * * \note * Since the ISR uses printf() to display information to the default I/O channel, * default I/O must not be on a channel that uses interrupt-driven I/O or the * debugger. * * \warning Blocks the active task. * * \see _int_install_unexpected_isr */ void _int_unexpected_isr ( void *parameter ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _GET_KERNEL_DATA(kernel_data); td_ptr = kernel_data->ACTIVE_PTR; #if MQXCFG_PRINT_MEM_DUMP #error "MQXCFG_PRINT_MEM_DUMP functionality is currently not supported. This feature will be supported again in future release.\ Please set MQXCFG_PRINT_MEM_DUMP to zero." #endif #if MQXCFG_PRINT_MEM_DUMP { unsigned int psp, msp, i; printf("\n\r*** UNHANDLED INTERRUPT ***\n\r"); printf("Vector #: 0x%02x Task Id: 0x%0x Td_ptr 0x%x\n\r", (unsigned int)parameter, (unsigned int)td_ptr->TASK_ID, (unsigned int)td_ptr); psp = __get_PSP(); msp = __get_MSP(); printf("PSP: 0x%08x MSP: 0x%08x PSR: 0x%08x\n\r", psp, msp, (unsigned int)__get_xPSR()); printf("\n\r\n\rMemory dump:\n\r"); for (i = 0; i < 32; i += 4) { printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", psp + i * 4, ((unsigned int*)psp)[i], ((unsigned int*)psp)[i + 1], ((unsigned int*)psp)[i + 2], ((unsigned int*)psp)[i + 3]); } printf("\n\r\n\rMemory dump:\n\r"); for (i = 0; i < 32; i += 4) { printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", msp + i * 4, ((unsigned int*)msp)[i], ((unsigned int*)msp)[i + 1], ((unsigned int*)msp)[i + 2], ((unsigned int*)msp)[i + 3]); } } #endif /* MQXCFG_PRINT_MEM_DUMP */ _INT_DISABLE(); if (td_ptr->STATE != UNHANDLED_INT_BLOCKED) { td_ptr->STATE = UNHANDLED_INT_BLOCKED; td_ptr->INFO = (_mqx_uint)parameter; _QUEUE_UNLINK(td_ptr); } /* Endif */ _INT_ENABLE(); } /* Endbody */
_mqx_uint _io_pcb_test ( /* The PCB pool in error */ pointer _PTR_ pool_in_error, /* The PCB in error */ pointer _PTR_ pcb_in_error ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; IO_PCB_POOL_STRUCT_PTR pool_ptr; _mqx_uint i; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); *pool_in_error = NULL; *pcb_in_error = NULL; _INT_DISABLE(); result = _queue_test((QUEUE_STRUCT_PTR)(&kernel_data->IO_PCB_POOLS), pool_in_error); if (result != MQX_OK) { _int_enable(); return(result); }/* Endif */ pool_ptr = (pointer)kernel_data->IO_PCB_POOLS.NEXT; for (i = 0; i < _queue_get_size((QUEUE_STRUCT_PTR)(&kernel_data->IO_PCB_POOLS)); i++) { if (pool_ptr->VALID != IO_PCB_VALID) { /* START CR 2062 */ _int_enable(); /* END CR 2062 */ *pool_in_error = (pointer)pool_ptr; return(IO_PCB_POOL_INVALID); }/* Endif */ pool_ptr = (pointer)pool_ptr->QUEUE.NEXT; } /* Endfor */ /* START CR 2062 */ _int_enable(); /* END CR 2062 */ return(MQX_OK); } /* Endbody */
_mqx_uint _event_clear ( /* [IN] - An event handle returned from a call to _event_open() or ** _event_open_fast() */ pointer users_event_ptr, /* [IN] - bit mask, each bit of which represents an event. */ _mqx_uint bit_mask ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; register EVENT_CONNECTION_STRUCT_PTR event_connection_ptr; register EVENT_STRUCT_PTR event_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_event_clear, users_event_ptr, bit_mask); event_connection_ptr = (EVENT_CONNECTION_STRUCT_PTR)users_event_ptr; #if MQX_CHECK_VALIDITY if (event_connection_ptr->VALID != EVENT_VALID){ _KLOGX2(KLOG_event_clear, EVENT_INVALID_EVENT_HANDLE); return(EVENT_INVALID_EVENT_HANDLE); } /* Endif */ #endif _INT_DISABLE(); event_ptr = event_connection_ptr->EVENT_PTR; #if MQX_CHECK_VALIDITY if (event_ptr->VALID != EVENT_VALID) { _int_enable(); _KLOGX2(KLOG_event_clear, EVENT_INVALID_EVENT); return(EVENT_INVALID_EVENT); } /* Endif */ #endif event_ptr->EVENT &= ~bit_mask; _INT_ENABLE(); _KLOGX2(KLOG_event_clear, MQX_OK); return(MQX_OK); } /* Endbody */
void _int_unexpected_isr ( /* [IN] the parameter passed to the default ISR, the vector */ pointer parameter ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; //PSP_INT_CONTEXT_STRUCT_PTR exception_frame_ptr; uint_32 psp, msp, i; _GET_KERNEL_DATA(kernel_data); td_ptr = kernel_data->ACTIVE_PTR; //exception_frame_ptr = kernel_data->INTERRUPT_CONTEXT_PTR; printf("\n\r*** UNHANDLED INTERRUPT ***\n\r"); printf("Vector #: 0x%02x Task Id: 0x%0x Td_ptr 0x%x\n\r", (uint_32)parameter, (uint_32)td_ptr->TASK_ID, (uint_32)td_ptr); psp = __get_PSP(); msp = __get_MSP(); printf("PC: 0x%08x LR: 0x%08x PSP: 0x%08x MSP: 0x%08x PSR: 0x%08x\n\r", __get_PC(), __get_LR(), psp, msp, __get_PSR()); printf("\n\r\n\rMemory dump:\n\r"); for (i = 0; i < 32; i += 4) { printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", psp + i * 4, ((uint_32*)psp)[i], ((uint_32*)psp)[i + 1], ((uint_32*)psp)[i + 2], ((uint_32*)psp)[i + 3]); } printf("\n\r\n\rMemory dump:\n\r"); for (i = 0; i < 32; i += 4) { printf("0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n\r", msp + i * 4, ((uint_32*)msp)[i], ((uint_32*)msp)[i + 1], ((uint_32*)msp)[i + 2], ((uint_32*)msp)[i + 3]); } _INT_ENABLE(); if (td_ptr->STATE != UNHANDLED_INT_BLOCKED) { td_ptr->STATE = UNHANDLED_INT_BLOCKED; td_ptr->INFO = (_mqx_uint)parameter; _QUEUE_UNLINK(td_ptr); } /* Endif */ _INT_DISABLE(); } /* Endbody */
void _time_get_elapsed_ticks ( /* [IN/OUT] the address where the time is to be put */ MQX_TICK_STRUCT_PTR tick_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; #if MQX_CHECK_ERRORS if ( tick_ptr == NULL ) { return; } /* Endif */ #endif _GET_KERNEL_DATA(kernel_data); _INT_DISABLE(); *tick_ptr = kernel_data->TIME; /* Start CR 1082*/ if (kernel_data->GET_HWTICKS) { // The hardware clock may have counted passed it's reference // and have an interrupt pending. Thus, HW_TICKS may exceed // kernel_data->HW_TICKS_PER_TICK and this tick_ptr may need // normalizing. This is done in a moment. tick_ptr->HW_TICKS = (*kernel_data->GET_HWTICKS) (kernel_data->GET_HWTICKS_PARAM); } /* Endif */ _INT_ENABLE(); // The timer ISR may go off and increment kernel_data->TIME // The tick_ptr->HW_TICKS value might exceed the // kernel_data->HW_TICKS_PER_TICK and need to be // normalized for the PSP. PSP_NORMALIZE_TICKS(tick_ptr); /* End CR 1082*/ } /* Endbody */
/*! * \brief Writes to the lightweight log. * * This function writes the log entry only if it returns MQX_OK. * * \param[in] log_number Log number of a previously created lightweight log. * \param[in] p1 Data to be written to the log entry. If log_number is 0 * and p1 is >= 10 (0 through 9 are reserved for MQX), data specified by p2 through * p7 is written to kernel log. * \param[in] p2 Data to be written into the log entry. * \param[in] p3 Data to be written into the log entry. * \param[in] p4 Data to be written into the log entry. * \param[in] p5 Data to be written into the log entry. * \param[in] p6 Data to be written into the log entry. * \param[in] p7 Data to be written into the log entry. * * \return MQX_OK * \return LOG_FULL (Log is full and LOG_OVERWRITE is not set.) * \return LOG_DISABLED (Log is disabled.) * \return LOG_INVALID (Log_number is out of range.) * \return LOG_DOES_NOT_EXIST (Log_number was not created.) * \return MQX_INVALID_COMPONENT_HANDLE (Log component data is not valid.) * \return MQX_COMPONENT_DOES_NOT_EXIST (Log component is not created.) * * \see _lwlog_create * \see _lwlog_create_at * \see _lwlog_read * \see _lwlog_disable * \see _lwlog_enable */ _mqx_uint _lwlog_write ( _mqx_uint log_number, _mqx_max_type p1, _mqx_max_type p2, _mqx_max_type p3, _mqx_max_type p4, _mqx_max_type p5, _mqx_max_type p6, _mqx_max_type p7 ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (log_number >= LOG_MAXIMUM_NUMBER) { return (LOG_INVALID); } /* Endif */ if (kernel_data->KERNEL_COMPONENTS[KERNEL_LWLOG] == NULL) { return (MQX_COMPONENT_DOES_NOT_EXIST); } /* Endif */ #endif _INT_DISABLE(); result = _lwlog_write_internal(log_number, p1, p2, p3, p4, p5, p6, p7); _INT_ENABLE(); return (result); } /* Endbody */
pointer _mem_alloc_system_zero_uncached ( /* [IN] the size of the memory block */ _mem_size size ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; pointer result; _mqx_uint error; _GET_KERNEL_DATA(kernel_data); //_KLOGE2(KLOG_mem_alloc_system_zero_uncached, size); _INT_DISABLE(); result = _mem_alloc_internal(size, SYSTEM_TD_PTR(kernel_data), (MEMPOOL_STRUCT_PTR)&kernel_data->UNCACHED_POOL, &error); /* update the memory allocation pointer in case a lower priority ** task was preempted inside _mem_alloc_internal */ kernel_data->UNCACHED_POOL.POOL_ALLOC_CURRENT_BLOCK = kernel_data->UNCACHED_POOL.POOL_FREE_LIST_PTR; _INT_ENABLE(); #if MQX_CHECK_ERRORS if (error != MQX_OK) { _task_set_error(error); } /* Endif */ #endif if (result != NULL) { _mem_zero(result, size); } /* Endif */ //_KLOGX3(KLOG_mem_alloc_system_zero_uncached, result, kernel_data->UNCACHED_POOL.POOL_BLOCK_IN_ERROR); return(result); }
/*! * \brief Writes data to the log. * * The function writes the log entry only if it returns MQX_OK. * * \param[in] log_number Log number of a previously created log. * \param[in] number_of_parameters Number of parameters to write. * * \return MQX_OK * \return MQX_COMPONENT_DOES_NOT_EXIST (Log component is not created.) * \return MQX_INVALID_COMPONENT_HANDLE (Log component data is not valid.) * \return LOG_INVALID (Log_number is out of range.) * \return LOG_DOES_NOT_EXIST (Log_number was not created.) * \return LOG_DISABLED (Log is disabled.) * \return LOG_FULL (Log is full and LOG_OVERWRITE is not set.) */ _mqx_uint _log_write ( _mqx_uint log_number, _mqx_uint number_of_parameters, ... ) { /* Body */ MQX_TICK_STRUCT ticks; TIME_STRUCT time; KERNEL_DATA_STRUCT_PTR kernel_data; LOG_COMPONENT_STRUCT_PTR log_component_ptr; LOG_HEADER_STRUCT_PTR log_header_ptr; _mqx_uint_ptr data_ptr; va_list param_ptr; _mqx_uint us; _mqx_uint i; _mqx_uint size; _mqx_uint old_size; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (kernel_data->KERNEL_COMPONENTS[KERNEL_LOG] == NULL) { return(MQX_COMPONENT_DOES_NOT_EXIST); } /* Endif */ #endif log_component_ptr = (LOG_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_LOG]; #if MQX_CHECK_VALIDITY if (log_component_ptr->VALID != LOG_VALID) { return(MQX_INVALID_COMPONENT_HANDLE); } /* Endif */ #endif #if MQX_CHECK_ERRORS if (log_number >= LOG_MAXIMUM_NUMBER) { return(LOG_INVALID); } /* Endif */ #endif log_header_ptr = log_component_ptr->LOGS[log_number]; #if MQX_CHECK_ERRORS if (log_header_ptr == NULL) { return(LOG_DOES_NOT_EXIST); } /* Endif */ #endif if (! (log_header_ptr->FLAGS & LOG_ENABLED)) { return(LOG_DISABLED); } /* Endif */ size = sizeof(LOG_ENTRY_STRUCT)/sizeof(_mqx_uint) + number_of_parameters; #if MQX_CHECK_ERRORS if (size > log_header_ptr->MAX) { /* * The request is to log an entry larger than the * entire log. Reject this. */ return(LOG_FULL); } /* Endif */ #endif va_start(param_ptr, number_of_parameters); i = number_of_parameters + 1; _INT_DISABLE(); if ((log_header_ptr->SIZE + size) > log_header_ptr->MAX) { if (log_header_ptr->FLAGS & LOG_OVERWRITE) { /* Remove leading elements until it can fit */ while ((log_header_ptr->SIZE + size) > log_header_ptr->MAX) { data_ptr = log_header_ptr->LOG_READ; old_size = *data_ptr; log_header_ptr->SIZE -= old_size; data_ptr += old_size; if (data_ptr >= log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START + (data_ptr - log_header_ptr->LOG_END); } /* Endif */ if (log_header_ptr->LOG_NEXT == log_header_ptr->LOG_READ) { /* Move up the next read pointer */ log_header_ptr->LOG_NEXT = data_ptr; } /* Endif */ log_header_ptr->LOG_READ = data_ptr; } /* Endwhile */ } else { _INT_ENABLE(); va_end(param_ptr); return(LOG_FULL); } /* Endif */ } /* Endif */ log_header_ptr->SIZE += size; data_ptr = log_header_ptr->LOG_WRITE; log_header_ptr->LAST_LOG = data_ptr; *data_ptr++ = size; if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ *data_ptr++ = log_header_ptr->NUMBER++; if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ us = (_mqx_uint)_time_get_microseconds(); PSP_ADD_TICKS(&kernel_data->TIME, &kernel_data->TIME_OFFSET, &ticks); PSP_TICKS_TO_TIME(&ticks, &time); #if MQX_INT_SIZE_IN_BITS >= 32 *data_ptr++ = (_mqx_uint)time.SECONDS; #else #if PSP_ENDIAN == MQX_BIG_ENDIAN *data_ptr++ = (_mqx_uint)((time.SECONDS >> MQX_INT_SIZE_IN_BITS) & MAX_MQX_UINT); if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ *data_ptr++ = (_mqx_uint)(time.SECONDS & MAX_MQX_UINT); #else *data_ptr++ = (_mqx_uint)(time.SECONDS & MAX_MQX_UINT); if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ *data_ptr++ = (_mqx_uint)((time.SECONDS >> MQX_INT_SIZE_IN_BITS) & MAX_MQX_UINT); #endif #endif if (data_ptr >= log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ #if PSP_MEMORY_ADDRESSING_CAPABILITY >= 32 *data_ptr++ = time.MILLISECONDS; if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ *data_ptr++ = us; #elif MQX_INT_SIZE_IN_BITS == 32 #if PSP_ENDIAN == MQX_LITTLE_ENDIAN *data_ptr++ = time.MILLISECONDS | (us << 16); #else *data_ptr++ = us | (time.MILLISECONDS << 16); #endif #else *data_ptr++ = (_mqx_uint)time.MILLISECONDS; if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ *data_ptr++ = us; #endif if (data_ptr >= log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ while (--i) { *data_ptr++ = (_mqx_uint)va_arg(param_ptr, _mqx_uint); if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ } /* Endwhile */ log_header_ptr->LOG_WRITE = data_ptr; _INT_ENABLE(); va_end(param_ptr); return(MQX_OK); } /* Endbody */
void _time_notify_kernel ( void ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; register TD_STRUCT_PTR td_ptr; register TD_STRUCT_PTR next_td_ptr; register _mqx_uint count; register _mqx_int result; _GET_KERNEL_DATA(kernel_data); /* ** Update the current time. */ PSP_INC_TICKS(&kernel_data->TIME); _INT_DISABLE(); if (kernel_data->GET_HWTICKS) { // The hardware clock may have counted passed it's reference // and have an interrupt pending. Thus, HW_TICKS may exceed // kernel_data->HW_TICKS_PER_TICK and this tick_ptr may need // normalizing. This is done in a moment. kernel_data->TIME.HW_TICKS = (*kernel_data->GET_HWTICKS) (kernel_data->GET_HWTICKS_PARAM); } /* Endif */ // The tick_ptr->HW_TICKS value might exceed the // kernel_data->HW_TICKS_PER_TICK and need to be // normalized for the PSP. PSP_NORMALIZE_TICKS(&kernel_data->TIME); /* ** Check for tasks on the timeout queue, and wake the appropriate ** ones up. The timeout queue is a time-priority queue. */ count = _QUEUE_GET_SIZE(&kernel_data->TIMEOUT_QUEUE); if (count) { td_ptr = (TD_STRUCT_PTR)((pointer)kernel_data->TIMEOUT_QUEUE.NEXT); ++count; while ( --count ) { next_td_ptr = td_ptr->TD_NEXT; result = PSP_CMP_TICKS(&kernel_data->TIME, &td_ptr->TIMEOUT); if (result >= 0) { --kernel_data->TIMEOUT_QUEUE.SIZE; _QUEUE_UNLINK(td_ptr); td_ptr->STATE &= ~IS_ON_TIMEOUT_Q; if (td_ptr->STATE & TD_IS_ON_AUX_QUEUE) { td_ptr->STATE &= ~TD_IS_ON_AUX_QUEUE; _QUEUE_REMOVE(td_ptr->INFO, &td_ptr->AUX_QUEUE); } /* Endif */ _TASK_READY(td_ptr, kernel_data); } else { break; /* No more to do */ } /* Endif */ td_ptr = next_td_ptr; } /* Endwhile */ } /* Endif */ #if MQX_HAS_TIME_SLICE /* ** Check if the currently running task is a time slice task ** and if its time has expired, put it at the end of its queue */ td_ptr = kernel_data->ACTIVE_PTR; if ( td_ptr->FLAGS & MQX_TIME_SLICE_TASK ) { PSP_INC_TICKS(&td_ptr->CURRENT_TIME_SLICE); if (! (td_ptr->FLAGS & TASK_PREEMPTION_DISABLED) ) { result = PSP_CMP_TICKS(&td_ptr->CURRENT_TIME_SLICE, &td_ptr->TIME_SLICE); if ( result >= 0 ) { _QUEUE_UNLINK(td_ptr); _TASK_READY(td_ptr,kernel_data); } /* Endif */ } /* Endif */ } /* Endif */ #endif _INT_ENABLE(); #if MQX_USE_TIMER /* If the timer component needs servicing, call its ISR function */ if (kernel_data->TIMER_COMPONENT_ISR != NULL) { (*kernel_data->TIMER_COMPONENT_ISR)(); }/* Endif */ #endif #if MQX_USE_LWTIMER /* If the lwtimer needs servicing, call its ISR function */ if (kernel_data->LWTIMER_ISR != NULL) { (*kernel_data->LWTIMER_ISR)(); }/* Endif */ #endif } /* Endbody */
_mqx_uint _lwsem_wait_ticks ( /* [IN] the semaphore address */ LWSEM_STRUCT_PTR sem_ptr, /* [IN] the number of ticks to delay, if 0, delay forever */ _mqx_uint time_in_ticks ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _mqx_uint result; #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwsem_wait_ticks(sem_ptr, time_in_ticks); } #endif _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwsem_wait_ticks, sem_ptr, time_in_ticks); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwsem_wait_ticks, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif #if MQX_CHECK_VALIDITY if (sem_ptr->VALID != LWSEM_VALID) { _KLOGX2(KLOG_lwsem_wait_ticks, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ #endif _INT_DISABLE(); if (sem_ptr->VALUE <= 0) { td_ptr = kernel_data->ACTIVE_PTR; if (time_in_ticks == 0) { td_ptr->STATE = LWSEM_BLOCKED; td_ptr->INFO = (_mqx_uint)&sem_ptr->TD_QUEUE; _QUEUE_UNLINK(td_ptr); _QUEUE_ENQUEUE(&sem_ptr->TD_QUEUE, &td_ptr->AUX_QUEUE); _sched_execute_scheduler_internal(); /* Let the other tasks run */ /* Another task has posted a semaphore, and it has been tranfered to this ** task. */ result = MQX_OK; } else { PSP_ADD_TICKS_TO_TICK_STRUCT(&kernel_data->TIME, time_in_ticks, &td_ptr->TIMEOUT); result = _lwsem_wait_timed_internal(sem_ptr, td_ptr); } /* Endif */ } else { --sem_ptr->VALUE; /* Start CR 788 */ result = MQX_OK; /* End CR 788 */ } /* Endif */ //#if MQX_COMPONENT_DESTRUCTION /* We must check for component destruction */ if (sem_ptr->VALID != LWSEM_VALID) { _int_enable(); /* The semaphore has been deleted */ _KLOGX2(KLOG_lwsem_wait_ticks, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ //#endif _INT_ENABLE(); _KLOGX2(KLOG_lwsem_wait_ticks, result); return(result); }
/*! * \brief Used by a task to set the specified event bits in an event. * * \param[in] event_ptr Pointer to the lightweight event to set bits in. * \param[in] bit_mask Bit mask. Each bit represents an event bit to be set. * * \return MQX_OK * \return MQX_LWEVENT_INVALID (Lightweight event was invalid.) * * \see _lwevent_create * \see _lwevent_destroy * \see _lwevent_set_auto_clear * \see _lwevent_clear * \see _lwevent_test * \see _lwevent_wait_for * \see _lwevent_wait_ticks * \see _lwevent_wait_until * \see _lwevent_get_signalled * \see LWEVENT_STRUCT */ _mqx_uint _lwevent_set ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint bit_mask ) { KERNEL_DATA_STRUCT_PTR kernel_data; QUEUE_ELEMENT_STRUCT_PTR q_ptr; QUEUE_ELEMENT_STRUCT_PTR next_q_ptr; TD_STRUCT_PTR td_ptr; _mqx_uint set_bits; #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwevent_set(event_ptr, bit_mask); } #endif _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwevent_set, event_ptr, bit_mask); _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); _KLOGX2(KLOG_lwevent_set, MQX_LWEVENT_INVALID); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif set_bits = event_ptr->VALUE | bit_mask; if (_QUEUE_GET_SIZE(&event_ptr->WAITING_TASKS)) { /* Schedule waiting task(s) to run if bits ok */ q_ptr = event_ptr->WAITING_TASKS.NEXT; while (q_ptr != (QUEUE_ELEMENT_STRUCT_PTR) ((void *) &event_ptr->WAITING_TASKS)) { td_ptr = (void *) q_ptr; _BACKUP_POINTER(td_ptr, TD_STRUCT, AUX_QUEUE); next_q_ptr = q_ptr->NEXT; if (((td_ptr->FLAGS & TASK_LWEVENT_ALL_BITS_WANTED) && ((td_ptr->LWEVENT_BITS & set_bits) == td_ptr->LWEVENT_BITS)) || ((!(td_ptr->FLAGS & TASK_LWEVENT_ALL_BITS_WANTED)) && (td_ptr->LWEVENT_BITS & set_bits))) { _QUEUE_REMOVE(&event_ptr->WAITING_TASKS, q_ptr); _TIME_DEQUEUE(td_ptr, kernel_data); td_ptr->INFO = 0; _TASK_READY(td_ptr, kernel_data); /* store information about which bits caused task to be unblocked */ td_ptr->LWEVENT_BITS &= set_bits; set_bits &= ~(event_ptr->AUTO & td_ptr->LWEVENT_BITS); } /* Endif */ q_ptr = next_q_ptr; } /* Endwhile */ } /* Endif */ event_ptr->VALUE = set_bits; _INT_ENABLE(); /* May need to let higher priority task run */ _CHECK_RUN_SCHEDULER(); _KLOGX2(KLOG_lwevent_set, MQX_OK); return (MQX_OK); }
/*! * \brief Allocates a message from the private message pool. * * The size of the message is determined by the message size that a task * specified when it called _msgpool_create(). The message is a resource of the * task until the task either frees it (_msg_free()) or puts it on a message * queue (_msgq_send() family of functions.) * * \param[in] pool A pool ID from _msgpool_create(). * * \return Pointer to a message (Success.) * \return NULL (Failure.) * * \warning On failure, calls _task_set_error() to set one the following task * error codes: * \li MQX_COMPONENT_DOES_NOT_EXIST (Message component is not created.) * \li MSGPOOL_INVALID_POOL_ID (Pool_id is not valid.) * \li MSGPOOL_OUT_OF_MESSAGES (All the messages in the pool are allocated.) * \li Task error codes from _mem_alloc_system() (If MQX needs to grow the pool.) * * \see _msg_alloc_system * \see _msg_free * \see _msgpool_create * \see _msgpool_destroy * \see _task_set_error * \see _mem_alloc * \see _mem_alloc_from * \see _mem_alloc_system * \see _mem_alloc_system_from * \see _mem_alloc_system_zero * \see _mem_alloc_system_zero_from * \see _mem_alloc_zero * \see _mem_alloc_zero_from * \see _mem_alloc_align * \see _mem_alloc_align_from * \see _mem_alloc_at * \see MESSAGE_HEADER_STRUCT */ pointer _msg_alloc ( _pool_id pool ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; #if MQX_CHECK_ERRORS MSG_COMPONENT_STRUCT_PTR msg_component_ptr; #endif register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MESSAGE_HEADER_STRUCT_PTR message_ptr; register MSGPOOL_STRUCT_PTR msgpool_ptr; uint_16 grow_number; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_msg_alloc, pool); #if MQX_CHECK_ERRORS msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); if (msg_component_ptr == NULL) { _task_set_error(MQX_COMPONENT_DOES_NOT_EXIST); _KLOGX3(KLOG_msg_alloc, NULL, MQX_COMPONENT_DOES_NOT_EXIST); return(NULL); } /* Endif */ #endif message_ptr = NULL; msgpool_ptr = (MSGPOOL_STRUCT_PTR)pool; #if MQX_CHECK_VALIDITY || MQX_CHECK_ERRORS if ( #if MQX_CHECK_VALIDITY (msgpool_ptr->VALID != MSG_VALID) #if MQX_CHECK_ERRORS || #endif #endif #if MQX_CHECK_ERRORS (msgpool_ptr->MSGPOOL_TYPE != MSG_POOL) #endif ) { _task_set_error(MSGPOOL_INVALID_POOL_ID); _KLOGX3(KLOG_msg_alloc, message_ptr, MSGPOOL_INVALID_POOL_ID); return (message_ptr); } /* Endif */ #endif if ( (msgpool_ptr->SIZE == 0) && (msgpool_ptr->GROW_NUMBER) && ( (msgpool_ptr->MAX < msgpool_ptr->GROW_LIMIT) || (msgpool_ptr->GROW_LIMIT == 0) ) ) { /* Attempt to add elements to the pool */ grow_number = msgpool_ptr->GROW_NUMBER; if (grow_number > (uint_16)(msgpool_ptr->GROW_LIMIT - msgpool_ptr->MAX)) { grow_number = msgpool_ptr->GROW_LIMIT - msgpool_ptr->MAX; } /* Endif */ _msgpool_add_internal(msgpool_ptr, grow_number); } /* Endif */ _INT_DISABLE(); imsg_ptr = msgpool_ptr->MSG_FREE_LIST_PTR; if (imsg_ptr == NULL) { _int_enable(); _task_set_error(MSGPOOL_OUT_OF_MESSAGES); _KLOGX3(KLOG_msg_alloc, message_ptr, MSGPOOL_OUT_OF_MESSAGES); return((pointer)message_ptr); } /* Endif */ msgpool_ptr->MSG_FREE_LIST_PTR = imsg_ptr->NEXT; --msgpool_ptr->SIZE; _INT_ENABLE(); imsg_ptr->FREE = FALSE; imsg_ptr->QUEUED = FALSE; if (kernel_data->IN_ISR) { imsg_ptr->TD_PTR = NULL; } else { imsg_ptr->TD_PTR = kernel_data->ACTIVE_PTR; } /* Endif */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)&imsg_ptr->MESSAGE; message_ptr->TARGET_QID = MSGQ_NULL_QUEUE_ID; message_ptr->SOURCE_QID = MSGQ_NULL_QUEUE_ID; message_ptr->SIZE = msgpool_ptr->MESSAGE_SIZE; message_ptr->CONTROL = MSG_HDR_ENDIAN | MSG_DATA_ENDIAN; _KLOGX3(KLOG_msg_alloc, message_ptr, MQX_OK); return (pointer)message_ptr; } /* Endbody */
_mqx_uint _event_set ( /* [IN] - An event handle returned from _event_open or _event_open_fast */ pointer users_event_ptr, /* [IN] - bit mask, each bit of which represents an event. */ _mqx_uint bit_mask ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; EVENT_STRUCT_PTR event_ptr; EVENT_COMPONENT_STRUCT_PTR event_component_ptr; EVENT_CONNECTION_STRUCT_PTR conn_ptr; EVENT_CONNECTION_STRUCT_PTR next_conn_ptr; EVENT_CONNECTION_STRUCT_PTR event_connection_ptr; TD_STRUCT_PTR new_td_ptr; _mqx_uint set_bits; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_event_set, users_event_ptr, bit_mask); event_connection_ptr = (EVENT_CONNECTION_STRUCT_PTR)users_event_ptr; #if MQX_CHECK_VALIDITY if (event_connection_ptr->VALID != EVENT_VALID){ _KLOGX2(KLOG_event_set, EVENT_INVALID_EVENT_HANDLE); return(EVENT_INVALID_EVENT_HANDLE); } /* Endif */ #endif event_component_ptr = (EVENT_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_EVENTS]; #if MQX_CHECK_ERRORS if (event_component_ptr == NULL){ _KLOGX2(KLOG_event_set, MQX_COMPONENT_DOES_NOT_EXIST); return(MQX_COMPONENT_DOES_NOT_EXIST); } /* Endif */ #endif #if MQX_CHECK_VALIDITY if (event_component_ptr->VALID != EVENT_VALID){ _KLOGX2(KLOG_event_set, MQX_INVALID_COMPONENT_BASE); return(MQX_INVALID_COMPONENT_BASE); } /* Endif */ #endif #if MQX_IS_MULTI_PROCESSOR if (event_connection_ptr->REMOTE_CPU) { if (kernel_data->IPC) { /* This open is for a remote processor */ (*kernel_data->IPC)(TRUE, event_connection_ptr->REMOTE_CPU, KERNEL_EVENTS, IPC_EVENT_SET, 2, event_connection_ptr->EVENT_PTR, bit_mask); _KLOGX2(KLOG_event_set, kernel_data->ACTIVE_PTR->TASK_ERROR_CODE); return(kernel_data->ACTIVE_PTR->TASK_ERROR_CODE); } else { _KLOGX2(KLOG_event_set, EVENT_NOT_FOUND); return(EVENT_NOT_FOUND); }/* Endif */ }/* Endif */ #endif _INT_DISABLE(); event_ptr = event_connection_ptr->EVENT_PTR; #if MQX_CHECK_VALIDITY if (event_ptr->VALID != EVENT_VALID) { _INT_ENABLE(); _KLOGX2(KLOG_event_set, EVENT_INVALID_EVENT); return(EVENT_INVALID_EVENT); } /* Endif */ #endif set_bits = event_ptr->EVENT | bit_mask; if (_QUEUE_GET_SIZE(&event_ptr->WAITING_TASKS)) { /* Schedule waiting task(s) to run if bits ok */ conn_ptr = (EVENT_CONNECTION_STRUCT_PTR) ((pointer)event_ptr->WAITING_TASKS.NEXT); while (conn_ptr != (EVENT_CONNECTION_STRUCT_PTR) ((pointer)&event_ptr->WAITING_TASKS)) { next_conn_ptr = (EVENT_CONNECTION_STRUCT_PTR)conn_ptr->NEXT; if (((conn_ptr->FLAGS & EVENT_WANTS_ALL) && ((conn_ptr->MASK & set_bits) == conn_ptr->MASK)) || ((!(conn_ptr->FLAGS & EVENT_WANTS_ALL)) && (conn_ptr->MASK & set_bits))) { new_td_ptr = conn_ptr->TD_PTR; if ((new_td_ptr->STATE & STATE_MASK) == EVENT_BLOCKED) { /* He may have timed out */ conn_ptr->FLAGS |= EVENT_OCCURRED; _TIME_DEQUEUE(new_td_ptr, kernel_data); _TASK_READY(new_td_ptr, kernel_data); /* Only ready one task if event is an auto clear event */ if (event_ptr->AUTO_CLEAR) { set_bits &= ~conn_ptr->MASK; break; } /* Endif */ } /* Endif */ } /* Endif */ conn_ptr = next_conn_ptr; } /* Endwhile */ } /* Endif */ event_ptr->EVENT = set_bits; _INT_ENABLE(); /* May need to let higher priority task run */ _CHECK_RUN_SCHEDULER(); _KLOGX2(KLOG_event_set, MQX_OK); return(MQX_OK); } /* Endbody */
MESSAGE_HEADER_STRUCT_PTR _msgq_receive_internal ( /* [IN] id of the queue from which a message is to be received */ _queue_id queue_id, /* [IN] indication of the number of ticks which can expire before ** this request times out */ MQX_TICK_STRUCT_PTR timeout_tick_ptr, /* [IN] relative or absolute time specified in tick_ptr */ _mqx_uint mode, /* [OUT] where the error code is to be stored */ _mqx_uint_ptr error_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MSG_COMPONENT_STRUCT_PTR msg_component_ptr; register TD_STRUCT_PTR td_ptr; MESSAGE_HEADER_STRUCT_PTR message_ptr; register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MSGQ_STRUCT_PTR msgq_ptr; _queue_number queue; *error_ptr = MQX_OK; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _task_set_error(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); *error_ptr = MQX_CANNOT_CALL_FUNCTION_FROM_ISR; return(NULL); }/* Endif */ #endif msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); #if MQX_CHECK_ERRORS if (msg_component_ptr == NULL){ _task_set_error(MQX_COMPONENT_DOES_NOT_EXIST); *error_ptr = MQX_COMPONENT_DOES_NOT_EXIST; return(NULL); } /* Endif */ #endif message_ptr = NULL; td_ptr = kernel_data->ACTIVE_PTR; if (queue_id == MSGQ_ANY_QUEUE){ /* if queue_id is 0 than a receive from any queue is performed */ /* Does the task own a queue */ if (td_ptr->MSG_QUEUE_HEAD == NULL){ /* Does NOT */ _task_set_error(MSGQ_QUEUE_IS_NOT_OPEN); *error_ptr = MSGQ_QUEUE_IS_NOT_OPEN; return NULL; } /* Endif */ _INT_DISABLE(); if (td_ptr->MESSAGES_AVAILABLE == 0){ td_ptr->STATE = RCV_ANY_BLOCKED; td_ptr->INFO = queue_id; td_ptr->MESSAGE = NULL; if (mode == MSG_TIMEOUT_NONE) { _task_block(); } else if (mode == MSG_TIMEOUT_RELATIVE) { _time_delay_for(timeout_tick_ptr); } else { _time_delay_until(timeout_tick_ptr); } /* Endif */ /* ** SHORT CUT... ** The message send routine does not queue up a message in this case. ** the message is deposited directly into the task descriptor */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)td_ptr->MESSAGE; if (message_ptr == NULL){ /* A timeout has occurred */ #if MQXCFG_ENABLE_MSG_TIMEOUT_ERROR _task_set_error(MSGQ_MESSAGE_NOT_AVAILABLE); #endif } /* Endif */ td_ptr->MESSAGE = NULL; } else { /* Check all queues for an available entry .. There must be at least ** one entry available */ msgq_ptr = (MSGQ_STRUCT_PTR)td_ptr->MSG_QUEUE_HEAD; while (msgq_ptr != NULL){ if (msgq_ptr->NO_OF_ENTRIES){ /* dequeue the top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); break; } /* Endif */ msgq_ptr = msgq_ptr->NEXT_MSGQ_PTR; } /* Endwhile */ } /* Endif */ } else { /* RECEIVE from a specific qid */ queue = QUEUE_FROM_QID(queue_id); #if MQX_CHECK_ERRORS if ( (PROC_NUMBER_FROM_QID(queue_id) != kernel_data->INIT.PROCESSOR_NUMBER) || (! VALID_QUEUE(queue)) ) { _task_set_error(MSGQ_INVALID_QUEUE_ID); *error_ptr = MSGQ_INVALID_QUEUE_ID; return (pointer)message_ptr; } /* Endif */ #endif msgq_ptr = &msg_component_ptr->MSGQS_PTR[queue]; #if MQX_CHECK_ERRORS if ( msgq_ptr->QUEUE != queue ) { _task_set_error(MSGQ_QUEUE_IS_NOT_OPEN); *error_ptr = MSGQ_QUEUE_IS_NOT_OPEN; return message_ptr; } /* Endif */ if ( (msgq_ptr->TD_PTR != NULL) && (msgq_ptr->TD_PTR != td_ptr) ) { _task_set_error(MSGQ_NOT_QUEUE_OWNER); *error_ptr = MSGQ_NOT_QUEUE_OWNER; return message_ptr; } /* Endif */ #endif /* ** check the specified queue for an entry ** if not entry, then block until an entry is received or ** timeout occurs */ _INT_DISABLE(); if (msgq_ptr->NO_OF_ENTRIES == 0) { if (msgq_ptr->TD_PTR == NULL) { /* A system message queue, indicate none available */ message_ptr = NULL; } else { td_ptr->STATE = RCV_SPECIFIC_BLOCKED; td_ptr->INFO = queue; td_ptr->MESSAGE = NULL; if (mode == MSG_TIMEOUT_NONE) { _task_block(); } else if (mode == MSG_TIMEOUT_RELATIVE) { _time_delay_for(timeout_tick_ptr); } else { _time_delay_until(timeout_tick_ptr); } /* Endif */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)td_ptr->MESSAGE; if ( message_ptr == NULL ) { #if MQXCFG_ENABLE_MSG_TIMEOUT_ERROR _task_set_error(MSGQ_MESSAGE_NOT_AVAILABLE); #endif } else if ((message_ptr->TARGET_QID != queue_id) && (msgq_ptr->NO_OF_ENTRIES > 0)) { /* The original msg was swapped out in msgq_sendi() for a higher priority msg with a different target_qid. Enqueue this msg, and then dequeue the msg we need. */ register MSGQ_STRUCT_PTR tmp_msgq_ptr; register _queue_number tmp_queue; /* Get the msg's queue */ tmp_queue = QUEUE_FROM_QID(message_ptr->TARGET_QID); tmp_msgq_ptr = &msg_component_ptr->MSGQS_PTR[tmp_queue]; if ((tmp_msgq_ptr->MAX_ENTRIES == 0) || (tmp_msgq_ptr->NO_OF_ENTRIES < tmp_msgq_ptr->MAX_ENTRIES)) { /* the msg's queue has room */ imsg_ptr = GET_INTERNAL_MESSAGE_PTR(message_ptr); #if MQX_CHECK_ERRORS if (imsg_ptr->VALID != MSG_VALID){ /* An invalid message was input by the application. */ _task_set_error(MSGQ_INVALID_MESSAGE); message_ptr = NULL; } else #endif { /* enqueue the msg */ _msgq_insert_message_internal(tmp_msgq_ptr, imsg_ptr, TRUE); if (tmp_msgq_ptr->TD_PTR) { ++(tmp_msgq_ptr->TD_PTR->MESSAGES_AVAILABLE); } /* Endif */ /* now dequeue our queue's top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); } } else { /* Queue full, error - this should not happen since msgq_sendi() checks for room on the queue for all msgs, including short-cut msgs. */ _task_set_error(MSGQ_QUEUE_FULL); message_ptr = NULL; } } /* Endif */ td_ptr->MESSAGE = NULL; } /* Endif */ } else { /* dequeue the top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); } /* Endif */ } /* Endif */ _INT_ENABLE(); return message_ptr; } /* Endbody */
boolean _msgq_send_internal ( /* [IN] pointer to the message being sent by application */ MESSAGE_HEADER_STRUCT_PTR msg_ptr, /* [IN] is the calling task to be blocked after the call */ boolean blocking, /* [IN] the queue to put the message onto */ _queue_id target_qid ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MSG_COMPONENT_STRUCT_PTR msg_component_ptr; register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MSGQ_STRUCT_PTR msgq_ptr; register TD_STRUCT_PTR td_ptr; MESSAGE_HEADER_STRUCT_PTR tmp_msg_ptr; register _mqx_uint state; register _queue_number queue; register _processor_number pnum; /* Start CR 2191 */ boolean swapped_msg; /* End CR 2191 */ _GET_KERNEL_DATA(kernel_data); msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); #if MQX_CHECK_ERRORS if (msg_component_ptr == NULL){ _task_set_error(MQX_COMPONENT_DOES_NOT_EXIST); return(FALSE); } /* Endif */ if (msg_ptr == NULL) { _task_set_error(MSGQ_INVALID_MESSAGE); return(FALSE); } /* Endif */ #endif imsg_ptr = GET_INTERNAL_MESSAGE_PTR(msg_ptr); #if MQX_CHECK_ERRORS if (imsg_ptr->VALID != MSG_VALID){ /* An invalid message was input by the application. */ _task_set_error(MSGQ_INVALID_MESSAGE); return FALSE; } /* Endif */ #endif #if MQX_CHECK_ERRORS if (imsg_ptr->FREE || imsg_ptr->QUEUED){ /* Trying to send a free message, or one on a message queue. */ _task_set_error(MSGQ_INVALID_MESSAGE); return FALSE; } /* Endif */ #endif pnum = PROC_NUMBER_FROM_QID(target_qid); /* If processor number is zero then the message is for this processor */ if (pnum == 0) { /* Fix up the target QID in the message header */ msg_ptr->TARGET_QID = BUILD_QID(kernel_data->INIT.PROCESSOR_NUMBER, msg_ptr->TARGET_QID); } else if (pnum != kernel_data->INIT.PROCESSOR_NUMBER) { #if MQX_IS_MULTI_PROCESSOR IPC_MSG_ROUTING_COMPONENT_STRUCT_PTR ipc_msg_comp_ptr; ipc_msg_comp_ptr = (IPC_MSG_ROUTING_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_IPC_MSG_ROUTING]; if (ipc_msg_comp_ptr && ipc_msg_comp_ptr->MSG_ROUTER) { return( (*ipc_msg_comp_ptr->MSG_ROUTER)(pnum, msg_ptr, blocking)); } else { #endif _msg_free(msg_ptr); _task_set_error(MSGQ_INVALID_QUEUE_ID); return FALSE; #if MQX_IS_MULTI_PROCESSOR }/* Endif */ #endif } /* Endif */ queue = QUEUE_FROM_QID(target_qid); #if MQX_CHECK_ERRORS if ( ! VALID_QUEUE(queue)) { _msg_free(msg_ptr); _task_set_error(MSGQ_INVALID_QUEUE_ID); return FALSE; } /* Endif */ #endif msgq_ptr = &msg_component_ptr->MSGQS_PTR[queue]; if (msgq_ptr->QUEUE != queue) { msgq_ptr = NULL; } /* Endif */ #if MQX_CHECK_ERRORS if (msgq_ptr == NULL) { _msg_free(msg_ptr); _task_set_error(MSGQ_QUEUE_IS_NOT_OPEN); return FALSE; } /* Endif */ #endif _INT_DISABLE(); if ((msgq_ptr->MAX_ENTRIES == 0) || (msgq_ptr->NO_OF_ENTRIES < msgq_ptr->MAX_ENTRIES)) { /* End CR 2265 */ /* There is room on the queue, so add the msg. We need to check for room here even if the msg ends up being short-cutted to the receiver (via td_ptr->MESSAGE) in case msg_receive needs to enqueue the msg. */ if (msgq_ptr->TYPE == MSG_QUEUE) { /* THIS MESSAGE QUEUE IS ATTACHED TO A TASK */ /* check for pending receive ** if a receive is pending then satisfy the request ** and add the receiving task onto the ready-to-run queue */ td_ptr = msgq_ptr->TD_PTR; state = td_ptr->STATE & STATE_MASK; if ( (state == RCV_ANY_BLOCKED) || ((state == RCV_SPECIFIC_BLOCKED) && (td_ptr->INFO == queue))) { /* The task is blocked, waiting for a message */ td_ptr->MESSAGE = &imsg_ptr->MESSAGE; imsg_ptr->TD_PTR = td_ptr; _TIME_DEQUEUE(td_ptr,kernel_data); _TASK_READY(td_ptr,kernel_data); /* Now run the notification function */ if (msgq_ptr->NOTIFICATION_FUNCTION != NULL) { (*msgq_ptr->NOTIFICATION_FUNCTION)(msgq_ptr->NOTIFICATION_FUNCTION_PARAMETER); } /* Endif */ if (blocking) { if ( ! kernel_data->IN_ISR) { td_ptr = kernel_data->ACTIVE_PTR; td_ptr->STATE = SEND_BLOCKED; _task_block(); } /* Endif */ } else { /* ** if the highest priority ready task is not the ** same priority as the sending task, then a higher ** priority task was made ready and it has to be allowed ** to run. */ _CHECK_RUN_SCHEDULER(); /* Let a higher priority task run */ } /* Endif */ } else { /* The task is ready to run and pre-empted OR blocked and ** on a different queue. */ /* Start CR 2191 */ swapped_msg = FALSE; /* End CR 2191 */ if ((msg_ptr->CONTROL & MSG_PRIORITY_MASK) && (td_ptr->MESSAGE != NULL)) { /* Check the message in the TD */ tmp_msg_ptr = (MESSAGE_HEADER_STRUCT_PTR)td_ptr->MESSAGE; if ( (msg_ptr->CONTROL & MSG_HDR_URGENT) || /* Urgent messages first */ ( (! (tmp_msg_ptr->CONTROL & MSG_HDR_URGENT)) && /* Start CR 621 */ ( (_mqx_uint)(tmp_msg_ptr->CONTROL & MSG_HDR_PRIORITY_MASK) < (_mqx_uint)(msg_ptr->CONTROL & MSG_HDR_PRIORITY_MASK)) /* End CR 621 */ ) ) /* Higher priority messages first */ { /* Put new message into TD */ td_ptr->MESSAGE = msg_ptr; /* Start CR 2193 */ /* Set the new message's ownership to the receiving queue's TD */ imsg_ptr = GET_INTERNAL_MESSAGE_PTR(msg_ptr); imsg_ptr->TD_PTR = td_ptr; /* Old message which we pulled from TD, need to add to queue, below */ /* End CR 2193 */ msg_ptr = tmp_msg_ptr; imsg_ptr = GET_INTERNAL_MESSAGE_PTR(msg_ptr); /* Don't know the sender's TD for the swapped out msg, so set it to NULL; */ imsg_ptr->TD_PTR = NULL; /* Start CR 2191 */ /* Indicate that a swap occurred */ swapped_msg = TRUE; /* Set the queue to the swapped msg's queue. */ if (target_qid != msg_ptr->TARGET_QID) { queue = QUEUE_FROM_QID(msg_ptr->TARGET_QID); msgq_ptr = &msg_component_ptr->MSGQS_PTR[queue]; /* This msg's queue was not full when it was short-cut, so we should not get here. Check anyway. */ if ((msgq_ptr->MAX_ENTRIES != 0) && (msgq_ptr->NO_OF_ENTRIES >= msgq_ptr->MAX_ENTRIES)) { /* Queue full, error */ _INT_ENABLE(); _msg_free(msg_ptr); _task_set_error(MSGQ_QUEUE_FULL); return FALSE; } /* Endif */ } /* Endif */ } /* Endif */ } /* Endif */ /* add the message */ _msgq_insert_message_internal(msgq_ptr, imsg_ptr, swapped_msg); if (msgq_ptr->TD_PTR){ ++(msgq_ptr->TD_PTR->MESSAGES_AVAILABLE); } /* Endif */ /* Now run the notification function */ if (msgq_ptr->NOTIFICATION_FUNCTION != NULL) { (*msgq_ptr->NOTIFICATION_FUNCTION)(msgq_ptr->NOTIFICATION_FUNCTION_PARAMETER); } /* Endif */ if (blocking && ! kernel_data->IN_ISR ) { td_ptr = kernel_data->ACTIVE_PTR; td_ptr->STATE = SEND_BLOCKED; _task_block(); } /* Endif */ } /* Endif */ } else { /* THIS IS A SYSTEM QUEUE NOT ATTACHED TO A TASK */ /* add the message to the queue */ _msgq_insert_message_internal(msgq_ptr, imsg_ptr, FALSE); /* Run the notification function. */ if ( msgq_ptr->NOTIFICATION_FUNCTION != NULL ) { (*msgq_ptr->NOTIFICATION_FUNCTION)(msgq_ptr->NOTIFICATION_FUNCTION_PARAMETER); } /* Endif */ } /* Endif */ } else { /* Queue full, error */ _INT_ENABLE(); _task_set_error(MSGQ_QUEUE_FULL); _msg_free(&imsg_ptr->MESSAGE); return FALSE; } /* Endif */ _INT_ENABLE(); return TRUE; /* Message sent MQX_OK */ } /* Endbody */
/*! * \brief Gets the number of free messages in the message pool. * * The function fails if either: * \li Message component is not created. * \li Pool_id is for a private message pool, but does not represent a valid one. * * \param[in] pool One of the following: * \li Private message pool for which to get the number of free messages. * \li MSGPOOL_NULL_POOL_ID (for system message pools). * * \return The number of free messages in the private message pool (success). * \return The number of free messages in all system message pools (success). * \return 0 (Success: No free messages.) * \return 0 (Failure: see Description.) * * \warning If pool_id does not represent a valid private message pool, calls * _task_set_error() to set the task error code to MSGPOOL_INVALID_POOL_ID * * \see _msgpool_create * \see _msgpool_destroy * \see _msg_free * \see _msg_alloc_system * \see _task_set_error * \see _msg_create_component */ _mqx_uint _msg_available ( _pool_id pool ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MSG_COMPONENT_STRUCT_PTR msg_component_ptr; register MSGPOOL_STRUCT_PTR msgpool_ptr; _mqx_uint i; _mqx_uint count; _GET_KERNEL_DATA(kernel_data); msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); #if MQX_CHECK_ERRORS if (msg_component_ptr == NULL) { return(0); } /* Endif */ #endif msgpool_ptr = msg_component_ptr->MSGPOOLS_PTR; #if MQX_CHECK_ERRORS if (msgpool_ptr == NULL) { return(0); }/* Endif */ #endif if (pool == MSGPOOL_NULL_POOL_ID) { count = 0; _INT_DISABLE(); i = msg_component_ptr->MAX_MSGPOOLS_EVER + 1; while ( --i ) { if ( #if MQX_CHECK_VALIDITY (msgpool_ptr->VALID == MSG_VALID) && #endif (msgpool_ptr->MSGPOOL_TYPE == SYSTEM_MSG_POOL)) { count += msgpool_ptr->SIZE; } /* Endif */ ++msgpool_ptr; } /* Endwhile */ _INT_ENABLE(); return count; } else { msgpool_ptr = (MSGPOOL_STRUCT_PTR)pool; if ( #if MQX_CHECK_VALIDITY (msgpool_ptr->VALID != MSG_VALID) || #endif (msgpool_ptr->MSGPOOL_TYPE != MSG_POOL) ) { _task_set_error(MSGPOOL_INVALID_POOL_ID); return (0); } /* Endif */ return (_mqx_uint)msgpool_ptr->SIZE; } /* Endif */ } /* Endbody */
/*! * \brief Allocates a message from a system message pool. * * The size of the message is determined by the message size that a task * specified when it called _msgpool_create_system(). * \n The message is a resource of the task until the task either frees it * (_msg_free()) or puts it on a message queue (_msgq_send family of functions.) * * \param[in] message_size Maximum size (in single-addressable units) of the * message. * * \return Pointer to a message of at least message_size single-addressable * units (success). * \return NULL (Failure: message component is not created.) * * \warning On failure, calls _task_set_error() to set one of the following task * error codes: * \li MQX_COMPONENT_DOES_NOT_EXIST (Message component is not created.) * \li Task error codes from _mem_alloc_system() (If MQX needs to grow the pool.) * * \see _mem_alloc * \see _mem_alloc_from * \see _mem_alloc_system * \see _mem_alloc_system_from * \see _mem_alloc_system_zero * \see _mem_alloc_system_zero_from * \see _mem_alloc_zero * \see _mem_alloc_zero_from * \see _mem_alloc_align * \see _mem_alloc_align_from * \see _mem_alloc_at * \see _msg_alloc * \see _msg_free * \see _msgpool_create_system * \see _msgq_send * \see _task_set_error * \see MESSAGE_HEADER_STRUCT */ pointer _msg_alloc_system ( _msg_size message_size ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MSG_COMPONENT_STRUCT_PTR msg_component_ptr; register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MESSAGE_HEADER_STRUCT_PTR message_ptr; register MSGPOOL_STRUCT_PTR msgpool_ptr; uint_16 grow_number; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_msg_alloc_system, message_size ); msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); #if MQX_CHECK_ERRORS if (msg_component_ptr == NULL) { _task_set_error(MQX_COMPONENT_DOES_NOT_EXIST); _KLOGX2( KLOG_msg_alloc_system, NULL ); return(NULL); }/* Endif */ #endif message_ptr = NULL; _INT_DISABLE(); msgpool_ptr = msg_component_ptr->SMALLEST_MSGPOOL_PTR; while (msgpool_ptr != NULL) { if (msgpool_ptr->MESSAGE_SIZE >= message_size) { imsg_ptr = msgpool_ptr->MSG_FREE_LIST_PTR; if ( (imsg_ptr == NULL) && (msgpool_ptr->GROW_NUMBER) && (msgpool_ptr->MAX < msgpool_ptr->GROW_LIMIT) ) { /* Attempt to add elements to the pool */ grow_number = msgpool_ptr->GROW_NUMBER; if ( ((uint_16)(msgpool_ptr->MAX + grow_number) > msgpool_ptr->GROW_LIMIT)) { grow_number = msgpool_ptr->GROW_LIMIT - msgpool_ptr->MAX; } /* Endif */ _msgpool_add_internal(msgpool_ptr, grow_number); imsg_ptr = msgpool_ptr->MSG_FREE_LIST_PTR; } /* Endif */ if ( imsg_ptr != NULL ) { msgpool_ptr->MSG_FREE_LIST_PTR = imsg_ptr->NEXT; --msgpool_ptr->SIZE; _INT_ENABLE(); imsg_ptr->FREE = FALSE; imsg_ptr->QUEUED = FALSE; if (kernel_data->IN_ISR) { imsg_ptr->TD_PTR = NULL; } else { imsg_ptr->TD_PTR = kernel_data->ACTIVE_PTR; } /* Endif */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)&imsg_ptr->MESSAGE; message_ptr->TARGET_QID = MSGQ_NULL_QUEUE_ID; message_ptr->SOURCE_QID = MSGQ_NULL_QUEUE_ID; message_ptr->SIZE = message_size; message_ptr->CONTROL = MSG_HDR_ENDIAN | MSG_DATA_ENDIAN; _KLOGX2(KLOG_msg_alloc_system, message_ptr); return (pointer)message_ptr; } /* Endif */ } /* Endif */ msgpool_ptr = msgpool_ptr->NEXT_MSGPOOL_PTR; } /* Endwhile */ _int_enable(); _KLOGX2(KLOG_msg_alloc_system, message_ptr); return (pointer)message_ptr; } /* Endbody */
/*! * \brief Reads the data from the log. * * <table> * <tr> * <td><b>read_type</b></td> * <td><b>Returns this entry in the log:</b></td> * </tr> * <tr> * <td>LOG_READ_NEWEST</td> * <td>Newest.</td> * </tr> * <tr> * <td>LOG_READ_NEXT</td> * <td>Next one after the previous one read (must be used with LOG_READ_OLDEST).</td> * </tr> * <tr> * <td>LOG_READ_OLDEST</td> * <td>Oldest.</td> * </tr> * <tr> * <td>LOG_READ_OLDEST_AND_DELETE</td> * <td>Oldest and deletes it.</td> * </tr> * </table> * * \param[in] log_number Log number of a previously created log. * \param[in] read_type Type of read operation (see Description). * \param[in] size_to_read Maximum number of _mqx_uints (not including the entry * header) to be read from an entry. * \param[in] entry_ptr Where to write the log entry (any structure that * starts with LOG_STRUCT or LOG_ENTRY_STRUCT). * * \return MQX_OK * \return LOG_INVALID (Log_number is out of range.) * \return LOG_DOES_NOT_EXIST (Log_number was not created.) * \return LOG_ENTRY_NOT_AVAILABLE (Log entry is not available.) * \return LOG_INVALID_READ_TYPE (Read_type is not valid.) * \return MQX_COMPONENT_DOES_NOT_EXIST (Log component is not created.) * \return MQX_INVALID_POINTER (Entry_ptr is NULL.) * \return MQX_INVALID_COMPONENT_HANDLE (Log component data is not valid.) * * \see _log_create * \see _log_write * \see LOG_STRUCT * \see LOG_ENTRY_STRUCT */ _mqx_uint _log_read ( _mqx_uint log_number, _mqx_uint read_type, _mqx_uint size_to_read, LOG_ENTRY_STRUCT_PTR entry_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; LOG_COMPONENT_STRUCT_PTR log_component_ptr; LOG_HEADER_STRUCT_PTR log_header_ptr; LOG_ENTRY_STRUCT_PTR log_ptr; _mqx_uint_ptr data_ptr; _mqx_uint_ptr next_ptr; _mqx_uint_ptr user_ptr; _mqx_uint size; uint_16 milliseconds; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (log_number >= LOG_MAXIMUM_NUMBER) { return(LOG_INVALID); } /* Endif */ if (kernel_data->KERNEL_COMPONENTS[KERNEL_LOG] == NULL) { return(MQX_COMPONENT_DOES_NOT_EXIST); } /* Endif */ if (entry_ptr == NULL) { return(MQX_INVALID_POINTER); } /* Endif */ #endif log_component_ptr = (LOG_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_LOG]; #if MQX_CHECK_VALIDITY if (log_component_ptr->VALID != LOG_VALID) { return(MQX_INVALID_COMPONENT_HANDLE); } /* Endif */ #endif _INT_DISABLE(); log_header_ptr = log_component_ptr->LOGS[log_number]; #if MQX_CHECK_ERRORS if (log_header_ptr == NULL) { _int_enable(); return(LOG_DOES_NOT_EXIST); } /* Endif */ #endif if (log_header_ptr->SIZE == 0) { /* No data available */ _INT_ENABLE(); return(LOG_ENTRY_NOT_AVAILABLE); } /* Endif */ if (read_type == LOG_READ_OLDEST_AND_DELETE) { data_ptr = log_header_ptr->LOG_READ; } else if (read_type == LOG_READ_NEXT) { data_ptr = log_header_ptr->LOG_NEXT; if (data_ptr == NULL) { _INT_ENABLE(); return(LOG_ENTRY_NOT_AVAILABLE); } /* Endif */ } else if (read_type == LOG_READ_OLDEST) { data_ptr = log_header_ptr->LOG_READ; } else if (read_type == LOG_READ_NEWEST) { data_ptr = log_header_ptr->LAST_LOG; #if MQX_CHECK_ERRORS } else { _int_enable(); return(LOG_INVALID_READ_TYPE); #endif } /* Endif */ size = *data_ptr; next_ptr = data_ptr + size; #if 0 if (next_ptr >= log_header_ptr->LOG_END) { next_ptr = log_header_ptr->LOG_START + (next_ptr - log_header_ptr->LOG_END); } /* Endif */ #else if (log_header_ptr->LOG_READ < log_header_ptr->LOG_WRITE) { /* R < W */ if (next_ptr >= log_header_ptr->LOG_WRITE) { next_ptr = log_header_ptr->LOG_READ; } /* Endif */ } else { /* R > W */ if (next_ptr >= log_header_ptr->LOG_END) { next_ptr = log_header_ptr->LOG_START + (next_ptr - log_header_ptr->LOG_END); } /* Endif */ if (next_ptr == log_header_ptr->LOG_WRITE) { next_ptr = log_header_ptr->LOG_READ; } /* Endif */ } /* Endif */ #endif if (read_type == LOG_READ_OLDEST_AND_DELETE) { log_header_ptr->LOG_READ += size; log_header_ptr->SIZE -= size; if (log_header_ptr->LOG_READ >= log_header_ptr->LOG_END) { log_header_ptr->LOG_READ = log_header_ptr->LOG_START + (log_header_ptr->LOG_READ - log_header_ptr->LOG_END); } /* Endif */ } /* Endif */ if (size > (size_to_read + (_mqx_uint)sizeof(LOG_ENTRY_STRUCT)/sizeof(_mqx_uint))) { size = (size_to_read + (_mqx_uint)sizeof(LOG_ENTRY_STRUCT)/sizeof(_mqx_uint)); } /* Endif */ ++size; user_ptr = (_mqx_uint_ptr)((pointer)entry_ptr); while (--size) { *user_ptr++ = *data_ptr++; if (data_ptr == log_header_ptr->LOG_END) { data_ptr = log_header_ptr->LOG_START; } /* Endif */ } /* Endwhile */ log_ptr = entry_ptr; if (log_ptr->MICROSECONDS > MICROSECS_IN_MILLISECOND) { milliseconds = log_ptr->MICROSECONDS / (uint_16)MICROSECS_IN_MILLISECOND; log_ptr->MILLISECONDS += milliseconds; log_ptr->MICROSECONDS -= (milliseconds * (uint_16)MICROSECS_IN_MILLISECOND); } /* Endif */ if (read_type == LOG_READ_NEXT) { log_header_ptr->LOG_NEXT = next_ptr; } else if (read_type == LOG_READ_OLDEST) { log_header_ptr->LOG_NEXT = next_ptr; } else { log_header_ptr->LOG_NEXT = NULL; } /* Endif */ _INT_ENABLE(); return(MQX_OK); } /* Endbody */
/*! * \private * * \brief This is internal function used by a task to wait for a specified event. * * \param[in] event_ptr Read only. Pointer to the lightweight event. * \param[in] bit_mask Bit mask. Each set bit represents an event bit * to wait for. * \param[in] all TRUE (wait for all bits in bit_mask to be set), * FALSE (wait for any bit in bit_mask to be set). * \param[in] tick_ptr Pointer to the maximum number of ticks to wait * for the events to be set. If the value is NULL, then the timeout will be infinite. * \param[in] ticks_are_absolute TRUE (ticks represents absolute time), FALSE * (ticks represents relative time). * * \return MQX_OK * \return LWEVENT_WAIT_TIMEOUT (The time elapsed before an event signalled.) * \return MQX_LWEVENT_INVALID (Lightweight event is no longer valid or was never valid.) * \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.) * * \see _lwevent_wait_for * \see _usr_lwevent_wait_for * \see _lwevent_wait_until * \see _usr_lwevent_wait_until * \see _lwevent_wait_ticks * \see _usr_lwevent_wait_ticks * \see LWEVENT_STRUCT * \see MQX_TICK_STRUCT */ _mqx_uint _lwevent_wait_internal ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint bit_mask, bool all, MQX_TICK_STRUCT_PTR tick_ptr, bool ticks_are_absolute ) { KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwevent_wait_internal, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return (MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif result = MQX_OK; td_ptr = kernel_data->ACTIVE_PTR; _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif if ( (all && (event_ptr->VALUE & bit_mask) == bit_mask) || (!all && (event_ptr->VALUE & bit_mask))) { /* store information about which bits caused task to be unblocked */ td_ptr->LWEVENT_BITS = event_ptr->VALUE & bit_mask; /* clear used automatic events */ event_ptr->VALUE &= ~(event_ptr->AUTO & bit_mask); _INT_ENABLE(); return (result); } /* Endif */ /* Must wait for a event to become available */ td_ptr->LWEVENT_BITS = bit_mask; if (all) { td_ptr->FLAGS |= TASK_LWEVENT_ALL_BITS_WANTED; } else { td_ptr->FLAGS &= ~TASK_LWEVENT_ALL_BITS_WANTED; } /* Endif */ /* Enqueue at end */ _QUEUE_ENQUEUE(&event_ptr->WAITING_TASKS, &td_ptr->AUX_QUEUE); /* Now put the task to sleep */ td_ptr->STATE = LWEVENT_BLOCKED; td_ptr->INFO = (_mqx_uint) &event_ptr->WAITING_TASKS; if (tick_ptr) { if (ticks_are_absolute) { _time_delay_until(tick_ptr); } else { _time_delay_for(tick_ptr); } /* Endif */ if (td_ptr->INFO) { /* Must have timed out */ /*_QUEUE_REMOVE(&event_ptr->WAITING_TASKS, &td_ptr->AUX_QUEUE);*/ result = LWEVENT_WAIT_TIMEOUT; } /* Endif */ } else { _task_block(); } /* Endif */ #if MQX_COMPONENT_DESTRUCTION if (event_ptr->VALID == 0) { /* We've been deleted */ result = MQX_LWEVENT_INVALID; } /* Endif */ #endif _INT_ENABLE(); return (result); }
_mqx_uint _mem_create_pool_internal ( /* [IN] the start of the memory pool */ pointer start, /* [IN] the end of the memory pool */ pointer end, /* [IN] where to store the memory pool context info. */ MEMPOOL_STRUCT_PTR mem_pool_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; STOREBLOCK_STRUCT_PTR block_ptr; STOREBLOCK_STRUCT_PTR end_block_ptr; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_VALIDITY _INT_DISABLE(); if (kernel_data->MEM_COMP.VALID != MEMPOOL_VALID) { /* The RTOS memory system has been corrupted */ _int_enable(); return(MQX_CORRUPT_MEMORY_SYSTEM); } /* Endif */ _INT_ENABLE(); #endif /* Align the start of the pool */ mem_pool_ptr->POOL_PTR = (STOREBLOCK_STRUCT_PTR) _ALIGN_ADDR_TO_HIGHER_MEM(start); /* Set the end of memory (aligned) */ mem_pool_ptr->POOL_LIMIT = (STOREBLOCK_STRUCT_PTR) _ALIGN_ADDR_TO_LOWER_MEM(end); #if MQX_CHECK_ERRORS if ( (uchar_ptr)mem_pool_ptr->POOL_LIMIT <= ((uchar_ptr)mem_pool_ptr->POOL_PTR + MQX_MIN_MEMORY_POOL_SIZE) ) { return MQX_MEM_POOL_TOO_SMALL; } /* Endif */ #endif block_ptr = (STOREBLOCK_STRUCT_PTR)mem_pool_ptr->POOL_PTR; mem_pool_ptr->POOL_HIGHEST_MEMORY_USED = (pointer)block_ptr; mem_pool_ptr->POOL_CHECK_POOL_PTR = (char _PTR_)mem_pool_ptr->POOL_PTR; mem_pool_ptr->POOL_BLOCK_IN_ERROR = NULL; /* Compute the pool size. */ mem_pool_ptr->POOL_SIZE = (_mem_size)((uchar_ptr)mem_pool_ptr->POOL_LIMIT - (uchar_ptr)mem_pool_ptr->POOL_PTR); /* Set up the first block as an idle block */ block_ptr->BLOCKSIZE = mem_pool_ptr->POOL_SIZE - MQX_MIN_MEMORY_STORAGE_SIZE; block_ptr->USER_AREA = NULL; block_ptr->PREVBLOCK = NULL; block_ptr->NEXTBLOCK = NULL; MARK_BLOCK_AS_FREE(block_ptr); CALC_CHECKSUM(block_ptr); mem_pool_ptr->POOL_FREE_LIST_PTR = block_ptr; /* ** Set up last block as an in_use block, so that the _mem_free algorithm ** will work (block coalescing) */ end_block_ptr = (STOREBLOCK_STRUCT_PTR) ((uchar_ptr)block_ptr + block_ptr->BLOCKSIZE); end_block_ptr->BLOCKSIZE = (_mem_size)(MQX_MIN_MEMORY_STORAGE_SIZE); end_block_ptr->USER_AREA = 0; end_block_ptr->PREVBLOCK = (struct storeblock_struct _PTR_)block_ptr; end_block_ptr->NEXTBLOCK = NULL; MARK_BLOCK_AS_USED(end_block_ptr, SYSTEM_TASK_ID(kernel_data)); CALC_CHECKSUM(end_block_ptr); mem_pool_ptr->POOL_END_PTR = end_block_ptr; /* Initialize the list of extensions to this pool */ _QUEUE_INIT(&mem_pool_ptr->EXT_LIST, 0); mem_pool_ptr->VALID = MEMPOOL_VALID; /* Protect the list of pools while adding new pool */ _lwsem_wait((LWSEM_STRUCT_PTR)&kernel_data->MEM_COMP.SEM); _QUEUE_ENQUEUE(&kernel_data->MEM_COMP.POOLS, &mem_pool_ptr->LINK); _lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->MEM_COMP.SEM); return MQX_OK; } /* Endbody */