/*! * \brief Gets a pointer to the kernel ISR for the specified vector number. The * kernel ISR depends on the PSP. * * \param[in] vector Vector number whose kernel ISR is requested. * * \return Pointer to the kernel ISR (Success.) * \return NULL * * \warning On failure, calls _task_set_error() to set the task error code: * \li MQX_INVALID_VECTORED_INTERRUPT * * \see _int_kernel_isr * \see _int_install_kernel_isr */ INT_KERNEL_ISR_FPTR _int_get_kernel_isr ( _mqx_uint int_vector ) { /* Body */ #if MQX_CHECK_ERRORS if ( int_vector >= PSP_MAXIMUM_INTERRUPT_VECTORS ) { _task_set_error(MQX_INVALID_VECTORED_INTERRUPT); return NULL; } /* Endif */ #endif #if defined (PSP_BOOKE) || defined( PSP_BOOKE_VLE) return _bsp_int_get_kernel_isr(int_vector); #else /* !PSP_BOOKE (Original exception model) */ #ifdef PSP_MPC566 return (INT_KERNEL_ISR_FPTR)(_int_get_vector_table() + (int_vector * 0x100)); #else return (INT_KERNEL_ISR_FPTR)(int_vector * 0x100); #endif #endif /* PSP_BOOKE */ } /* Endbody */
/*! * \brief Installs the kernel ISR handler. The kernel ISR depends on the PSP. * * Some real-time applications need special event handling to occur outside the * scope of MQX. The need might arise that the latency in servicing an interrupt * be less than the MQX interrupt latency. If this is the case, an application can * use _int_install_kernel_isr() to bypass MQX and let the interrupt be serviced * immediately. * \n Because the function returns the previous kernel ISR, applications can * temporarily install an ISR or chain ISRs so that each new one calls the one * installed before it. * \n A kernel ISR must save the registers that it needs and must service the * hardware interrupt. When the kernel ISR is finished, it must restore the * registers and perform a return-from-interrupt instruction. * \n A kernel ISR cannot call MQX functions. However, it can put data in global * data, which a task can access. * * \note The function is not available for all PSPs. * * \param[in] vector Vector where the ISR is to be installed. * \param[in] isr_ptr Pointer to the ISR to install into the vector table. * * \return Pointer to the previous kernel ISR for the vector (Success.). * \return NULL * * \see _int_kernel_isr * \see _int_get_kernel_isr */ INT_KERNEL_ISR_FPTR _int_install_kernel_isr ( uint_32 vector, INT_KERNEL_ISR_FPTR isr_ptr ) { #if !MQX_ROM_VECTORS #if MQX_KERNEL_LOGGING KERNEL_DATA_STRUCT_PTR kernel_data; #endif INT_KERNEL_ISR_FPTR old_isr_ptr; uint_32 result_code; uint_32_ptr loc_ptr; #if MQX_KERNEL_LOGGING _GET_KERNEL_DATA(kernel_data); #endif _KLOGE3(KLOG_int_install_kernel_isr, vector, isr_ptr); #if MQX_CHECK_ERRORS result_code = MQX_OK; old_isr_ptr = NULL; if ( vector >= PSP_MAXIMUM_INTERRUPT_VECTORS ) { result_code = MQX_INVALID_VECTORED_INTERRUPT; } else { #endif loc_ptr = (uint_32_ptr)_int_get_vector_table(); old_isr_ptr = (INT_KERNEL_ISR_FPTR)loc_ptr[vector]; loc_ptr[vector] = (uint_32)isr_ptr; #if MQX_CHECK_ERRORS } /* Endif */ /* Set result code and return result. */ _task_set_error(result_code); #endif _KLOGX3(KLOG_int_install_kernel_isr, old_isr_ptr, result_code); return (old_isr_ptr); #else #if MQX_CHECK_ERRORS /* Set result code and return result. */ _task_set_error(MQX_INVALID_CONFIGURATION); #endif return NULL; #endif }
/*! * \brief This function initializes kernel interrupt tables. */ void _psp_int_install ( void ) { /* Body */ #if !MQX_ROM_VECTORS uint32_t i; uint32_t *vbr_ptr; vbr_ptr = (uint32_t *)_int_get_vector_table(); /* Initialize the hardware interrupt vector table */ // 0: Initial stack pointer // 1: Initial program counter for (i = 2; i < PSP_MAXIMUM_INTERRUPT_VECTORS; i++ ) { vbr_ptr[i] = (uint32_t)_int_kernel_isr; } /* Endfor */ #endif } /* Endbody */
void _mqx_init_kernel_data_internal ( void ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TASK_TEMPLATE_STRUCT_PTR task_template_ptr; TD_STRUCT_PTR td_ptr; _mqx_uint priority_levels; _mqx_uint i; _GET_KERNEL_DATA(kernel_data); /* Store the configuration used when the kernel was compiled */ kernel_data->CONFIG1 = MQX_CNFG1; kernel_data->CONFIG2 = MQX_CNFG2; /* Store the addressability of the processor. How many bits in a byte. */ kernel_data->ADDRESSING_CAPABILITY = PSP_MEMORY_ADDRESSING_CAPABILITY; /* Indicate the endianess of the target */ kernel_data->ENDIANESS = PSP_ENDIAN; /* Store PSP memory alignment information */ #if PSP_MEM_STOREBLOCK_ALIGNMENT != 0 kernel_data->PSP_CFG_MEM_STOREBLOCK_ALIGNMENT = PSP_MEM_STOREBLOCK_ALIGNMENT; #endif kernel_data->PSP_CFG_MEMORY_ALIGNMENT = PSP_MEMORY_ALIGNMENT; kernel_data->PSP_CFG_STACK_ALIGNMENT = PSP_STACK_ALIGNMENT; /* ** Fill in fields of the kernel data structure from the initialization ** structure. */ //kernel_data->PROCESSOR_NUMBER = kernel_data->INIT.PROCESSOR_NUMBER; /* Set IPC id for compatibility */ #if MQX_USE_IPC kernel_data->MY_IPC_ID = BUILD_TASKID(kernel_data->INIT.PROCESSOR_NUMBER, 1); #endif /* Store location of current interrupt vector table */ #if MQX_EXIT_ENABLED kernel_data->USERS_VBR = (_mqx_max_type)_int_get_vector_table(); #endif #if MQX_CHECK_ERRORS if (kernel_data->INIT.TASK_TEMPLATE_LIST == NULL) { _mqx_exit(MQX_INVALID_POINTER); } /* Endif */ #endif #if MQX_HAS_TIME_SLICE /* Set the default scheduling policy for created tasks */ kernel_data->SCHED_POLICY = MQX_SCHED_FIFO; #endif #if MQX_KD_HAS_COUNTER /* Initialize the kernel counter. */ kernel_data->COUNTER = 1U; #endif /* Set up the disable and enable priority levels */ _psp_set_kernel_disable_level(); /* ** Initialize the system task so that functions which update the ** task error code can be called. ** The system task never runs, but it's TD is used for error codes ** during initialization, and for storage of memory blocks assigned ** to the system. */ td_ptr = (TD_STRUCT_PTR)&kernel_data->SYSTEM_TD; kernel_data->ACTIVE_PTR = td_ptr; kernel_data->ACTIVE_SR = kernel_data->DISABLE_SR; td_ptr->TASK_SR = kernel_data->DISABLE_SR; td_ptr->TASK_ID = BUILD_TASKID(kernel_data->INIT.PROCESSOR_NUMBER, SYSTEM_TASK_NUMBER); td_ptr->STATE = BLOCKED; /* Initialize the light weight semaphores queue */ _QUEUE_INIT(&kernel_data->LWSEM, 0); #if MQX_ENABLE_USER_MODE _QUEUE_INIT(&kernel_data->USR_LWSEM, 0); #endif #if MQX_HAS_TICK /* Set up the timeout queue */ _QUEUE_INIT(&kernel_data->TIMEOUT_QUEUE, 0); #endif /* ** Compute the number of MQX priority levels needed. This is done ** by determining the task that has the lowest priority (highest number) */ priority_levels = 0; task_template_ptr = kernel_data->INIT.TASK_TEMPLATE_LIST; for (i = 0; task_template_ptr->TASK_TEMPLATE_INDEX && (i < MQX_MAXIMUM_NUMBER_OF_TASK_TEMPLATES); ++i, ++task_template_ptr) { if (priority_levels < task_template_ptr->TASK_PRIORITY) { priority_levels = task_template_ptr->TASK_PRIORITY; } /* Endif */ } /* Endfor */ kernel_data->LOWEST_TASK_PRIORITY = priority_levels; #if MQX_USE_IDLE_TASK /* ** Initialize the task template for the IDLE Task. ** NOTE that the idle task runs at 1 level lower than any user task. */ task_template_ptr = (TASK_TEMPLATE_STRUCT_PTR) &kernel_data->IDLE_TASK_TEMPLATE; task_template_ptr->TASK_TEMPLATE_INDEX = IDLE_TASK; task_template_ptr->TASK_STACKSIZE = PSP_IDLE_STACK_SIZE; task_template_ptr->TASK_NAME = MQX_IDLE_TASK_NAME; task_template_ptr->TASK_ADDRESS = _mqx_idle_task; task_template_ptr->TASK_PRIORITY = priority_levels + 1; #endif /* ** Initialize the linked list of all TDs in the system. ** Initially zero. Not including system TD */ _QUEUE_INIT(&kernel_data->TD_LIST, 0); /* Set the TD counter */ /* Start SPR P171-0014-02 */ /* kernel_data->TD_COUNTER = 1; */ kernel_data->TASK_NUMBER = 1; /* End SPR P171-0014-02 */ } /* Endbody */