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