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 #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