テスト用です。

Dependencies:   mbed

Committer:
jksoft
Date:
Tue Oct 11 11:09:42 2016 +0000
Revision:
0:8468a4403fea
SB??ver;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jksoft 0:8468a4403fea 1 /* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
jksoft 0:8468a4403fea 2 *
jksoft 0:8468a4403fea 3 * The information contained herein is property of Nordic Semiconductor ASA.
jksoft 0:8468a4403fea 4 * Terms and conditions of usage are described in detail in NORDIC
jksoft 0:8468a4403fea 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
jksoft 0:8468a4403fea 6 *
jksoft 0:8468a4403fea 7 * Licensees are granted free, non-transferable use of the information. NO
jksoft 0:8468a4403fea 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
jksoft 0:8468a4403fea 9 * the file.
jksoft 0:8468a4403fea 10 *
jksoft 0:8468a4403fea 11 */
jksoft 0:8468a4403fea 12
jksoft 0:8468a4403fea 13 #include "bootloader_util.h"
jksoft 0:8468a4403fea 14 #include <stdint.h>
jksoft 0:8468a4403fea 15
jksoft 0:8468a4403fea 16
jksoft 0:8468a4403fea 17 /**
jksoft 0:8468a4403fea 18 * @brief Function for aborting current handler mode and jump to to other application/bootloader.
jksoft 0:8468a4403fea 19 *
jksoft 0:8468a4403fea 20 * @details This function will use the address provided (reset handler) to be executed after
jksoft 0:8468a4403fea 21 * handler mode is exited. It creates an initial stack to ensure correct reset behavior
jksoft 0:8468a4403fea 22 * when the reset handler is executed.
jksoft 0:8468a4403fea 23 *
jksoft 0:8468a4403fea 24 * @param[in] reset_handler Address of the reset handler to be executed when handler mode exits.
jksoft 0:8468a4403fea 25 *
jksoft 0:8468a4403fea 26 * @note This function must never be called directly from 'C' but is intended only to be used from
jksoft 0:8468a4403fea 27 * \ref bootloader_util_reset. This function will never return but issue a reset into
jksoft 0:8468a4403fea 28 * provided address.
jksoft 0:8468a4403fea 29 */
jksoft 0:8468a4403fea 30 #ifdef TOOLCHAIN_ARM
jksoft 0:8468a4403fea 31 __asm void isr_abort(uint32_t reset_handler)
jksoft 0:8468a4403fea 32 {
jksoft 0:8468a4403fea 33 xPSR_RESET EQU 0x21000000 ; Default value of xPSR after System Reset.
jksoft 0:8468a4403fea 34 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.
jksoft 0:8468a4403fea 35
jksoft 0:8468a4403fea 36 LDR R4,=MASK_ONES ; Fill with ones before jumping to reset handling. We be popped as R12 when exiting ISR (Cleaning up the registers).
jksoft 0:8468a4403fea 37 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.
jksoft 0:8468a4403fea 38 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.
jksoft 0:8468a4403fea 39 LDR R7,=xPSR_RESET ; Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR.
jksoft 0:8468a4403fea 40 PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR.
jksoft 0:8468a4403fea 41
jksoft 0:8468a4403fea 42 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).
jksoft 0:8468a4403fea 43 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).
jksoft 0:8468a4403fea 44 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).
jksoft 0:8468a4403fea 45 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).
jksoft 0:8468a4403fea 46 PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine.
jksoft 0:8468a4403fea 47
jksoft 0:8468a4403fea 48 LDR R0,=EXC_RETURN_CMD ; Load the execution return command into register.
jksoft 0:8468a4403fea 49 BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application.
jksoft 0:8468a4403fea 50 ALIGN
jksoft 0:8468a4403fea 51 }
jksoft 0:8468a4403fea 52 #elif defined(TOOLCHAIN_GCC)
jksoft 0:8468a4403fea 53 void isr_abort(uint32_t reset_handler)
jksoft 0:8468a4403fea 54 {
jksoft 0:8468a4403fea 55 asm(
jksoft 0:8468a4403fea 56 ".equ xPSR_RESET, 0x21000000 \n\t" /* Default value of xPSR after System Reset. */
jksoft 0:8468a4403fea 57 ".equ EXC_RETURN_CMD, 0xFFFFFFF9\n\t" /* EXC_RETURN for ARM Cortex. When loaded to PC the current interrupt
jksoft 0:8468a4403fea 58 * service routine (handler mode) willl exit and the stack will be
jksoft 0:8468a4403fea 59 * popped. Execution will continue in thread mode. */
jksoft 0:8468a4403fea 60
jksoft 0:8468a4403fea 61 "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). */
jksoft 0:8468a4403fea 62 "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. */
jksoft 0:8468a4403fea 63 "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. */
jksoft 0:8468a4403fea 64 "LDR R7,=xPSR_RESET\n\t" /* Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. */
jksoft 0:8468a4403fea 65 "PUSH {r4-r7} \n\t" /* Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. */
jksoft 0:8468a4403fea 66
jksoft 0:8468a4403fea 67 "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). */
jksoft 0:8468a4403fea 68 "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). */
jksoft 0:8468a4403fea 69 "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). */
jksoft 0:8468a4403fea 70 "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). */
jksoft 0:8468a4403fea 71 "PUSH {r4-r7} \n\t" /* Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. */
jksoft 0:8468a4403fea 72
jksoft 0:8468a4403fea 73 "LDR R0,=EXC_RETURN_CMD\n\t" /* Load the execution return command into register. */
jksoft 0:8468a4403fea 74 "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. */
jksoft 0:8468a4403fea 75 );
jksoft 0:8468a4403fea 76 }
jksoft 0:8468a4403fea 77 #endif /* TOOLCHAIN_ARM */
jksoft 0:8468a4403fea 78
jksoft 0:8468a4403fea 79 /**
jksoft 0:8468a4403fea 80 * @brief Function for aborting current application/bootloader jump to to other app/bootloader.
jksoft 0:8468a4403fea 81 *
jksoft 0:8468a4403fea 82 * @details This function will use the address provided to swap the stack pointer and then load
jksoft 0:8468a4403fea 83 * the address of the reset handler to be executed. It will check current system mode
jksoft 0:8468a4403fea 84 * (thread/handler) and if in thread mode it will reset into other application.
jksoft 0:8468a4403fea 85 * If in handler mode \ref isr_abort will be executed to ensure correct exit of handler
jksoft 0:8468a4403fea 86 * mode and jump into reset handler of other application.
jksoft 0:8468a4403fea 87 *
jksoft 0:8468a4403fea 88 * @param[in] start_addr Start address of other application. This address must point to the
jksoft 0:8468a4403fea 89 initial stack pointer of the application.
jksoft 0:8468a4403fea 90 *
jksoft 0:8468a4403fea 91 * @note This function will never return but issue a reset into provided application.
jksoft 0:8468a4403fea 92 */
jksoft 0:8468a4403fea 93 #ifdef TOOLCHAIN_ARM
jksoft 0:8468a4403fea 94 __asm static void bootloader_util_reset(uint32_t start_addr)
jksoft 0:8468a4403fea 95 {
jksoft 0:8468a4403fea 96 MASK_ONES EQU 0xFFFFFFFF ; Ones, to be loaded into register as default value before reset.
jksoft 0:8468a4403fea 97 MASK_ZEROS EQU 0x00000000 ; Zeros, to be loaded into register as default value before reset.
jksoft 0:8468a4403fea 98
jksoft 0:8468a4403fea 99 LDR R1, [R0] ; Get App initial MSP for bootloader.
jksoft 0:8468a4403fea 100 MSR MSP, R1 ; Set the main stack pointer to the applications MSP.
jksoft 0:8468a4403fea 101 LDR R0,[R0, #0x04] ; Load Reset handler into register 0.
jksoft 0:8468a4403fea 102
jksoft 0:8468a4403fea 103 LDR R2, =MASK_ZEROS ; Load zeros to R2
jksoft 0:8468a4403fea 104 MRS R3, IPSR ; Load IPSR to R3 to check for handler or thread mode
jksoft 0:8468a4403fea 105 CMP R2, R3 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader
jksoft 0:8468a4403fea 106 BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader
jksoft 0:8468a4403fea 107
jksoft 0:8468a4403fea 108 LDR R4, =MASK_ONES ; Load ones to R4 to be placed in Link Register.
jksoft 0:8468a4403fea 109 MOV LR, R4 ; Clear the link register and set to ones to ensure no return.
jksoft 0:8468a4403fea 110 BX R0 ; Branch to reset handler of bootloader
jksoft 0:8468a4403fea 111 ALIGN
jksoft 0:8468a4403fea 112 }
jksoft 0:8468a4403fea 113 #elif defined(TOOLCHAIN_GCC)
jksoft 0:8468a4403fea 114 static void bootloader_util_reset(uint32_t start_addr)
jksoft 0:8468a4403fea 115 {
jksoft 0:8468a4403fea 116 asm(
jksoft 0:8468a4403fea 117 ".equ MASK_ONES, 0xFFFFFFFF\n\t" /* Ones, to be loaded into register as default value before reset. */
jksoft 0:8468a4403fea 118 ".equ MASK_ZEROS, 0x00000000\n\t" /* Zeros, to be loaded into register as default value before reset. */
jksoft 0:8468a4403fea 119
jksoft 0:8468a4403fea 120 "LDR r1, [r0] \n\t" /* Get App initial MSP for bootloader. */
jksoft 0:8468a4403fea 121 "MSR MSP, r1 \n\t" /* Set the main stack pointer to the applications MSP. */
jksoft 0:8468a4403fea 122 "LDR r0,[r0, #0x04] \n\t" /* Load Reset handler into register 0. */
jksoft 0:8468a4403fea 123
jksoft 0:8468a4403fea 124 "LDR r2, =MASK_ZEROS\n\t" /* Load zeros to R2 */
jksoft 0:8468a4403fea 125 "MRS r3, IPSR \n\t" /* Load IPSR to R3 to check for handler or thread mode */
jksoft 0:8468a4403fea 126 "CMP r2, r3 \n\t" /* Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader */
jksoft 0:8468a4403fea 127 "BNE isr_abort \n\t" /* If not zero we need to exit current ISR and jump to reset handler of bootloader */
jksoft 0:8468a4403fea 128
jksoft 0:8468a4403fea 129 "LDR r4, =MASK_ONES \n\t" /* Load ones to R4 to be placed in Link Register. */
jksoft 0:8468a4403fea 130 "MOV LR, r4 \n\t" /* Clear the link register and set to ones to ensure no return. */
jksoft 0:8468a4403fea 131 "BX r0 \n\t" /* Branch to reset handler of bootloader */
jksoft 0:8468a4403fea 132 : /* output operands */
jksoft 0:8468a4403fea 133 : /* input operands */
jksoft 0:8468a4403fea 134 : "r0", "r1", "r2", "r3", "r4" /* clobber list */
jksoft 0:8468a4403fea 135 );
jksoft 0:8468a4403fea 136 }
jksoft 0:8468a4403fea 137 #endif /* TOOLCHAIN_ARM */
jksoft 0:8468a4403fea 138
jksoft 0:8468a4403fea 139 void bootloader_util_app_start(uint32_t start_addr)
jksoft 0:8468a4403fea 140 {
jksoft 0:8468a4403fea 141 bootloader_util_reset(start_addr);
jksoft 0:8468a4403fea 142 }