Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
source/nordic-sdk/components/libraries/bootloader_dfu/bootloader_util_arm.c@541:884f95bf5351, 2016-01-11 (annotated)
- Committer:
- vcoubard
- Date:
- Mon Jan 11 10:19:02 2016 +0000
- Revision:
- 541:884f95bf5351
- Child:
- 546:1e147322b2b5
Synchronized with git rev 60a7c0c0
Author: Rohit Grover
bring in the latest changes for BLE::init() where we allow <object, member> tuples for init callback.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vcoubard | 541:884f95bf5351 | 1 | /* |
vcoubard | 541:884f95bf5351 | 2 | * Copyright (c) Nordic Semiconductor ASA |
vcoubard | 541:884f95bf5351 | 3 | * All rights reserved. |
vcoubard | 541:884f95bf5351 | 4 | * |
vcoubard | 541:884f95bf5351 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
vcoubard | 541:884f95bf5351 | 6 | * are permitted provided that the following conditions are met: |
vcoubard | 541:884f95bf5351 | 7 | * |
vcoubard | 541:884f95bf5351 | 8 | * 1. Redistributions of source code must retain the above copyright notice, this |
vcoubard | 541:884f95bf5351 | 9 | * list of conditions and the following disclaimer. |
vcoubard | 541:884f95bf5351 | 10 | * |
vcoubard | 541:884f95bf5351 | 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this |
vcoubard | 541:884f95bf5351 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
vcoubard | 541:884f95bf5351 | 13 | * other materials provided with the distribution. |
vcoubard | 541:884f95bf5351 | 14 | * |
vcoubard | 541:884f95bf5351 | 15 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of other |
vcoubard | 541:884f95bf5351 | 16 | * contributors to this software may be used to endorse or promote products |
vcoubard | 541:884f95bf5351 | 17 | * derived from this software without specific prior written permission. |
vcoubard | 541:884f95bf5351 | 18 | * |
vcoubard | 541:884f95bf5351 | 19 | * |
vcoubard | 541:884f95bf5351 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
vcoubard | 541:884f95bf5351 | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
vcoubard | 541:884f95bf5351 | 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
vcoubard | 541:884f95bf5351 | 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
vcoubard | 541:884f95bf5351 | 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
vcoubard | 541:884f95bf5351 | 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
vcoubard | 541:884f95bf5351 | 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
vcoubard | 541:884f95bf5351 | 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
vcoubard | 541:884f95bf5351 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
vcoubard | 541:884f95bf5351 | 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
vcoubard | 541:884f95bf5351 | 30 | * |
vcoubard | 541:884f95bf5351 | 31 | */ |
vcoubard | 541:884f95bf5351 | 32 | #include "compiler_abstraction.h" |
vcoubard | 541:884f95bf5351 | 33 | #include "bootloader_util.h" |
vcoubard | 541:884f95bf5351 | 34 | #include <stdint.h> |
vcoubard | 541:884f95bf5351 | 35 | #include <string.h> |
vcoubard | 541:884f95bf5351 | 36 | |
vcoubard | 541:884f95bf5351 | 37 | /** |
vcoubard | 541:884f95bf5351 | 38 | * @brief Function for aborting current application/bootloader jump to to other app/bootloader. |
vcoubard | 541:884f95bf5351 | 39 | * |
vcoubard | 541:884f95bf5351 | 40 | * @details This functions will use the address provide to swap the stack pointer and then load |
vcoubard | 541:884f95bf5351 | 41 | * the address of the reset handler to be executed. It will check current system mode |
vcoubard | 541:884f95bf5351 | 42 | * (thread/handler) and if in thread mode it will reset into other application. |
vcoubard | 541:884f95bf5351 | 43 | * If in handler mode \ref isr_abort will be executed to ensure correct exit of handler |
vcoubard | 541:884f95bf5351 | 44 | * mode and jump into reset handler of other application. |
vcoubard | 541:884f95bf5351 | 45 | * |
vcoubard | 541:884f95bf5351 | 46 | * @param[in] start_addr Start address of other application. This address must point to the |
vcoubard | 541:884f95bf5351 | 47 | initial stack pointer of the application. |
vcoubard | 541:884f95bf5351 | 48 | * |
vcoubard | 541:884f95bf5351 | 49 | * @note This function will never return but issue a reset into provided application. |
vcoubard | 541:884f95bf5351 | 50 | */ |
vcoubard | 541:884f95bf5351 | 51 | #ifdef TOOLCHAIN_ARM |
vcoubard | 541:884f95bf5351 | 52 | __asm static void bootloader_util_reset(uint32_t start_addr) |
vcoubard | 541:884f95bf5351 | 53 | { |
vcoubard | 541:884f95bf5351 | 54 | MASK_ONES EQU 0xFFFFFFFF ; Ones, to be loaded into register as default value before reset. |
vcoubard | 541:884f95bf5351 | 55 | MASK_ZEROS EQU 0x00000000 ; Zeros, to be loaded into register as default value before reset. |
vcoubard | 541:884f95bf5351 | 56 | xPSR_RESET EQU 0x21000000 ; Default value of xPSR after System Reset. |
vcoubard | 541:884f95bf5351 | 57 | 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. |
vcoubard | 541:884f95bf5351 | 58 | LDR R5, [R0] ; Get App initial MSP for bootloader. |
vcoubard | 541:884f95bf5351 | 59 | MSR MSP, R5 ; Set the main stack pointer to the applications MSP. |
vcoubard | 541:884f95bf5351 | 60 | LDR R6, [R0, #0x04] ; Load Reset handler into register 6. |
vcoubard | 541:884f95bf5351 | 61 | |
vcoubard | 541:884f95bf5351 | 62 | LDR R2, =MASK_ZEROS ; Load zeros to R2 |
vcoubard | 541:884f95bf5351 | 63 | MRS R3, IPSR ; Load IPSR to R3 to check for handler or thread mode |
vcoubard | 541:884f95bf5351 | 64 | CMP R2, R3 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader |
vcoubard | 541:884f95bf5351 | 65 | MOV R0, R6 |
vcoubard | 541:884f95bf5351 | 66 | BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader |
vcoubard | 541:884f95bf5351 | 67 | |
vcoubard | 541:884f95bf5351 | 68 | LDR R4, =MASK_ONES ; Load ones to R4 to be placed in Link Register. |
vcoubard | 541:884f95bf5351 | 69 | MOV LR, R4 ; Clear the link register and set to ones to ensure no return. |
vcoubard | 541:884f95bf5351 | 70 | BX R6 ; Branch to reset handler of bootloader |
vcoubard | 541:884f95bf5351 | 71 | isr_abort |
vcoubard | 541:884f95bf5351 | 72 | LDR R4,=MASK_ONES ; Fill with ones before jumping to reset handling. We be popped as R12 when exiting ISR (Cleaning up the registers). |
vcoubard | 541:884f95bf5351 | 73 | 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. |
vcoubard | 541:884f95bf5351 | 74 | 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. |
vcoubard | 541:884f95bf5351 | 75 | LDR R7,=xPSR_RESET ; Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. |
vcoubard | 541:884f95bf5351 | 76 | PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. |
vcoubard | 541:884f95bf5351 | 77 | |
vcoubard | 541:884f95bf5351 | 78 | 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). |
vcoubard | 541:884f95bf5351 | 79 | 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). |
vcoubard | 541:884f95bf5351 | 80 | 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). |
vcoubard | 541:884f95bf5351 | 81 | 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). |
vcoubard | 541:884f95bf5351 | 82 | PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. |
vcoubard | 541:884f95bf5351 | 83 | |
vcoubard | 541:884f95bf5351 | 84 | LDR R0,=EXC_RETURN_CMD ; Load the execution return command into register. |
vcoubard | 541:884f95bf5351 | 85 | BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application. |
vcoubard | 541:884f95bf5351 | 86 | ALIGN |
vcoubard | 541:884f95bf5351 | 87 | } |
vcoubard | 541:884f95bf5351 | 88 | #elif defined(TOOLCHAIN_GCC) |
vcoubard | 541:884f95bf5351 | 89 | static void bootloader_util_reset(uint32_t start_addr) |
vcoubard | 541:884f95bf5351 | 90 | { |
vcoubard | 541:884f95bf5351 | 91 | __ASM( |
vcoubard | 541:884f95bf5351 | 92 | ".equ MASK_ONES, 0xFFFFFFFF\n\t" /* Ones, to be loaded into register as default value before reset. */ |
vcoubard | 541:884f95bf5351 | 93 | ".equ MASK_ZEROS, 0x00000000\n\t" /* Zeros, to be loaded into register as default value before reset. */ |
vcoubard | 541:884f95bf5351 | 94 | ".equ xPSR_RESET, 0x21000000\n\t" /* Default value of xPSR after System Reset. */ |
vcoubard | 541:884f95bf5351 | 95 | ".equ EXC_RETURN_CMD, 0xFFFFFFF9\n\t" /* 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. */ |
vcoubard | 541:884f95bf5351 | 96 | |
vcoubard | 541:884f95bf5351 | 97 | "LDR r5, [r0] \n\t" /* Get App initial MSP for bootloader. */ |
vcoubard | 541:884f95bf5351 | 98 | "MSR MSP, r5 \n\t" /* Set the main stack pointer to the applications MSP. */ |
vcoubard | 541:884f95bf5351 | 99 | "LDR r6,[r0, #0x04] \n\t" /* Load Reset handler into register 0. */ |
vcoubard | 541:884f95bf5351 | 100 | |
vcoubard | 541:884f95bf5351 | 101 | "LDR r2, =MASK_ZEROS\n\t" /* Load zeros to R2 */ |
vcoubard | 541:884f95bf5351 | 102 | "MRS r3, IPSR \n\t" /* Load IPSR to R3 to check for handler or thread mode */ |
vcoubard | 541:884f95bf5351 | 103 | "CMP r2, r3 \n\t" /* Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader */ |
vcoubard | 541:884f95bf5351 | 104 | "MOV R0, R6 \n\t" |
vcoubard | 541:884f95bf5351 | 105 | "BNE isr_abort \n\t" /* If not zero we need to exit current ISR and jump to reset handler of bootloader */ |
vcoubard | 541:884f95bf5351 | 106 | |
vcoubard | 541:884f95bf5351 | 107 | "LDR r4, =MASK_ONES \n\t" /* Load ones to R4 to be placed in Link Register. */ |
vcoubard | 541:884f95bf5351 | 108 | "MOV LR, r4 \n\t" /* Clear the link register and set to ones to ensure no return. */ |
vcoubard | 541:884f95bf5351 | 109 | "BX r6 \n\t" /* Branch to reset handler of bootloader */ |
vcoubard | 541:884f95bf5351 | 110 | "isr_abort: \n\t" |
vcoubard | 541:884f95bf5351 | 111 | "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). */ |
vcoubard | 541:884f95bf5351 | 112 | "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. */ |
vcoubard | 541:884f95bf5351 | 113 | "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. */ |
vcoubard | 541:884f95bf5351 | 114 | "LDR R7,=xPSR_RESET\n\t" /* Move reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. */ |
vcoubard | 541:884f95bf5351 | 115 | "PUSH {r4-r7} \n\t" /* Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR. */ |
vcoubard | 541:884f95bf5351 | 116 | |
vcoubard | 541:884f95bf5351 | 117 | "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). */ |
vcoubard | 541:884f95bf5351 | 118 | "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). */ |
vcoubard | 541:884f95bf5351 | 119 | "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). */ |
vcoubard | 541:884f95bf5351 | 120 | "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). */ |
vcoubard | 541:884f95bf5351 | 121 | "PUSH {r4-r7} \n\t" /* Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine. */ |
vcoubard | 541:884f95bf5351 | 122 | |
vcoubard | 541:884f95bf5351 | 123 | "LDR R0,=EXC_RETURN_CMD\n\t" /* Load the execution return command into register. */ |
vcoubard | 541:884f95bf5351 | 124 | "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. */ |
vcoubard | 541:884f95bf5351 | 125 | : /* output operands */ |
vcoubard | 541:884f95bf5351 | 126 | : /* input operands */ |
vcoubard | 541:884f95bf5351 | 127 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" /* clobber list */ |
vcoubard | 541:884f95bf5351 | 128 | ); |
vcoubard | 541:884f95bf5351 | 129 | } |
vcoubard | 541:884f95bf5351 | 130 | #endif /* TOOLCHAIN_ARM */ |
vcoubard | 541:884f95bf5351 | 131 | |
vcoubard | 541:884f95bf5351 | 132 | void bootloader_util_app_start(uint32_t start_addr) |
vcoubard | 541:884f95bf5351 | 133 | { |
vcoubard | 541:884f95bf5351 | 134 | bootloader_util_reset(start_addr); |
vcoubard | 541:884f95bf5351 | 135 | } |