pointer _lwmem_alloc_system_from ( /* [IN] the pool to allocate from */ _lwmem_pool_id pool_id, /* [IN] the size of the memory block */ _mem_size size ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; pointer result; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_lwmem_alloc_system_from, size); result = _lwmem_alloc_internal(size, SYSTEM_TD_PTR(kernel_data), pool_id, FALSE); _KLOGX2(KLOG_lwmem_alloc_system_from, result); 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 Initializes and starts MQX on the processor. * * The function does the following: * \li Initializes the default memory pool and memory components. * \li Initializes kernel data. * \li Performs BSP-specific initialization, which includes installing the * periodic timer. * \li Performs PSP-specific initialization. * \li Creates the interrupt stack. * \li Creates the ready queues. * \li Starts MQX tasks. * \li Starts autostart application tasks. * * \param[in] mqx_init Pointer to the MQX initialization structure for the * processor. * * \return Does not return (Success.) * \return If application called _mqx_exit(), error code that it passed to * _mqx_exit() (Success.) * \return Errors from _int_install_isr() (MQX cannot install the interrupt * subsystem.) * \return Errors from _io_init() (MQX cannot install the I/O subsystem.) * \return Errors from _mem_alloc_system() (There is not enough memory to * allocate either the interrupt stack or the interrupt table.) * \return Errors from _mem_alloc_zero() (There is not enough memory to allocate * the ready queues.) * \return MQX_KERNEL_MEMORY_TOO_SMALL (Init_struct_ptr does not specify enough * kernel memory.) * \return MQX_OUT_OF_MEMORY (There is not enough memory to allocate either the * ready queues, the interrupt stack, or the interrupt table.) * \return MQX_TIMER_ISR_INSTALL_FAIL (MQX cannot install the periodic timer ISR.) * * \warning Must be called exactly once per processor. * * \see _mqx_exit * \see _int_install_isr * \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 MQX_INITIALIZATION_STRUCT * \see TASK_TEMPLATE_STRUCT */ _mqx_uint _mqx ( register MQX_INITIALIZATION_STRUCT_PTR mqx_init ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TASK_TEMPLATE_STRUCT_PTR template_ptr; TD_STRUCT_PTR td_ptr; _mqx_uint result; pointer stack_ptr; pointer sys_td_stack_ptr; uchar_ptr sys_stack_base_ptr; #if MQX_EXIT_ENABLED || MQX_CRIPPLED_EVALUATION /* Setup a longjmp buffer using setjmp, so that if an error occurs * in mqx initialization, we can perform a longjmp to this location. * * Also _mqx_exit will use this jumpbuffer to longjmp to here in order * to cleanly exit MQX. */ if ( MQX_SETJMP( _mqx_exit_jump_buffer_internal ) ) { _GET_KERNEL_DATA(kernel_data); _int_set_vector_table(kernel_data->USERS_VBR); return kernel_data->USERS_ERROR; } /* Endif */ #endif /* * The kernel data structure starts at the start of kernel memory, * as specified in the initialization structure. Make sure address * specified is aligned */ kernel_data = (KERNEL_DATA_STRUCT_PTR) _ALIGN_ADDR_TO_HIGHER_MEM(mqx_init->START_OF_KERNEL_MEMORY); /* Set the global pointer to the kernel data structure */ _SET_KERNEL_DATA(kernel_data); /* The following assignments are done to force the linker to include * the symbols, which are required by TAD. * Note that we should use address of the variable so it is not optimized * as direct constant assignment when optimization level is high. * Note that counter will be immediately reset to zero on the subsequent * _mem_zero call. */ *(volatile pointer*) kernel_data = (pointer) & _mqx_version_number; *(volatile pointer*) kernel_data = (pointer) & _mqx_vendor; /* Initialize the kernel data to zero. */ _mem_zero((pointer) kernel_data, (_mem_size) sizeof(KERNEL_DATA_STRUCT)); #if MQX_CHECK_ERRORS && MQX_VERIFY_KERNEL_DATA /* Verify that kernel data can be read and written correcly without * errors. This is necessary during BSP development to validate the * DRAM controller is initialized properly. */ #ifndef PSP_KERNEL_DATA_VERIFY_ENABLE #define PSP_KERNEL_DATA_VERIFY_ENABLE 0 #endif /* PSP_KERNEL_DATA_VERIFY_ENABLE */ if (PSP_KERNEL_DATA_VERIFY_ENABLE) { /* This memory check is dangerous, because can destroy boot stack * stack which is used !!! -> MQX will failed ! * Set PSP_KERNEL_DATA_VERIFY_ENABLE to 1 * only if your boot stack is out of MQX memory heap */ result = _mem_verify((uchar_ptr)kernel_data + sizeof(KERNEL_DATA_STRUCT), mqx_init->END_OF_KERNEL_MEMORY); if ( result != MQX_OK ) { _mqx_exit(result); /* RETURN TO USER */ } } #endif /* MQX_CHECK_ERRORS && MQX_VERIFY_KERNEL_DATA */ /* Copy the MQX initialization structure into kernel data. */ kernel_data->INIT = *mqx_init; kernel_data->INIT.START_OF_KERNEL_MEMORY = (pointer) kernel_data; kernel_data->INIT.END_OF_KERNEL_MEMORY = (pointer) _ALIGN_ADDR_TO_LOWER_MEM(kernel_data->INIT.END_OF_KERNEL_MEMORY); /* init kernel data structures */ _mqx_init_kernel_data_internal(); /* Initialize the memory resource manager for the kernel */ result = _mem_init_internal(); #if MQX_CHECK_ERRORS if ( result != MQX_OK ) { _mqx_exit(result); /* RETURN TO USER */ } /* Endif */ #endif #if MQX_USE_INTERRUPTS /* Now obtain the interrupt stack */ if (kernel_data->INIT.INTERRUPT_STACK_LOCATION) { stack_ptr = kernel_data->INIT.INTERRUPT_STACK_LOCATION; result = kernel_data->INIT.INTERRUPT_STACK_SIZE; } else { if ( kernel_data->INIT.INTERRUPT_STACK_SIZE < PSP_MINSTACKSIZE ) { kernel_data->INIT.INTERRUPT_STACK_SIZE = PSP_MINSTACKSIZE; } /* Endif */ #if PSP_STACK_ALIGNMENT result = kernel_data->INIT.INTERRUPT_STACK_SIZE + PSP_STACK_ALIGNMENT + 1; #else result = kernel_data->INIT.INTERRUPT_STACK_SIZE; #endif stack_ptr = _mem_alloc_system((_mem_size)result); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (stack_ptr == NULL) { _mqx_exit(MQX_OUT_OF_MEMORY); /* RETURN TO USER */ } /* Endif */ #endif _mem_set_type(stack_ptr, MEM_TYPE_INTERRUPT_STACK); } /* Endif */ #if MQX_MONITOR_STACK _task_fill_stack_internal((_mqx_uint_ptr)stack_ptr, result); #endif kernel_data->INTERRUPT_STACK_PTR = _GET_STACK_BASE(stack_ptr, result); #endif /* * Set the stack for the system TD, in case the idle task gets blocked * by an exception or if idle task is not used. */ result = PSP_MINSTACKSIZE; sys_td_stack_ptr = _mem_alloc_system((_mem_size) result); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (sys_td_stack_ptr == NULL) { _mqx_exit(MQX_OUT_OF_MEMORY); /* RETURN TO USER */ } /* Endif */ #endif _mem_set_type(sys_td_stack_ptr, MEM_TYPE_SYSTEM_STACK); sys_stack_base_ptr = (uchar_ptr) _GET_STACK_BASE(sys_td_stack_ptr, result); td_ptr = SYSTEM_TD_PTR(kernel_data); td_ptr->STACK_PTR = (pointer)(sys_stack_base_ptr - sizeof(PSP_STACK_START_STRUCT)); td_ptr->STACK_BASE = sys_stack_base_ptr; #if MQX_TD_HAS_STACK_LIMIT td_ptr->STACK_LIMIT = _GET_STACK_LIMIT(sys_td_stack_ptr, result); #endif _mqx_system_stack = td_ptr->STACK_PTR; /* Build the MQX ready to run queues */ result = _psp_init_readyqs(); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if ( result != MQX_OK ) { _mqx_exit(result); /* RETURN TO USER */ } /* Endif */ #endif #if MQX_USE_COMPONENTS /* Create a light wait semaphore for component creation */ _lwsem_create((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM, 1); #endif /* Create a light wait semaphore for task creation/destruction creation */ _lwsem_create((LWSEM_STRUCT_PTR) & kernel_data->TASK_CREATE_LWSEM, 1); /* Call bsp to enable timers and other devices */ result = _bsp_enable_card(); #if MQX_CHECK_ERRORS if ( result != MQX_OK ) { _mqx_exit(result); /* RETURN TO USER */ } /* Endif */ #endif #if MQX_HAS_TIME_SLICE /* Set the kernel default time slice value */ PSP_ADD_TICKS_TO_TICK_STRUCT(&kernel_data->SCHED_TIME_SLICE, MQX_DEFAULT_TIME_SLICE, &kernel_data->SCHED_TIME_SLICE); #endif /* Create the idle task */ #if MQX_USE_IDLE_TASK td_ptr = _task_init_internal( (TASK_TEMPLATE_STRUCT_PTR)&kernel_data->IDLE_TASK_TEMPLATE, kernel_data->ACTIVE_PTR->TASK_ID, MQX_IDLE_TASK_PARAMETER, TRUE, NULL, 0); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (td_ptr == NULL) { _mqx_exit(MQX_OUT_OF_MEMORY); } /* Endif */ #endif _task_ready_internal(td_ptr); #endif /* Check here for auto-create tasks, and create them here */ template_ptr = kernel_data->INIT.TASK_TEMPLATE_LIST; while (template_ptr->TASK_TEMPLATE_INDEX) { if (template_ptr->TASK_ATTRIBUTES & MQX_AUTO_START_TASK) { td_ptr = _task_init_internal(template_ptr, kernel_data->ACTIVE_PTR->TASK_ID, template_ptr->CREATION_PARAMETER, FALSE, NULL, 0); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (td_ptr == NULL) { _mqx_exit(MQX_OUT_OF_MEMORY); } /* Endif */ #endif _task_ready_internal(td_ptr); } /* Endif */ ++template_ptr; } /* Endwhile */ _sched_start_internal(); /* WILL NEVER RETURN FROM HERE */ return MQX_OK; /* To satisfy lint */ } /* Endbody */
_mqx_uint _task_abort ( /* [IN] the task id of the task to abort */ _task_id task_id ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; pointer stack_ptr; _processor_number processor; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_task_abort, task_id); if (task_id != MQX_NULL_TASK_ID) { processor = PROC_NUMBER_FROM_TASKID(task_id); if (processor != (_processor_number)kernel_data->INIT.PROCESSOR_NUMBER ) { #if MQX_IS_MULTI_PROCESSOR if ( kernel_data->IPC != NULL ) { _KLOGX2(KLOG_task_abort, MQX_OK); return( (*kernel_data->IPC)(FALSE, processor, KERNEL_MESSAGES, IPC_TASK_ABORT, 1, (_mqx_uint)task_id) ); } else { #endif _KLOGX2(KLOG_task_abort, MQX_INVALID_TASK_ID); return(MQX_INVALID_TASK_ID); #if MQX_IS_MULTI_PROCESSOR } /* Endif */ #endif }/* Endif */ }/* Endif */ td_ptr = (TD_STRUCT_PTR)_task_get_td(task_id); #if MQX_CHECK_ERRORS if ( (td_ptr == NULL) || (td_ptr == SYSTEM_TD_PTR(kernel_data)) ) { _KLOGX2(KLOG_task_abort, MQX_INVALID_TASK_ID); return( MQX_INVALID_TASK_ID ); } /* Endif */ #endif if (td_ptr == kernel_data->ACTIVE_PTR) { if (kernel_data->IN_ISR) { stack_ptr = (pointer)td_ptr->STACK_PTR; _PSP_SET_PC_OF_INTERRUPTED_TASK(stack_ptr, _task_exit_function_internal); } else { _task_exit_function_internal(); }/* Endif */ } else { _int_disable(); /* Task is not running */ stack_ptr = (pointer)td_ptr->STACK_PTR; _PSP_SET_PC_OF_BLOCKED_TASK(stack_ptr, _task_exit_function_internal); /* Start CR 1222 */ if (td_ptr->STATE & IS_ON_TIMEOUT_Q){ /* Remove from time queue (uses NEXT, PREV field) */ _TIME_DEQUEUE(td_ptr, kernel_data); /* End CR 1222 */ } else if (td_ptr->STATE & TD_IS_ON_QUEUE) { _QUEUE_REMOVE(td_ptr->INFO, td_ptr); /* Begin CR 1223 */ } else if((td_ptr->STATE & BLOCKED_ON_AUX_QUEUE) ==BLOCKED_ON_AUX_QUEUE){ /* We need to remove it here because _task_ready() below will change its state to READY */ _QUEUE_REMOVE(td_ptr->INFO, &td_ptr->AUX_QUEUE); } /* Endif */ /* End CR 1223 */ if (td_ptr->STATE & IS_BLOCKED) { _task_ready(td_ptr); } /* Endif */ _int_enable(); }/* Endif */ _KLOGX2(KLOG_task_abort, MQX_OK); return(MQX_OK); } /* Endbody */
/*! * \brief Initializes MQXLite on the processor. * * The function does the following: * \n - Initializes kernel data. * \n - Creates the interrupt stack. * \n - Creates the ready queues. * \n - Creates a lightweight semaphore for task creation/destruction. * \n - Initializes interrupts. * \n - Initializes system timer. * * \param[in] mqx_init Pointer to the MQXLITE initialization structure for the * processor. * * \return MQX_OK * \return Initialization error code * * \warning Must be called exactly once per processor. * * \see _mqxlite * \see _mqx_exit * \see MQXLITE_INITIALIZATION_STRUCT */ _mqx_uint _mqxlite_init ( MQXLITE_INITIALIZATION_STRUCT const * mqx_init ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; pointer stack_ptr; _mqx_uint result = MQX_OK; /* * The kernel data structure starts at the start of kernel memory, * as specified in the initialization structure. Make sure address * specified is aligned */ kernel_data = (KERNEL_DATA_STRUCT_PTR) (mqx_init->START_OF_KERNEL_MEMORY); /* Set the global pointer to the kernel data structure */ _SET_KERNEL_DATA(kernel_data); /* The following assignments are done to force the linker to include * the symbols, which are required by TAD. * Note that we should use address of the variable so it is not optimized * as direct constant assignment when optimization level is high. * Note that counter will be immediately reset to zero on the subsequent * _mem_zero call. */ { MQX_INITIALIZATION_STRUCT * MQX_init_struct_ptr; *(volatile pointer*) kernel_data = (pointer) & _mqx_version_number; *(volatile pointer*) kernel_data = (pointer) & _mqx_vendor; *(volatile pointer*) kernel_data = (pointer) & _mqx_path; *(volatile pointer*) kernel_data = (pointer) & _mqxlite_version_number; *(volatile pointer*) kernel_data = (pointer) & MQX_init_struct_ptr; } /* Initialize the kernel data to zero. */ _mem_zero((pointer) kernel_data, (_mem_size) sizeof(KERNEL_DATA_STRUCT)); #if MQX_CHECK_ERRORS && MQX_VERIFY_KERNEL_DATA /* Verify that kernel data can be read and written correctly without * errors. This is necessary during BSP development to validate the * DRAM controller is initialized properly. */ if (PSP_KERNEL_DATA_VERIFY_ENABLE) { /* This memory check is dangerous, because can destroy boot stack * stack which is used !!! -> MQX will failed ! * Set PSP_KERNEL_DATA_VERIFY_ENABLE to 1 * only if your boot stack is out of MQX memory heap */ result = _mem_verify((uchar_ptr)kernel_data + sizeof(KERNEL_DATA_STRUCT), mqx_init->END_OF_KERNEL_MEMORY); if ( result != MQX_OK ) { return (result); /* RETURN TO USER */ } } #endif /* MQX_CHECK_ERRORS && MQX_VERIFY_KERNEL_DATA */ /* Copy the MQX initialization structure into kernel data. */ kernel_data->INIT = *mqx_init; /* init kernel data structures */ _mqx_init_kernel_data_internal(); #if MQX_USE_LWMEM == 1 /** * Initialize lightweight memory pool for dynamic memory allocation */ { /* Extern symbols defined in linker command file */ extern char __heap_addr[]; extern char __heap_size[]; KERNEL_DATA_STRUCT * kernel_data; LWMEM_POOL_STRUCT * pool_ptr; void * start_addr; _GET_KERNEL_DATA(kernel_data); pool_ptr = (LWMEM_POOL_STRUCT *) __heap_addr; kernel_data->KERNEL_LWMEM_POOL = pool_ptr; start_addr = (void *)((char *) __heap_addr + sizeof(LWMEM_POOL_STRUCT)); _lwmem_create_pool(pool_ptr, start_addr, (_mem_size)__heap_size); } #endif #if MQX_USE_INTERRUPTS /* Now obtain the interrupt stack */ if (kernel_data->INIT.INTERRUPT_STACK_LOCATION) { stack_ptr = kernel_data->INIT.INTERRUPT_STACK_LOCATION; result = kernel_data->INIT.INTERRUPT_STACK_SIZE; } else { return (MQX_INVALID_PARAMETER); } /* Endif */ #if MQX_MONITOR_STACK _task_fill_stack_internal((_mqx_uint_ptr)stack_ptr, result); #endif kernel_data->INTERRUPT_STACK_PTR = _GET_STACK_BASE(stack_ptr, result); #endif /* MQX_USE_INTERRUPTS */ #if MQX_USE_IDLE_TASK == 0 { /* * Set the stack for the system TD, in case the idle task gets blocked * by an exception or if idle task is not used. */ TD_STRUCT_PTR td_ptr; uchar_ptr stack_base_ptr; stack_base_ptr = (uchar_ptr) _GET_STACK_BASE(mqx_system_stack, PSP_MINSTACKSIZE); td_ptr = SYSTEM_TD_PTR(kernel_data); td_ptr->STACK_PTR = (pointer)(stack_base_ptr - sizeof(PSP_STACK_START_STRUCT)); td_ptr->STACK_BASE = stack_base_ptr; #if MQX_TD_HAS_STACK_LIMIT td_ptr->STACK_LIMIT = _GET_STACK_LIMIT(mqx_system_stack, PSP_MINSTACKSIZE); #endif _mqx_system_stack = td_ptr->STACK_PTR; } #endif /* MQX_USE_IDLE_TASK */ /* Build the MQX ready to run queues */ result = _psp_init_readyqs(); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if ( result != MQX_OK ) { return (result); /* RETURN TO USER */ } /* Endif */ #endif #if MQX_USE_COMPONENTS /* Create a light wait semaphore for component creation */ _lwsem_create((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM, 1); #endif /* Create a light wait semaphore for task creation/destruction creation */ _lwsem_create((LWSEM_STRUCT_PTR) & kernel_data->TASK_CREATE_LWSEM, 1); /* Set the CPU type */ _mqx_set_cpu_type(MQX_CPU); result = _psp_int_init(FIRST_INTERRUPT_VECTOR_USED, LAST_INTERRUPT_VECTOR_USED); if (result != MQX_OK) { return(result); /* RETURN TO USER */ } /* set possible new interrupt vector table * if MQX_ROM_VECTORS = 0 switch to ram interrupt table which * was initialized in _psp_int_init) */ _int_set_vector_table((uint32_t)(&__vect_table)); /* * Initialize System Timer and Ticks parameters in kernel_data structure */ system_timer_init(NULL); return MQX_OK; /* To satisfy lint */ } /* Endbody */