7070#include "sam_ba_usb.h"
7171#include "sam_ba_cdc.h"
7272
73- extern uint32_t __app_start_address ;
73+ extern uint32_t __sketch_stackptr ; // Exported value from linker script
7474extern void board_init (void );
7575
76- //static void check_start_application(void);
76+ #if (defined DEBUG ) && (DEBUG == 1 )
77+ volatile uint32_t * pulSketch_Start_Address ;
78+ #endif
7779
7880static volatile bool main_b_cdc_enable = false;
7981
@@ -105,7 +107,9 @@ static void check_start_application(void)
105107 /* First tap */
106108 BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC ;
107109
108- /* Wait 0.5sec to see if the user tap reset again */
110+ /* Wait 0.5sec to see if the user tap reset again.
111+ * The loop value is based on SAMD21 default 1MHz clock @ reset.
112+ */
109113 for (uint32_t i = 0 ; i < 125000 ; i ++ ) /* 500ms */
110114 /* force compiler to not optimize this... */
111115 __asm__ __volatile__("" );
@@ -115,51 +119,71 @@ static void check_start_application(void)
115119 }
116120#endif
117121
118- uint32_t app_start_address ;
122+ #if (!defined DEBUG ) || ((defined DEBUG ) && (DEBUG == 0 ))
123+ uint32_t * pulSketch_Start_Address ;
124+ #endif
119125
120- /* Load the Reset Handler address of the application */
121- app_start_address = * (uint32_t * )(& __app_start_address + 4 );
126+ /*
127+ * Test sketch stack pointer @ &__sketch_stackptr
128+ * Stay in SAM-BA if value @ (&__sketch_stackptr) == 0xFFFFFFFF (Erased flash cell value)
129+ */
130+ if (__sketch_stackptr == 0xFFFFFFFF )
131+ {
132+ /* Stay in bootloader */
133+ return ;
134+ }
135+
136+ /*
137+ * Load the sketch Reset Handler address
138+ * __sketch_stackptr is exported from linker script and point on first 32b word of sketch vector table
139+ * First 32b word is sketch stack
140+ * Second 32b word is sketch entry point: Reset_Handler()
141+ */
142+ pulSketch_Start_Address = & __sketch_stackptr ;
143+ pulSketch_Start_Address ++ ;
122144
123- /**
124- * Test reset vector of application @__app_start_address +4
125- * Stay in SAM-BA if *(__app_start_address+0x4) == 0xFFFFFFFF
126- * Application erased condition
145+ /*
146+ * Test reset vector of sketch @ &__sketch_stackptr +4
147+ * Stay in SAM-BA if this function is not aligned enough, ie not valid
148+ * The value 0x01 is the 'Thumb mode' bit added by linker.
127149 */
128- if (app_start_address == 0xFFFFFFFF )
150+ if ( ( * pulSketch_Start_Address & ~ SCB_VTOR_TBLOFF_Msk ) != 0x01 )
129151 {
130152 /* Stay in bootloader */
131153 return ;
132154 }
133155
156+ /*
134157#if defined(BOOT_LOAD_PIN)
135158 volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32]));
136159 volatile bool boot_en;
137160
138- /* Enable the input mode in Boot GPIO Pin */
161+ // Enable the input mode in Boot GPIO Pin
139162 boot_port->DIRCLR.reg = BOOT_PIN_MASK;
140163 boot_port->PINCFG[BOOT_LOAD_PIN & 0x1F].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN;
141164 boot_port->OUTSET.reg = BOOT_PIN_MASK;
142- /* Read the BOOT_LOAD_PIN status */
165+ // Read the BOOT_LOAD_PIN status
143166 boot_en = (boot_port->IN.reg) & BOOT_PIN_MASK;
144167
145- /* Check the bootloader enable condition */
168+ // Check the bootloader enable condition
146169 if (!boot_en)
147170 {
148- /* Stay in bootloader */
171+ // Stay in bootloader
149172 return;
150173 }
151174#endif
175+ */
152176
153177 LED_on ();
154178
155179 /* Rebase the Stack Pointer */
156- __set_MSP (* (uint32_t * ) & __app_start_address );
180+ __set_MSP ( (uint32_t )( * ( pulSketch_Start_Address - 1 )) );
157181
158182 /* Rebase the vector table base address */
159- SCB -> VTOR = ((uint32_t ) & __app_start_address & SCB_VTOR_TBLOFF_Msk );
183+ SCB -> VTOR = ((uint32_t )( pulSketch_Start_Address - 1 ) & SCB_VTOR_TBLOFF_Msk );
160184
161185 /* Jump to application Reset Handler in the application */
162- asm("bx %0" ::"r" (app_start_address ));
186+ asm("bx %0" ::"r" (* pulSketch_Start_Address ));
163187}
164188
165189#if DEBUG_ENABLE
0 commit comments