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 */ 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 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 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 */ 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 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 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 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 368 void blRestoreInts(uint32_t state) 369 { 370 asm volatile( 371 "msr PRIMASK, %0 \n" 372 ::"r"((uint32_t)state) 373 ); 374 } 375 376 void blReboot(void) 377 { 378 SCB->AIRCR = 0x05FA0004; 379 //we never get here 380 while(1); 381 } 382 383 void blResetRxData() 384 { 385 (void)SPI->DR; 386 while (!(SPI->SR & 1)); 387 (void)SPI->DR; 388 } 389 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 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 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 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 456 bool blHostActive() 457 { 458 return !(GPIOA->IDR & (1 << INT_IN_PIN)); 459 } 460 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 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 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 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