Wallbot_CaaS
Dependencies: MPU6050 mbed PID
Fork of BLE_MPU6050_test6_challenge_sb by
bootloader_util_arm.c
00001 /* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved. 00002 * 00003 * The information contained herein is property of Nordic Semiconductor ASA. 00004 * Terms and conditions of usage are described in detail in NORDIC 00005 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 00006 * 00007 * Licensees are granted free, non-transferable use of the information. NO 00008 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 00009 * the file. 00010 * 00011 */ 00012 00013 #include "bootloader_util.h " 00014 #include <stdint.h> 00015 00016 00017 /** 00018 * @brief Function for aborting current handler mode and jump to to other application/bootloader. 00019 * 00020 * @details This function will use the address provided (reset handler) to be executed after 00021 * handler mode is exited. It creates an initial stack to ensure correct reset behavior 00022 * when the reset handler is executed. 00023 * 00024 * @param[in] reset_handler Address of the reset handler to be executed when handler mode exits. 00025 * 00026 * @note This function must never be called directly from 'C' but is intended only to be used from 00027 * \ref bootloader_util_reset. This function will never return but issue a reset into 00028 * provided address. 00029 */ 00030 #ifdef TOOLCHAIN_ARM 00031 __asm void isr_abort(uint32_t reset_handler) 00032 { 00033 xPSR_RESET EQU 0x21000000 ; Default value of xPSR after System Reset. 00034 EXC_RETURN_CMD EQU 0xFFFFFFF9 ; EXC_RETURN for ARM Cortex. When loaded to PC the current interrupt service routine (handler mode) willl exit and the stack will be popped. Execution will continue in thread mode. 00035 00036 LDR R4,=MASK_ONES ; Fill with ones before jumping to reset handling. We be popped as R12 when exiting ISR (Cleaning up the registers). 00037 LDR R5,=MASK_ONES ; Fill with ones before jumping to reset handling. We be popped as LR when exiting ISR. Ensures no return to application. 00038 MOV R6, R0 ; Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. 00039 LDR R7,=xPSR_RESET ; Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. 00040 PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. 00041 00042 LDR R4,=MASK_ZEROS ; Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). 00043 LDR R5,=MASK_ZEROS ; Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). 00044 LDR R6,=MASK_ZEROS ; Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). 00045 LDR R7,=MASK_ZEROS ; Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). 00046 PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. 00047 00048 LDR R0,=EXC_RETURN_CMD ; Load the execution return command into register. 00049 BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. 00050 ALIGN 00051 } 00052 #elif defined(TOOLCHAIN_GCC) 00053 void isr_abort(uint32_t reset_handler) 00054 { 00055 asm( 00056 ".equ xPSR_RESET, 0x21000000 \n\t" /* Default value of xPSR after System Reset. */ 00057 ".equ EXC_RETURN_CMD, 0xFFFFFFF9\n\t" /* EXC_RETURN for ARM Cortex. When loaded to PC the current interrupt 00058 * service routine (handler mode) willl exit and the stack will be 00059 * popped. Execution will continue in thread mode. */ 00060 00061 "LDR R4,=MASK_ONES \n\t" /* Fill with ones before jumping to reset handling. We be popped as R12 when exiting ISR (Cleaning up the registers). */ 00062 "LDR R5,=MASK_ONES \n\t" /* Fill with ones before jumping to reset handling. We be popped as LR when exiting ISR. Ensures no return to application. */ 00063 "MOV R6, R0 \n\t" /* Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR. */ 00064 "LDR R7,=xPSR_RESET\n\t" /* Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. */ 00065 "PUSH {r4-r7} \n\t" /* Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. */ 00066 00067 "LDR R4,=MASK_ZEROS\n\t" /* Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers). */ 00068 "LDR R5,=MASK_ZEROS\n\t" /* Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers). */ 00069 "LDR R6,=MASK_ZEROS\n\t" /* Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers). */ 00070 "LDR R7,=MASK_ZEROS\n\t" /* Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers). */ 00071 "PUSH {r4-r7} \n\t" /* Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. */ 00072 00073 "LDR R0,=EXC_RETURN_CMD\n\t" /* Load the execution return command into register. */ 00074 "BX R0 \n\t" /* No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. */ 00075 ); 00076 } 00077 #endif /* TOOLCHAIN_ARM */ 00078 00079 /** 00080 * @brief Function for aborting current application/bootloader jump to to other app/bootloader. 00081 * 00082 * @details This function will use the address provided to swap the stack pointer and then load 00083 * the address of the reset handler to be executed. It will check current system mode 00084 * (thread/handler) and if in thread mode it will reset into other application. 00085 * If in handler mode \ref isr_abort will be executed to ensure correct exit of handler 00086 * mode and jump into reset handler of other application. 00087 * 00088 * @param[in] start_addr Start address of other application. This address must point to the 00089 initial stack pointer of the application. 00090 * 00091 * @note This function will never return but issue a reset into provided application. 00092 */ 00093 #ifdef TOOLCHAIN_ARM 00094 __asm static void bootloader_util_reset(uint32_t start_addr) 00095 { 00096 MASK_ONES EQU 0xFFFFFFFF ; Ones, to be loaded into register as default value before reset. 00097 MASK_ZEROS EQU 0x00000000 ; Zeros, to be loaded into register as default value before reset. 00098 00099 LDR R1, [R0] ; Get App initial MSP for bootloader. 00100 MSR MSP, R1 ; Set the main stack pointer to the applications MSP. 00101 LDR R0,[R0, #0x04] ; Load Reset handler into register 0. 00102 00103 LDR R2, =MASK_ZEROS ; Load zeros to R2 00104 MRS R3, IPSR ; Load IPSR to R3 to check for handler or thread mode 00105 CMP R2, R3 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader 00106 BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader 00107 00108 LDR R4, =MASK_ONES ; Load ones to R4 to be placed in Link Register. 00109 MOV LR, R4 ; Clear the link register and set to ones to ensure no return. 00110 BX R0 ; Branch to reset handler of bootloader 00111 ALIGN 00112 } 00113 #elif defined(TOOLCHAIN_GCC) 00114 static void bootloader_util_reset(uint32_t start_addr) 00115 { 00116 asm( 00117 ".equ MASK_ONES, 0xFFFFFFFF\n\t" /* Ones, to be loaded into register as default value before reset. */ 00118 ".equ MASK_ZEROS, 0x00000000\n\t" /* Zeros, to be loaded into register as default value before reset. */ 00119 00120 "LDR r1, [r0] \n\t" /* Get App initial MSP for bootloader. */ 00121 "MSR MSP, r1 \n\t" /* Set the main stack pointer to the applications MSP. */ 00122 "LDR r0,[r0, #0x04] \n\t" /* Load Reset handler into register 0. */ 00123 00124 "LDR r2, =MASK_ZEROS\n\t" /* Load zeros to R2 */ 00125 "MRS r3, IPSR \n\t" /* Load IPSR to R3 to check for handler or thread mode */ 00126 "CMP r2, r3 \n\t" /* Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader */ 00127 "BNE isr_abort \n\t" /* If not zero we need to exit current ISR and jump to reset handler of bootloader */ 00128 00129 "LDR r4, =MASK_ONES \n\t" /* Load ones to R4 to be placed in Link Register. */ 00130 "MOV LR, r4 \n\t" /* Clear the link register and set to ones to ensure no return. */ 00131 "BX r0 \n\t" /* Branch to reset handler of bootloader */ 00132 : /* output operands */ 00133 : /* input operands */ 00134 : "r0", "r1", "r2", "r3", "r4" /* clobber list */ 00135 ); 00136 } 00137 #endif /* TOOLCHAIN_ARM */ 00138 00139 void bootloader_util_app_start(uint32_t start_addr) 00140 { 00141 bootloader_util_reset(start_addr); 00142 }
Generated on Tue Jul 12 2022 18:33:09 by 1.7.2