Sergey Solodunov / nRF51822

Dependencies:   nrf51-sdk

Fork of nRF51822 by Nordic Semiconductor

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?

UserRevisionLine numberNew 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 }