Home | History | Annotate | Download | only in stm32
      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