void kos_init_regs(void) { uint32_t msp = __get_MSP(); __set_PSP(msp); __set_MSP((uint32_t)g_kos_isr_stk + g_kos_isr_stksz); __set_CONTROL(2); }
/******************************************************************************* * 名 称: IAP_JumpTo() * 功 能: 跳转到应用程序段 * 入口参数: * 出口参数: 无 * 作 者: 无名沈 * 创建日期: 2014-04-23 * 修 改: * 修改日期: *******************************************************************************/ void IAP_JumpTo(u32 appAddr) { u32 JumpAddress = 0; u8 cpu_sr; /*********************************************** * 描述: 保存程序地址 */ IAP_SetAppAddr(appAddr); /*********************************************** * 描述: 关中断,防止值被中断修改 */ CPU_CRITICAL_ENTER(); /*********************************************** * 描述: 外设恢复默认,避免进入应用程序后影响程序正常运行 */ IAP_DevDeInit(); /*********************************************** * 描述: 获取应用入口及初始化堆栈指针 */ JumpAddress =*(volatile u32*) (appAddr + 4); // 地址+4为PC地址 pApp = (pFunction)JumpAddress; // 函数指针指向APP __set_MSP (*(volatile u32*) appAddr); // 初始化主堆栈指针(MSP) __set_PSP (*(volatile u32*) appAddr); // 初始化进程堆栈指针(PSP) __set_CONTROL (0); // 清零CONTROL /*********************************************** * 描述: 跳转到APP程序 */ pApp(); CPU_CRITICAL_EXIT(); }
static void tt_use_PSP(unsigned int irq_stack_addr) { __set_PSP(__get_MSP()); __set_MSP(irq_stack_addr); __set_CONTROL(2); __ISB(); }
static void isr_reset(void) { // remove compiler warning (void)g_pfnVectors; /** * The hyperload bootloader sets the MSP/PSP upon a true reset, which is when the * LPC17xx (Cortex-M3) sets the values of the stack pointer. But since we are * booting after a bootloader, we have to manually setup the stack pointers ourselves. */ do { const uint32_t topOfStack = (uint32_t) &_vStackTop; __set_PSP(topOfStack); __set_MSP(topOfStack); } while(0); do { // Copy data from FLASH to RAM unsigned int LoadAddr, ExeAddr, SectionLen; unsigned int *SectionTableAddr; // Load base address of Global Section Table SectionTableAddr = &__data_section_table; // Copy the data sections from flash to SRAM. while (SectionTableAddr < &__data_section_table_end) { LoadAddr = *SectionTableAddr++; ExeAddr = *SectionTableAddr++; SectionLen = *SectionTableAddr++; data_init(LoadAddr, ExeAddr, SectionLen); } // At this point, SectionTableAddr = &__bss_section_table; // Zero fill the bss segment while (SectionTableAddr < &__bss_section_table_end) { ExeAddr = *SectionTableAddr++; SectionLen = *SectionTableAddr++; bss_init(ExeAddr, SectionLen); } } while (0) ; #if defined (__cplusplus) __libc_init_array(); // Call C++ library initialization #endif do { low_level_init(); // Initialize minimal system, such as Clock & UART high_level_init(); // Initialize high level board specific features main(); // Finally call main() } while(0); // In case main() exits: uart0_init(SYS_CFG_UART0_BPS); u0_dbg_put("main() should never exit on this system\n"); while (1) { ; } }
void Init_Cpu(void) { __set_PSP((uint32_t)msp_top); __set_PRIMASK(1); __set_FAULTMASK(1); __set_CONTROL(0); #if (CN_CPU_OPTIONAL_FPU == 1) startup_scb_reg->CPACR = (3UL << 20)|(3UL << 22); //使能FPU startup_scb_reg->FPCCR = (1UL << 31); //关闭lazy stacking #endif switch(startup_scb_reg->CPUID) { } extern void SysClockInit(void); SysClockInit(); #ifdef USE_HAL_DRIVER HAL_TickInit(); #endif extern void SRAM_Init(void); SRAM_Init(); IAP_SelectLoadProgam(); }
void execute_user_code(void) { void (*user_code_entry)(void); unsigned *p; // used for loading address of reset handler from user flash /* Change the Vector Table to the USER_FLASH_START in case the user application uses interrupts */ SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80); /* SP (stack pointer) register must be set correctly before jump to the * user application: http://www.keil.com/forum/17342/ */ __set_PSP(USER_FLASH_START); // Load contents of second word of user flash - the reset handler address // in the applications vector table p = (unsigned *)(USER_FLASH_START +4); // Set user_code_entry to be the address contained in that second word // of user flash user_code_entry = (void *) *p; // Jump to user application user_code_entry(); }
//! @brief Exits bootloader and jumps to the user application. static void jump_to_application(uint32_t applicationAddress, uint32_t stackPointer) { #if BL_FEATURE_OTFAD_MODULE quadspi_cache_clear(); oftfad_resume_as_needed(); #endif shutdown_cleanup(kShutdownType_Shutdown); // Create the function call to the user application. // Static variables are needed since changed the stack pointer out from under the compiler // we need to ensure the values we are using are not stored on the previous stack static uint32_t s_stackPointer = 0; s_stackPointer = stackPointer; static void (*farewellBootloader)(void) = 0; farewellBootloader = (void (*)(void))applicationAddress; // Set the VTOR to the application vector table address. SCB->VTOR = (uint32_t)APP_VECTOR_TABLE; // Set stack pointers to the application stack pointer. __set_MSP(s_stackPointer); __set_PSP(s_stackPointer); // while (1); /* SGF REMOVE */ // Jump to the application. farewellBootloader(); // Dummy fcuntion call, should never go to this fcuntion call shutdown_cleanup(kShutdownType_Shutdown); }
void Init_Cpu(void) { __set_PSP((uint32_t)msp_top); __set_PRIMASK(1); __set_FAULTMASK(1); __set_CONTROL(0); #if (CN_CPU_OPTIONAL_FPU == 1) pg_scb_reg->CPACR = (3UL << 20)|(3UL << 22); //使能FPU pg_scb_reg->FPCCR = (1UL << 31); //关闭lazy stacking #endif switch(pg_scb_reg->CPUID) { // case cn_revision_r0p1://todo // break; //好像没什么要做的 } extern void WDT_Disable(void); WDT_Disable(); //关狗 extern void SysClockInit(void); SysClockInit(); extern void SDRAM_Init(void); SDRAM_Init(); extern void Cache_Init(void); Cache_Init(); Load_Preload(); }
int init_sys(void) { SCB->CCR |= SCB_CCR_STKALIGN_Msk; // enable double word stack alignment PSP_array[0] = ((unsigned int)task0_stack) + (sizeof task0_stack) - 16*4; // top of stack HW32_REG((PSP_array[0] + (14<<2))) = (unsigned long)task0; // initial Program Counter HW32_REG((PSP_array[0] + (15<<2))) = 0x01000000; // initial PSR PSP_array[1] = ((unsigned int)task1_stack) + (sizeof task1_stack) - 16*4; HW32_REG((PSP_array[1] + (14<<2))) = (unsigned long)task1; HW32_REG((PSP_array[1] + (15<<2))) = 0x01000000; curr_task = 0; __set_PSP((PSP_array[curr_task] + 16*4)); // set PSP to top of stack NVIC_SetPriority(PendSV_IRQn, 0xFF); SysTick_Config(168000); __set_CONTROL(0x3); __ISB(); task0(); /*while(1) { stop_cpu; }; */ }
void _start() { /* copy data segment from flash to ram */ { const size_t datalen = (size_t) &_edata - (unsigned int) &_sdata; memcpy(&_sdata, &_sidata, datalen); } /* zero out bss segment */ { const size_t bsslen = (size_t) &_ebss - (unsigned int) &_sbss; memset(&_sbss, 0x0, bsslen); } SystemInit(); /* set process stack */ __set_PSP((uint32_t) &_eusrstack); /* enable drivers */ for (size_t i = 0; i < sizeof(drivers); i++) { const driver_t* drv_p = drivers[i]; if (drv_p->driver_reset != NULL) drv_p->driver_reset(); enable_clocks(drv_p); } (void) _init_crt1(); (void) main(); }
/** \brief Test case: TC_CoreFunc_PSP \details - Check if __get_PSP and __set_PSP intrinsic can be used to manipulate process stack pointer. */ void TC_CoreFunc_PSP (void) { // don't use stack for this variables static uint32_t orig; static uint32_t psp; static uint32_t result; orig = __get_PSP(); psp = orig + 0x12345678U; __set_PSP(psp); result = __get_PSP(); __set_PSP(orig); ASSERT_TRUE(result == psp); }
static inline void set_and_switch_to_psp(void) { u32_t process_sp; process_sp = (u32_t)&_interrupt_stack + CONFIG_ISR_STACK_SIZE; __set_PSP(process_sp); switch_sp_to_psp(); }
/** Switch the context back from the destination box to the source one. * * @internal * * In this function we keep the same naming convention of the switch-in. Hence, * here the destination box is the one we are leaving, the source box is the one * we are switching to. We do not need any input from the caller as we already * know where we are switching to from the stacked state. * * @warning With thread context switches there is no context switch-out, but * only a context switch-in (from the current thread to the next one), so this * function should not be used for that purpose. An error will be thrown if used * for thread switches. */ TContextPreviousState * context_switch_out(TContextSwitchType context_type) { uint8_t src_id, dst_id; uint32_t src_sp; TContextPreviousState * previous_state; /* This function is not needed for unbound context switches. * In those cases there is only a switch from a source box to a destination * box, and it can be done without state keeping. It is the host OS that * takes care of switching the stacks. */ if (context_type == CONTEXT_SWITCH_UNBOUND_THREAD) { HALT_ERROR(NOT_ALLOWED, "Unbound context switching (e.g. for thread context switching) does not need to switch " "out. Just call the context_switch_in(...) function repeatedly to switch from one task " "to another."); } /* Destination box: Gather information from the current state. */ dst_id = g_active_box; /* Source box: Gather information from the previous state. */ /* This function halts if it finds an error. */ previous_state = context_state_pop(); src_id = previous_state->src_id; src_sp = previous_state->src_sp; /* The source/destination box IDs can be the same (for example, in IRQs). */ if (src_id != dst_id) { /* Store outgoing newlib reent pointer. */ UvisorBoxIndex * index = (UvisorBoxIndex *) g_context_current_states[dst_id].bss; index->bss.address_of.newlib_reent = (uint32_t) *(__uvisor_config.newlib_impure_ptr); /* Update the ID of the currently active box. */ g_active_box = src_id; /* Update the context pointer to the one of the source box. */ index = (UvisorBoxIndex *) g_context_current_states[src_id].bss; *(__uvisor_config.uvisor_box_context) = (uint32_t *) index; /* Switch MPU configurations. */ /* This function halts if it finds an error. */ vmpu_switch(dst_id, src_id); /* Restore incoming newlib reent pointer. */ *(__uvisor_config.newlib_impure_ptr) = (uint32_t *) index->bss.address_of.newlib_reent; } /* Set the stack pointer for the source box. This is only needed if the * context switch is tied to a function. * Unbound context switches require the host OS to set the correct stack * pointer before handling execution to the unprivileged code. */ if (context_type == CONTEXT_SWITCH_FUNCTION_GATEWAY || context_type == CONTEXT_SWITCH_FUNCTION_ISR || context_type == CONTEXT_SWITCH_FUNCTION_DEBUG) { __set_PSP(src_sp); } return previous_state; }
/*! \brief C part of the SVC exception handler SVC 0 is initializing the OS and starting the scheduler. Each thread stack frame is initialized. \param svc_args Used to extract the SVC number */ void SVC_Handler_C(unsigned int * svc_args) { uint8_t svc_number; svc_number = ((char *) svc_args[6])[-2]; // Memory[(Stacked PC)-2] // marking kernel as busy kernel_busy = 1; switch(svc_number) { //************* SVC( 0 ) OS Start case (0): // OS start // Starting the task scheduler //TWP playing a trick here!? by making curr = next, will make next's stack and current's stack the same stack! // will save (garbage) current register values, and then immediately restore them as next's initial values :-) curr_task = rtr_q_h; // Switch to head ready-to-run task (Current task) // when current task was put in RTRQ its state was set to RUNNING svc_exc_return = HW32_REG(( curr_task->stack_p )); // Return to thread with PSP __set_PSP(( (uint32_t) curr_task->stack_p + 10*4)); // Set PSP to @R0 of task 0 exception stack frame NVIC_SetPriority(PendSV_IRQn, 0xFF); // Set PendSV to lowest possible priority if (SysTick_Config(os_sysTickTicks) != 0) // 1000 Hz SysTick interrupt on 16MHz core clock { stop_cpu2; // Impossible SysTick_Config number of ticks } __set_CONTROL(0x3); // Switch to use Process Stack, unprivileged state __ISB(); // Execute ISB after changing CONTROL (architectural recommendation) break; //************* SVC( 1 ) Thread Yield case (1): // Thread Yield if (curr_task != rtr_q_h) { // Context switching needed ScheduleContextSwitch(); } __ISB(); break; //************* SVC( 2 ) Stack Frame Allocation for First Launch //TWPV6: no longer used! Functionality moved to osThreadCreate ... case left here (for now) case (2): // Stack Allocation __ISB(); break; default: #if ((ENABLE_KERNEL_PRINTF) && (ENABLE_KERNEL_PRINTF == 1)) printf("ERROR: Unknown SVC service number\n\r"); printf("- SVC number 0x%x\n\r", svc_number); #endif stop_cpu2; break; } // end switch // marking kernel as normal kernel_busy = 0; }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) { /* The port_extctx structure is pointed by the PSP register.*/ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsRescRequiredI()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ (void) __get_FPSCR(); #endif } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } #if CORTEX_USE_FPU { uint32_t fpccr; /* Saving the special register SCB_FPCCR into the reserved offset of the Cortex-M4 exception frame.*/ (ctxp + 1)->fpccr = (regarm_t)(fpccr = FPU->FPCCR); /* Now the FPCCR is modified in order to not restore the FPU status from the artificial return context.*/ FPU->FPCCR = fpccr | FPU_FPCCR_LSPACT_Msk; } #endif /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
/** * @brief PendSV vector. * @details The PendSV vector is used for exception mode re-entering after a * context switch. */ void PendSV_Handler(void) { /* The port_extctx structure is pointed by the PSP register.*/ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); }
void Init_Cpu(void) { __set_PSP((uint32_t)msp_top); __set_PRIMASK(1); __set_FAULTMASK(1); __set_CONTROL(0); switch(pg_scb_reg->CPUID) { case cn_revision_r0p0: break; //市场没有版本0的芯片 case cn_revision_r1p0: pg_scb_reg->CCR |= 1<<bo_scb_ccr_stkalign; break; case cn_revision_r1p1: pg_scb_reg->CCR |= 1<<bo_scb_ccr_stkalign; break; case cn_revision_r2p0:break; //好像没什么要做的 } pg_inflash_fpec_reg->ACR &= ~(u32)0x1f; pg_inflash_fpec_reg->ACR |= (CN_CFG_MCLK-1)/24000000; //设置等待周期。 pg_inflash_fpec_reg->ACR |= 0x10; //开启预取 if(((pg_rcc_reg->CR & cn_cr_check_mask) != cn_cr_check) || ((pg_rcc_reg->CFGR & cn_cfgr_check_mask) != cn_cfgr_check)) { //开始初始化时钟 //step1:复位时钟控制寄存器 pg_rcc_reg->CR |= (uint32_t)0x00000001; // 复位 SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] MCO[2:0] 位 pg_rcc_reg->CFGR &= (uint32_t)0xF8FF0000; // 复位 HSEON, CSSON and PLLON 位 pg_rcc_reg->CR &= (uint32_t)0xFEF6FFFF; // 复位 HSEBYP 位 pg_rcc_reg->CR &= (uint32_t)0xFFFBFFFF; // 复位 PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE 位 pg_rcc_reg->CFGR &= (uint32_t)0xFF80FFFF; // 禁止所有中断 pg_rcc_reg->CIR = 0x00000000; //step2:设置各时钟控制位以及倍频、分频值 pg_rcc_reg->CFGR = cn_cfgr_set+(7<<24); // set clock configuration register pg_rcc_reg->CR = cn_cr_set; // set clock control register while(bb_rcc_cr_hserdy ==0); while(bb_rcc_cr_pllrdy ==0); } SRAM_Init(); Load_Preload(); }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB_ICSR & ICSR_RETTOBASE) != 0) { struct extctx *ctxp; /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; __set_PSP((unsigned long)ctxp); ctxp->xpsr = (regarm_t)0x01000000; /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; #if CORTEX_USE_FPU /* Triggering a lazy FPU state save.*/ (void)__get_FPSCR(); #endif } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } #if CORTEX_USE_FPU { uint32_t fpccr; /* Saving the special register SCB_FPCCR into the reserved offset of the Cortex-M4 exception frame.*/ (ctxp + 1)->fpccr = (regarm_t)(fpccr = SCB_FPCCR); /* Now the FPCCR is modified in order to not restore the FPU status from the artificial return context.*/ SCB_FPCCR = fpccr | FPCCR_LSPACT; } #endif /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
void cmd_reset(void) { rt_uint32_t usrAddr = 0x08000000; typedef void (*funcPtr)(void); typedef volatile uint32_t vu32; __set_PRIMASK(0); //关闭所有中断,可以没有 if(((*(vu32*)usrAddr)&0x2FFE0000)==0x20000000) //判断地址是不是在RAM之内 { rt_uint32_t jumpAddr = *(vu32*) (usrAddr+0x04); /* reset ptr in vector table */ funcPtr usrMain1 = (funcPtr)jumpAddr; __set_PSP(*(vu32*)usrAddr); //设置堆栈指针 usrMain1(); /* go! */ } }
/** * @brief NMI vector. * @details The NMI vector is used for exception mode re-entering after a * context switch. */ void NMI_Handler(void) { /* The port_extctx structure is pointed by the PSP register.*/ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); /* Restoring the normal interrupts status.*/ port_unlock_from_isr(); }
/** * @brief PendSV vector. * @details The PendSV vector is used for exception mode re-entering after a * context switch. * @note The PendSV vector is only used in compact kernel mode. */ void PendSVVector(void) { struct extctx *ctxp; /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; #if CORTEX_USE_FPU /* Restoring the special register SCB_FPCCR.*/ SCB_FPCCR = (uint32_t)ctxp->fpccr; SCB_FPCAR = SCB_FPCAR + sizeof (struct extctx); #endif __set_PSP((unsigned long)ctxp); }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) { struct port_extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ (void) __get_FPSCR(); #endif /* The port_extctx structure is pointed by the PSP register.*/ ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; #if CORTEX_USE_FPU ctxp->fpscr = (regarm_t)FPU->FPDSCR; #endif /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
void Reset_Handler( void ) { #if main_stack_size + proc_stack_size > 0 /* Initialize the process stack pointer */ __set_PSP((unsigned)__initial_sp); __set_CONTROL(CONTROL_SPSEL_Msk); #endif #if __FPU_USED /* Set CP10 and CP11 Full Access */ SCB->CPACR = 0x00F00000U; #endif #ifndef __NO_SYSTEM_INIT /* Call the system clock intitialization function */ SystemInit(); #endif /* Call the application's entry point */ __main(); }
/** * @brief PendSV vector. * @details The PendSV vector is used for exception mode re-entering after a * context switch. * @note The PendSV vector is only used in compact kernel mode. */ void PendSV_Handler(void) { struct port_extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing unstacking of the FP part of the context.*/ FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; #endif /* The port_extctx structure is pointed by the PSP register.*/ ctxp = (struct port_extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); }
/** * @brief PendSV vector. * @details The PendSV vector is used for exception mode re-entering after a * context switch. * @note The PendSV vector is only used in compact kernel mode. */ void PendSVVector(void) { struct extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing unstacking of the FP part of the context.*/ SCB_FPCCR &= ~FPCCR_LSPACT; #endif /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; /* Restoring real position of the original stack frame.*/ __set_PSP((unsigned long)ctxp); }
/** * @brief PendSV vector. * @details The PendSV vector is used for exception mode re-entering after a * context switch. * @note The PendSV vector is only used in compact kernel mode. */ void PendSV_Handler(void) { /* The port_extctx structure is pointed by the PSP register.*/ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; #if CORTEX_USE_FPU /* Restoring the special register FPCCR.*/ FPU->FPCCR = (uint32_t)ctxp->fpccr; FPU->FPCAR = FPU->FPCAR + sizeof (struct port_extctx); #endif /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); }
void nOS_InitSpecific(void) { #if (NOS_CONFIG_DEBUG > 0) size_t i; for (i = 0; i < NOS_CONFIG_ISR_STACK_SIZE; i++) { _isrStack[i] = 0xFFFFFFFFUL; } #endif /* Copy MSP to PSP */ __set_PSP(__get_MSP()); /* Set MSP to local ISR stack */ __set_MSP((uint32_t)&_isrStack[NOS_CONFIG_ISR_STACK_SIZE] & 0xFFFFFFF8UL); /* Set current stack to PSP and privileged mode */ __set_CONTROL(__get_CONTROL() | 0x00000002UL); /* Set PendSV exception to lowest priority */ *(volatile uint32_t *)0xE000ED20UL |= 0x00FF0000UL; }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB_ICSR & ICSR_RETTOBASE) != 0) { struct extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save. Note, it goes in the original context because the FPCAR register has not been modified.*/ (void)__get_FPSCR(); #endif /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; ctxp->xpsr = (regarm_t)0x01000000; #if CORTEX_USE_FPU ctxp->fpscr = (regarm_t)SCB_FPDSCR; #endif __set_PSP((unsigned long)ctxp); /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
/** * Boots the image described by the supplied image header. * * @param hdr The header for the image to boot. */ void hal_system_start(void *img_start) { typedef void jump_fn(void); uint32_t base0entry; uint32_t jump_addr; jump_fn *fn; /* First word contains initial MSP value. */ __set_MSP(*(uint32_t *)img_start); __set_PSP(*(uint32_t *)img_start); /* Second word contains address of entry point (Reset_Handler). */ base0entry = *(uint32_t *)(img_start + 4); jump_addr = base0entry; fn = (jump_fn *)jump_addr; /* Jump to image. */ fn(); }
/** * @brief SVC vector. * @details The SVC vector is used for exception mode re-entering after a * context switch. * @note The PendSV vector is only used in advanced kernel mode. */ void SVC_Handler(void) { struct port_extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing unstacking of the FP part of the context.*/ FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; #endif /* The port_extctx structure is pointed by the PSP register.*/ ctxp = (struct port_extctx *)__get_PSP(); /* Discarding the current exception context and positioning the stack to point to the real one.*/ ctxp++; /* Restoring real position of the original stack frame.*/ __set_PSP((uint32_t)ctxp); /* Restoring the normal interrupts status.*/ port_unlock_from_isr(); }