1 #include <alloca.h>
2 #include <stdbool.h>
3 #include <string.h>
4
5 #include <variant/variant.h>
6
7 #include <plat/pwr.h>
8 #include <plat/gpio.h>
9 #include <plat/cmsis.h>
10
11 #include <bl.h>
12
13 struct StmUdid
14 {
15 volatile uint32_t U_ID[3];
16 };
17
18 struct StmSpi {
19 volatile uint32_t CR1;
20 volatile uint32_t CR2;
21 volatile uint32_t SR;
22 volatile uint32_t DR;
23 volatile uint32_t CRCPR;
24 volatile uint32_t RXCRCR;
25 volatile uint32_t TXCRCR;
26 volatile uint32_t I2SCFGR;
27 volatile uint32_t I2SPR;
28 };
29
30 struct StmGpio {
31 volatile uint32_t MODER;
32 volatile uint32_t OTYPER;
33 volatile uint32_t OSPEEDR;
34 volatile uint32_t PUPDR;
35 volatile uint32_t IDR;
36 volatile uint32_t ODR;
37 volatile uint32_t BSRR;
38 volatile uint32_t LCKR;
39 volatile uint32_t AFR[2];
40 };
41
42 struct StmFlash
43 {
44 volatile uint32_t ACR;
45 volatile uint32_t KEYR;
46 volatile uint32_t OPTKEYR;
47 volatile uint32_t SR;
48 volatile uint32_t CR;
49 volatile uint32_t OPTCR;
50 };
51
52 struct StmCrc
53 {
54 volatile uint32_t DR;
55 volatile uint32_t IDR;
56 volatile uint32_t CR;
57 };
58
59 struct StmRcc {
60 volatile uint32_t CR;
61 volatile uint32_t PLLCFGR;
62 volatile uint32_t CFGR;
63 volatile uint32_t CIR;
64 volatile uint32_t AHB1RSTR;
65 volatile uint32_t AHB2RSTR;
66 volatile uint32_t AHB3RSTR;
67 uint8_t unused0[4];
68 volatile uint32_t APB1RSTR;
69 volatile uint32_t APB2RSTR;
70 uint8_t unused1[8];
71 volatile uint32_t AHB1ENR;
72 volatile uint32_t AHB2ENR;
73 volatile uint32_t AHB3ENR;
74 uint8_t unused2[4];
75 volatile uint32_t APB1ENR;
76 volatile uint32_t APB2ENR;
77 uint8_t unused3[8];
78 volatile uint32_t AHB1LPENR;
79 volatile uint32_t AHB2LPENR;
80 volatile uint32_t AHB3LPENR;
81 uint8_t unused4[4];
82 volatile uint32_t APB1LPENR;
83 volatile uint32_t APB2LPENR;
84 uint8_t unused5[8];
85 volatile uint32_t BDCR;
86 volatile uint32_t CSR;
87 uint8_t unused6[8];
88 volatile uint32_t SSCGR;
89 volatile uint32_t PLLI2SCFGR;
90 };
91
92 typedef void (*FlashEraseF)(volatile uint32_t *, uint32_t, volatile uint32_t *);
93 typedef void (*FlashWriteF)(volatile uint8_t *, uint8_t, volatile uint32_t *);
94
95 static struct StmSpi *SPI;
96 static struct StmGpio *GPIOA;
97 static struct StmRcc *RCC;
98 static uint32_t mOldApb2State;
99 static uint32_t mOldAhb1State;
100
101 #define INT_IN_PIN (SH_INT_WAKEUP - GPIO_PA(0))
102
103 #define FLASH_ACR_LAT(x) ((x) & FLASH_ACR_LAT_MASK)
104 #define FLASH_ACR_LAT_MASK 0x0F
105 #define FLASH_ACR_PRFTEN 0x00000100
106 #define FLASH_ACR_ICEN 0x00000200
107 #define FLASH_ACR_DCEN 0x00000400
108 #define FLASH_ACR_ICRST 0x00000800
109 #define FLASH_ACR_DCRST 0x00001000
110
111 #define FLASH_SR_EOP 0x00000001
112 #define FLASH_SR_OPERR 0x00000002
113 #define FLASH_SR_WRPERR 0x00000010
114 #define FLASH_SR_PGAERR 0x00000020
115 #define FLASH_SR_PGPERR 0x00000040
116 #define FLASH_SR_PGSERR 0x00000080
117 #define FLASH_SR_RDERR 0x00000100
118 #define FLASH_SR_BSY 0x00010000
119
120 #define FLASH_CR_PG 0x00000001
121 #define FLASH_CR_SER 0x00000002
122 #define FLASH_CR_MER 0x00000004
123 #define FLASH_CR_SNB(x) (((x) << FLASH_CR_SNB_SHIFT) & FLASH_CR_SNB_MASK)
124 #define FLASH_CR_SNB_MASK 0x00000078
125 #define FLASH_CR_SNB_SHIFT 3
126 #define FLASH_CR_PSIZE(x) (((x) << FLASH_CR_PSIZE_SHIFT) & FLASH_CR_PSIZE_MASK)
127 #define FLASH_CR_PSIZE_MASK 0x00000300
128 #define FLASH_CR_PSIZE_SHIFT 8
129 #define FLASH_CR_PSIZE_8 0x0
130 #define FLASH_CR_PSIZE_16 0x1
131 #define FLASH_CR_PSIZE_32 0x2
132 #define FLASH_CR_PSIZE_64 0x3
133 #define FLASH_CR_STRT 0x00010000
134 #define FLASH_CR_EOPIE 0x01000000
135 #define FLASH_CR_ERRIE 0x02000000
136 #define FLASH_CR_LOCK 0x80000000
137
138 //stm defines
139 #define BL_MAX_FLASH_CODE 1024
140
141 /*
142 * Return the address of the erase code and the length of the code
143 *
144 * This code needs to run out of ram and not flash since accessing flash
145 * while erasing is undefined (best case the processor stalls, worst case
146 * it starts executing garbage)
147 *
148 * This function is used to get a pointer to the actual code that does the
149 * erase and polls for completion (so we can copy it to ram) as well as the
150 * length of the code (so we know how much space to allocate for it)
151 *
152 * void FlashEraseF(volatile uint32_t *addr, uint32_t value, volatile uint32_t *status)
153 * {
154 * *addr = value;
155 * while (*status & FLASH_SR_BSY) ;
156 * }
157 */
blGetFlashEraseCode(uint16_t ** addr,uint32_t * size)158 static void __attribute__((naked)) blGetFlashEraseCode(uint16_t **addr, uint32_t *size)
159 {
160 asm volatile (
161 " push {lr} \n"
162 " bl 9f \n"
163 " str r1, [r0, #0] \n" // *addr = value
164 "1: \n"
165 " ldr r3, [r2, #0] \n" // r3 = *status
166 " lsls r3, #15 \n" // r3 <<= 15
167 " bmi 1b \n" // if (r3 < 0) goto 1
168 " bx lr \n" // return
169 "9: \n"
170 " bic lr, #0x1 \n"
171 " adr r3, 9b \n"
172 " sub r3, lr \n"
173 " str lr, [r0] \n"
174 " str r3, [r1] \n"
175 " pop {pc} \n"
176 );
177 }
178
_blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask)179 static void _blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask)
180 {
181 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
182 uint16_t *code_src, *code;
183 uint32_t i, code_length;
184 FlashEraseF func;
185
186 blGetFlashEraseCode(&code_src, &code_length);
187
188 if (code_length < BL_MAX_FLASH_CODE) {
189 code = (uint16_t *)(((uint32_t)alloca(code_length + 1) + 1) & ~0x1);
190 func = (FlashEraseF)((uint8_t *)code+1);
191
192 for (i = 0; i < code_length / sizeof(uint16_t); i++)
193 code[i] = code_src[i];
194
195 for (i = 0; i < sector_cnt; i++) {
196 if (erase_mask[i]) {
197 flash->CR = (flash->CR & ~(FLASH_CR_SNB_MASK)) |
198 FLASH_CR_SNB(i) | FLASH_CR_SER;
199 func(&flash->CR, flash->CR | FLASH_CR_STRT, &flash->SR);
200 flash->CR &= ~(FLASH_CR_SNB_MASK | FLASH_CR_SER);
201 }
202 }
203 }
204 }
205
blEraseSectors(uint32_t sector_cnt,uint8_t * erase_mask,uint32_t key1,uint32_t key2)206 bool blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask, uint32_t key1, uint32_t key2)
207 {
208 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
209 uint32_t acr_cache, cr_cache;
210 // disable interrupts
211 // otherwise an interrupt during flash write/erase will stall the processor
212 // until the write/erase completes
213 uint32_t int_state = blDisableInts();
214
215 // wait for flash to not be busy (should never be set at this point)
216 while (flash->SR & FLASH_SR_BSY);
217
218 cr_cache = flash->CR;
219
220 if (flash->CR & FLASH_CR_LOCK) {
221 // unlock flash
222 flash->KEYR = key1;
223 flash->KEYR = key2;
224 }
225
226 if (!(flash->CR & FLASH_CR_LOCK)) {
227 flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
228 acr_cache = flash->ACR;
229
230 // disable and flush data and instruction caches
231 flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
232 flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
233
234 _blEraseSectors(sector_cnt, erase_mask);
235
236 flash->ACR = acr_cache;
237 flash->CR = cr_cache;
238
239 // restore interrupts
240 blRestoreInts(int_state);
241 return true;
242 }
243 return false;
244 }
245
246 /*
247 * Return the address of the write code and the length of the code
248 *
249 * This code needs to run out of ram and not flash since accessing flash
250 * while writing to flash is undefined (best case the processor stalls, worst
251 * case it starts executing garbage)
252 *
253 * This function is used to get a pointer to the actual code that does the
254 * write and polls for completion (so we can copy it to ram) as well as the
255 * length of the code (so we know how much space to allocate for it)
256 *
257 * void FlashWriteF(volatile uint8_t *addr, uint8_t value, volatile uint32_t *status)
258 * {
259 * *addr = value;
260 * while (*status & FLASH_SR_BSY) ;
261 * }
262 */
blGetFlashWriteCode(uint16_t ** addr,uint32_t * size)263 static void __attribute__((naked)) blGetFlashWriteCode(uint16_t **addr, uint32_t *size)
264 {
265 asm volatile (
266 " push {lr} \n"
267 " bl 9f \n"
268 " strb r1, [r0, #0] \n" // *addr = value
269 "1: \n"
270 " ldr r3, [r2, #0] \n" // r3 = *status
271 " lsls r3, #15 \n" // r3 <<= 15
272 " bmi 1b \n" // if (r3 < 0) goto 1
273 " bx lr \n" // return
274 "9: \n"
275 " bic lr, #0x1 \n"
276 " adr r3, 9b \n"
277 " sub r3, lr \n"
278 " str lr, [r0] \n"
279 " str r3, [r1] \n"
280 " pop {pc} \n"
281 );
282 }
283
blWriteBytes(uint8_t * dst,const uint8_t * src,uint32_t length)284 static void blWriteBytes(uint8_t *dst, const uint8_t *src, uint32_t length)
285 {
286 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
287 uint16_t *code_src, *code;
288 uint32_t i, code_length;
289 FlashWriteF func;
290
291 blGetFlashWriteCode(&code_src, &code_length);
292
293 if (code_length < BL_MAX_FLASH_CODE) {
294 code = (uint16_t *)(((uint32_t)alloca(code_length+1) + 1) & ~0x1);
295 func = (FlashWriteF)((uint8_t *)code+1);
296
297 for (i = 0; i < code_length / sizeof(uint16_t); i++)
298 code[i] = code_src[i];
299
300 flash->CR |= FLASH_CR_PG;
301
302 for (i = 0; i < length; i++) {
303 if (dst[i] != src[i])
304 func(&dst[i], src[i], &flash->SR);
305 }
306
307 flash->CR &= ~FLASH_CR_PG;
308 }
309 }
310
blPlatProgramFlash(uint8_t * dst,const uint8_t * src,uint32_t length,uint32_t key1,uint32_t key2)311 bool blPlatProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2)
312 {
313 struct StmFlash *flash = (struct StmFlash *)FLASH_BASE;
314 uint32_t acr_cache, cr_cache;
315 // disable interrupts
316 // otherwise an interrupt during flash write will stall the processor
317 // until the write completes
318 uint32_t int_state = blDisableInts();
319
320 // wait for flash to not be busy (should never be set at this point)
321 while (flash->SR & FLASH_SR_BSY);
322
323 cr_cache = flash->CR;
324
325 if (flash->CR & FLASH_CR_LOCK) {
326 // unlock flash
327 flash->KEYR = key1;
328 flash->KEYR = key2;
329 }
330
331 if (flash->CR & FLASH_CR_LOCK) {
332 // unlock failed, restore interrupts
333 blRestoreInts(int_state);
334
335 return false;
336 }
337
338 flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8);
339
340 acr_cache = flash->ACR;
341
342 // disable and flush data and instruction caches
343 flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN);
344 flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST);
345
346 blWriteBytes(dst, src, length);
347
348 flash->ACR = acr_cache;
349 flash->CR = cr_cache;
350
351 blRestoreInts(int_state);
352 return true;
353 }
354
blDisableInts(void)355 uint32_t blDisableInts(void)
356 {
357 uint32_t state;
358
359 asm volatile (
360 "mrs %0, PRIMASK \n"
361 "cpsid i \n"
362 :"=r"(state)
363 );
364
365 return state;
366 }
367
blRestoreInts(uint32_t state)368 void blRestoreInts(uint32_t state)
369 {
370 asm volatile(
371 "msr PRIMASK, %0 \n"
372 ::"r"((uint32_t)state)
373 );
374 }
375
blReboot(void)376 void blReboot(void)
377 {
378 SCB->AIRCR = 0x05FA0004;
379 //we never get here
380 while(1);
381 }
382
blResetRxData()383 void blResetRxData()
384 {
385 (void)SPI->DR;
386 while (!(SPI->SR & 1));
387 (void)SPI->DR;
388 }
389
blSpiTxRxByte(uint32_t val)390 uint8_t blSpiTxRxByte(uint32_t val)
391 {
392 while (!(SPI->SR & 2));
393 SPI->DR = val;
394 while (!(SPI->SR & 1));
395 return SPI->DR;
396 }
397
blGetSnum(uint32_t * snum,uint32_t length)398 uint32_t blGetSnum(uint32_t *snum, uint32_t length)
399 {
400 struct StmUdid *reg = (struct StmUdid *)UDID_BASE;
401 uint32_t i;
402
403 if (length > 3)
404 length = 3;
405
406 for (i = 0; i < length; i++)
407 snum[i] = reg->U_ID[i];
408
409 return (length << 2);
410 }
411
blSetup()412 void blSetup()
413 {
414 SPI = (struct StmSpi*)SPI1_BASE;
415 GPIOA = (struct StmGpio*)GPIOA_BASE;
416 RCC = (struct StmRcc*)RCC_BASE;
417
418 if (SH_INT_WAKEUP < GPIO_PA(0) || SH_INT_WAKEUP > GPIO_PA(15)) {
419
420 //link time assert :)
421 extern void ThisIsAnError_BlIntPinNotInGpioA(void);
422 ThisIsAnError_BlIntPinNotInGpioA();
423 }
424
425 //SPI & GPIOA on
426 mOldApb2State = RCC->APB2ENR;
427 mOldAhb1State = RCC->AHB1ENR;
428 RCC->APB2ENR |= PERIPH_APB2_SPI1;
429 RCC->AHB1ENR |= PERIPH_AHB1_GPIOA;
430
431 //reset units
432 RCC->APB2RSTR |= PERIPH_APB2_SPI1;
433 RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
434 RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
435 RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
436
437 //configure GPIOA for SPI A4..A7 for SPI use (function 5), int pin as not func, high speed, no pullups, not open drain, proper directions
438 GPIOA->AFR[0] = (GPIOA->AFR[0] & 0x0000ffff & ~(0x0f << (INT_IN_PIN * 4))) | 0x55550000;
439 GPIOA->OSPEEDR |= 0x0000ff00 | (3 << (INT_IN_PIN * 2));
440 GPIOA->PUPDR &=~ (0x0000ff00 | (3 << (INT_IN_PIN * 2)));
441 GPIOA->OTYPER &=~ (0x00f0 | (1 << INT_IN_PIN));
442 GPIOA->MODER = (GPIOA->MODER & 0xffff00ff & ~(0x03 << (INT_IN_PIN * 2))) | 0x0000aa00;
443 }
444
blCleanup()445 void blCleanup()
446 {
447 //reset units & return APB2 & AHB1 to initial state
448 RCC->APB2RSTR |= PERIPH_APB2_SPI1;
449 RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA;
450 RCC->APB2RSTR &=~ PERIPH_APB2_SPI1;
451 RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA;
452 RCC->APB2ENR = mOldApb2State;
453 RCC->AHB1ENR = mOldAhb1State;
454 }
455
blHostActive()456 bool blHostActive()
457 {
458 return !(GPIOA->IDR & (1 << INT_IN_PIN));
459 }
460
blConfigIo()461 void blConfigIo()
462 {
463 //config SPI
464 SPI->CR1 = 0x00000040; //spi is on, configured same as bootloader would
465 SPI->CR2 = 0x00000000; //spi is on, configured same as bootloader would
466 }
467
blSyncWait(uint32_t syncCode)468 bool blSyncWait(uint32_t syncCode)
469 {
470 uint32_t nRetries;
471 //wait for sync
472 for (nRetries = 10000; nRetries; nRetries--) {
473 if (SPI->SR & 1) {
474 if (SPI->DR == syncCode)
475 break;
476 (void)SPI->SR; //re-read to clear overlfow condition (if any)
477 }
478 }
479 return nRetries > 0;
480 }
481
__blEntry(void)482 static void __blEntry(void)
483 {
484 extern char __code_start[], __bss_end[], __bss_start[], __data_end[], __data_start[], __data_data[];
485 uint32_t appBase = ((uint32_t)&__code_start) & ~1;
486
487 //make sure we're the vector table and no ints happen (BL does not use them)
488 blDisableInts();
489 SCB->VTOR = (uint32_t)&BL;
490
491 //init things a little for the higher levels
492 memset(__bss_start, 0, __bss_end - __bss_start);
493 memcpy(__data_start, __data_data, __data_end - __data_start);
494
495 blMain(appBase);
496
497 //call OS with ints off
498 blDisableInts();
499 SCB->VTOR = appBase;
500 asm volatile(
501 "LDR SP, [%0, #0] \n"
502 "LDR PC, [%0, #4] \n"
503 :
504 :"r"(appBase)
505 :"memory", "cc"
506 );
507
508 //we should never return here
509 while(1);
510 }
511
blSpuriousIntHandler(void)512 static void blSpuriousIntHandler(void)
513 {
514 //BAD!
515 blReboot();
516 }
517
518 extern uint8_t __stack_top[];
519 uint64_t __attribute__ ((section (".stack"))) _STACK[BL_STACK_SIZE / sizeof(uint64_t)];
520
521 const struct BlVecTable __attribute__((section(".blvec"))) __BL_VEC =
522 {
523 .blStackTop = (uint32_t)&__stack_top,
524 .blEntry = &__blEntry,
525 .blNmiHandler = &blSpuriousIntHandler,
526 .blMmuFaultHandler = &blSpuriousIntHandler,
527 .blBusFaultHandler = &blSpuriousIntHandler,
528 .blUsageFaultHandler = &blSpuriousIntHandler,
529 };
530