staticdfu_ble_peer_data_tm_peer_data__attribute__((section("NoInit"),zero_init));/**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
staticuint16_tm_peer_data_crc__attribute__((section("NoInit"),zero_init));/**< CRC variable to ensure the integrity of the peer data provided. */
#elif defined ( __GNUC__ )
__attribute__((section(".noinit")))staticdfu_ble_peer_data_tm_peer_data;/**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
__attribute__((section(".noinit")))staticuint16_tm_peer_data_crc;/**< CRC variable to ensure the integrity of the peer data provided. */
#elif defined ( __ICCARM__ )
__no_initstaticdfu_ble_peer_data_tm_peer_data@0x20003F80;/**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
__no_initstaticuint16_tm_peer_data_crc@0x20003F80+sizeof(dfu_ble_peer_data_t);/**< CRC variable to ensure the integrity of the peer data provided. */
#endif
/**@brief Function for setting the peer data from application in bootloader before reset.
constuint32_texc_return=0xFFFFFFFD;// EXC_RETURN using PSP for ARM Cortex. If Link register contains this value it indicates the PSP was used before the SVC, otherwise the MSP was used.
__asmvolatile(
"cmp lr, %0\t\n"// Compare the link register with argument 0 (%0), which is exc_return. If equal then PSP was used, otherwise MSP was used before SVC.
"bne UseMSP\t\n"// Branch to code fetching SVC arguments using MSP.
"mrs r1, psp\t\n"// Move PSP into R1.
"b Call_C_SVC_Handler\t\n"// Branch to Call_C_SVC_Handler below.
"UseMSP: \t\n"//
"mrs r1, msp\t\n"// MSP was used, therefore Move MSP into R1.
"Call_C_SVC_Handler: \t\n"//
"ldr r0, [r1, #24]\t\n"// The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR.
// R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.
"sub r0, r0, #2\t\n"// The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.
"ldrb r0, [r0]\t\n"// SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.
"bx %1\t\n"// Branch to C implementation of SVC handler, argument 1 (%1). R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.
".align\t\n"
::"r"(exc_return),"r"(C_SVC_Handler)// Argument list for the gcc assembly. exc_return is %0, C_SVC_Handler is %1.
:"r0","r1"// List of register maintained manually.
);
}
#elif defined ( __ICCARM__ )
voidSVC_Handler(void)
{
asm("movs r0, #0x02\n"// Load 0x02 into R6 to prepare for exec return test.
"mvns r0, r0\n"// Invert R0 to obtain exec return code using PSP for ARM Cortex.
"cmp lr, r0\n"// Compare the link register with argument 0 (%0), which is exc_return. If equal then PSP was used, otherwise MSP was used before SVC.
"bne.n UseMSP\n"// Branch to code fetching SVC arguments using MSP.
"mrs r1, psp\n"// Move PSP into R1.
"b.n Call_C_SVC_Handler\t\n"// Branch to Call_C_SVC_Handler below.
"UseMSP: \n"//
"mrs r1, msp\n"// MSP was used, therefore Move MSP into R1.
"Call_C_SVC_Handler: \n"//
"ldr r0, [r1, #24]\n"// The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR.
// R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.
"subs r0, #0x02\n"// The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.
"ldrb r0, [r0]\n"// SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.
"bx %0\n"// Branch to C implementation of SVC handler, argument 1 (%1). R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.
::"r"(C_SVC_Handler)// Argument list for the gcc assembly. C_SVC_Handler is %0.
:"r0","r1"// List of register maintained manually.