1bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <alloca.h> 2bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <stdbool.h> 3bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <string.h> 4515f84084123dd42de0ba58445b2d65976132dc7Dmitry Grinberg 5f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <variant/variant.h> 6b62d65a623f9c09a5936c69dacae829e0cc9a2baAlexey Polyudov 7f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/pwr.h> 8bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <plat/gpio.h> 9bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <plat/cmsis.h> 10a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 11bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <bl.h> 126308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 13bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstruct StmUdid 146308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema{ 15bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t U_ID[3]; 16bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov}; 17bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 18bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstruct StmSpi { 19bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t CR1; 20bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t CR2; 21bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t SR; 226308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t DR; 23bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t CRCPR; 24bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t RXCRCR; 25bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t TXCRCR; 26bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t I2SCFGR; 27bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t I2SPR; 28bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov}; 29bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 30bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstruct StmGpio { 31bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t MODER; 32bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t OTYPER; 33bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t OSPEEDR; 34bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t PUPDR; 356308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t IDR; 36bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t ODR; 37bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t BSRR; 38bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t LCKR; 39bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t AFR[2]; 406308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema}; 416308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 426308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennemastruct StmFlash 436308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema{ 446308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t ACR; 456308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t KEYR; 466308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t OPTKEYR; 476308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t SR; 486308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t CR; 496308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t OPTCR; 506308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema}; 516308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 52bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstruct StmCrc 53bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov{ 54bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t DR; 55bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t IDR; 56bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov volatile uint32_t CR; 57bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov}; 58bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 596308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennemastruct StmRcc { 606308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t CR; 616308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t PLLCFGR; 626308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t CFGR; 636308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t CIR; 646308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB1RSTR; 656308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB2RSTR; 666308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB3RSTR; 676308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused0[4]; 686308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB1RSTR; 696308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB2RSTR; 706308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused1[8]; 716308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB1ENR; 726308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB2ENR; 736308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB3ENR; 746308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused2[4]; 756308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB1ENR; 766308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB2ENR; 776308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused3[8]; 786308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB1LPENR; 796308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB2LPENR; 806308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t AHB3LPENR; 816308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused4[4]; 826308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB1LPENR; 836308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t APB2LPENR; 846308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused5[8]; 856308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t BDCR; 866308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t CSR; 876308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema uint8_t unused6[8]; 886308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t SSCGR; 896308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema volatile uint32_t PLLI2SCFGR; 906308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema}; 916308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 92bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovtypedef void (*FlashEraseF)(volatile uint32_t *, uint32_t, volatile uint32_t *); 93bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovtypedef void (*FlashWriteF)(volatile uint8_t *, uint8_t, volatile uint32_t *); 946308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 95bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic struct StmSpi *SPI; 96bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic struct StmGpio *GPIOA; 97bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic struct StmRcc *RCC; 98bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic uint32_t mOldApb2State; 99bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic uint32_t mOldAhb1State; 1006308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 101bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#define INT_IN_PIN (SH_INT_WAKEUP - GPIO_PA(0)) 1026308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 1036308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_LAT(x) ((x) & FLASH_ACR_LAT_MASK) 1046308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_LAT_MASK 0x0F 1056308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_PRFTEN 0x00000100 1066308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_ICEN 0x00000200 1076308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_DCEN 0x00000400 1086308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_ICRST 0x00000800 1096308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_ACR_DCRST 0x00001000 1106308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 1116308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_EOP 0x00000001 1126308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_OPERR 0x00000002 1136308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_WRPERR 0x00000010 1146308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_PGAERR 0x00000020 1156308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_PGPERR 0x00000040 1166308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_PGSERR 0x00000080 1176308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_RDERR 0x00000100 1186308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_SR_BSY 0x00010000 1196308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 1206308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PG 0x00000001 1216308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_SER 0x00000002 1226308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_MER 0x00000004 1236308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_SNB(x) (((x) << FLASH_CR_SNB_SHIFT) & FLASH_CR_SNB_MASK) 1246308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_SNB_MASK 0x00000078 1256308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_SNB_SHIFT 3 1266308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE(x) (((x) << FLASH_CR_PSIZE_SHIFT) & FLASH_CR_PSIZE_MASK) 1276308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_MASK 0x00000300 1286308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_SHIFT 8 1296308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_8 0x0 1306308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_16 0x1 1316308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_32 0x2 1326308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_PSIZE_64 0x3 1336308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_STRT 0x00010000 1346308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_EOPIE 0x01000000 1356308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_ERRIE 0x02000000 1366308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema#define FLASH_CR_LOCK 0x80000000 1376308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 138bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov//stm defines 139bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#define BL_MAX_FLASH_CODE 1024 1406308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 1416308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema/* 1426308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * Return the address of the erase code and the length of the code 1436308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 1446308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * This code needs to run out of ram and not flash since accessing flash 1456308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * while erasing is undefined (best case the processor stalls, worst case 1466308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * it starts executing garbage) 1476308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 1486308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * This function is used to get a pointer to the actual code that does the 1496308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * erase and polls for completion (so we can copy it to ram) as well as the 1506308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * length of the code (so we know how much space to allocate for it) 1516308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 152e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg * void FlashEraseF(volatile uint32_t *addr, uint32_t value, volatile uint32_t *status) 1536308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * { 1546308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * *addr = value; 1556308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * while (*status & FLASH_SR_BSY) ; 1566308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * } 1576308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema */ 158e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinbergstatic void __attribute__((naked)) blGetFlashEraseCode(uint16_t **addr, uint32_t *size) 1596308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema{ 1606308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema asm volatile ( 1616308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " push {lr} \n" 1626308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bl 9f \n" 1636308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " str r1, [r0, #0] \n" // *addr = value 1646308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema "1: \n" 1656308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " ldr r3, [r2, #0] \n" // r3 = *status 1666308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " lsls r3, #15 \n" // r3 <<= 15 1676308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bmi 1b \n" // if (r3 < 0) goto 1 1686308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bx lr \n" // return 1696308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema "9: \n" 1706308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bic lr, #0x1 \n" 1716308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " adr r3, 9b \n" 1726308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " sub r3, lr \n" 1736308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " str lr, [r0] \n" 1746308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " str r3, [r1] \n" 1756308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " pop {pc} \n" 1766308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema ); 1776308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema} 1786308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 179bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic void _blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask) 180bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov{ 181bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov struct StmFlash *flash = (struct StmFlash *)FLASH_BASE; 182bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint16_t *code_src, *code; 183bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t i, code_length; 184bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov FlashEraseF func; 185bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 186bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov blGetFlashEraseCode(&code_src, &code_length); 187bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 188bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (code_length < BL_MAX_FLASH_CODE) { 189bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov code = (uint16_t *)(((uint32_t)alloca(code_length + 1) + 1) & ~0x1); 190bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov func = (FlashEraseF)((uint8_t *)code+1); 191bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 192bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov for (i = 0; i < code_length / sizeof(uint16_t); i++) 193bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov code[i] = code_src[i]; 194bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 195bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov for (i = 0; i < sector_cnt; i++) { 196bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (erase_mask[i]) { 197bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->CR = (flash->CR & ~(FLASH_CR_SNB_MASK)) | 198bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov FLASH_CR_SNB(i) | FLASH_CR_SER; 199bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov func(&flash->CR, flash->CR | FLASH_CR_STRT, &flash->SR); 200bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->CR &= ~(FLASH_CR_SNB_MASK | FLASH_CR_SER); 201bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov } 202bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov } 203bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov } 204bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov} 205bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 206bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovbool blEraseSectors(uint32_t sector_cnt, uint8_t *erase_mask, uint32_t key1, uint32_t key2) 207bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov{ 208bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov struct StmFlash *flash = (struct StmFlash *)FLASH_BASE; 209bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t acr_cache, cr_cache; 210bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // disable interrupts 211bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // otherwise an interrupt during flash write/erase will stall the processor 212bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // until the write/erase completes 213bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t int_state = blDisableInts(); 214bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 215bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // wait for flash to not be busy (should never be set at this point) 216bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov while (flash->SR & FLASH_SR_BSY); 217bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 218bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov cr_cache = flash->CR; 219bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 220bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (flash->CR & FLASH_CR_LOCK) { 221bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // unlock flash 222bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->KEYR = key1; 223bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->KEYR = key2; 224bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov } 225bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 226bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (!(flash->CR & FLASH_CR_LOCK)) { 227bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8); 228bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov acr_cache = flash->ACR; 229bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 230bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // disable and flush data and instruction caches 231bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN); 232bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST); 233bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 234bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov _blEraseSectors(sector_cnt, erase_mask); 235bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 236bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->ACR = acr_cache; 237bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov flash->CR = cr_cache; 238bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 239bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov // restore interrupts 240bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov blRestoreInts(int_state); 241bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return true; 242bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov } 243bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return false; 244bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov} 245bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 2466308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema/* 2476308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * Return the address of the write code and the length of the code 2486308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 2496308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * This code needs to run out of ram and not flash since accessing flash 2506308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * while writing to flash is undefined (best case the processor stalls, worst 2516308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * case it starts executing garbage) 2526308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 2536308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * This function is used to get a pointer to the actual code that does the 2546308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * write and polls for completion (so we can copy it to ram) as well as the 2556308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * length of the code (so we know how much space to allocate for it) 2566308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * 257e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg * void FlashWriteF(volatile uint8_t *addr, uint8_t value, volatile uint32_t *status) 2586308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * { 2596308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * *addr = value; 2606308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * while (*status & FLASH_SR_BSY) ; 2616308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema * } 2626308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema */ 263e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinbergstatic void __attribute__((naked)) blGetFlashWriteCode(uint16_t **addr, uint32_t *size) 2646308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema{ 2656308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema asm volatile ( 2666308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " push {lr} \n" 2676308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bl 9f \n" 2686308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " strb r1, [r0, #0] \n" // *addr = value 2696308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema "1: \n" 2706308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " ldr r3, [r2, #0] \n" // r3 = *status 2716308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " lsls r3, #15 \n" // r3 <<= 15 2726308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bmi 1b \n" // if (r3 < 0) goto 1 2736308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bx lr \n" // return 2746308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema "9: \n" 2756308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " bic lr, #0x1 \n" 2766308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " adr r3, 9b \n" 2776308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " sub r3, lr \n" 2786308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " str lr, [r0] \n" 2796308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " str r3, [r1] \n" 2806308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema " pop {pc} \n" 2816308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema ); 2826308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema} 2836308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 284e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinbergstatic void blWriteBytes(uint8_t *dst, const uint8_t *src, uint32_t length) 285e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 286e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg struct StmFlash *flash = (struct StmFlash *)FLASH_BASE; 287e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg uint16_t *code_src, *code; 288e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg uint32_t i, code_length; 289e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg FlashWriteF func; 290e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 291e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blGetFlashWriteCode(&code_src, &code_length); 292e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 293e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg if (code_length < BL_MAX_FLASH_CODE) { 294e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg code = (uint16_t *)(((uint32_t)alloca(code_length+1) + 1) & ~0x1); 295e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg func = (FlashWriteF)((uint8_t *)code+1); 296e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 297e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg for (i = 0; i < code_length / sizeof(uint16_t); i++) 298e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg code[i] = code_src[i]; 299e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 300e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg flash->CR |= FLASH_CR_PG; 301e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 302e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg for (i = 0; i < length; i++) { 303e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg if (dst[i] != src[i]) 304e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg func(&dst[i], src[i], &flash->SR); 305e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg } 306e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 307e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg flash->CR &= ~FLASH_CR_PG; 308e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg } 309e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 310e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 311bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovbool blPlatProgramFlash(uint8_t *dst, const uint8_t *src, uint32_t length, uint32_t key1, uint32_t key2) 312e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 313e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg struct StmFlash *flash = (struct StmFlash *)FLASH_BASE; 314bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t acr_cache, cr_cache; 315019ae84cb5b18417772b683fded7719450349272Ben Fennema // disable interrupts 316019ae84cb5b18417772b683fded7719450349272Ben Fennema // otherwise an interrupt during flash write will stall the processor 317019ae84cb5b18417772b683fded7719450349272Ben Fennema // until the write completes 318bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t int_state = blDisableInts(); 319019ae84cb5b18417772b683fded7719450349272Ben Fennema 3206308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema // wait for flash to not be busy (should never be set at this point) 321e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg while (flash->SR & FLASH_SR_BSY); 3226308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3236308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema cr_cache = flash->CR; 3246308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3256308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema if (flash->CR & FLASH_CR_LOCK) { 3266308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema // unlock flash 3276308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->KEYR = key1; 3286308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->KEYR = key2; 3296308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema } 3306308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3316308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema if (flash->CR & FLASH_CR_LOCK) { 332639605691efc26e9671bf584b1a37782ab688ed1Ben Fennema // unlock failed, restore interrupts 333e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blRestoreInts(int_state); 3346308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 335e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg return false; 3366308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema } 3376308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3386308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->CR = FLASH_CR_PSIZE(FLASH_CR_PSIZE_8); 3396308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3406308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema acr_cache = flash->ACR; 3416308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3426308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema // disable and flush data and instruction caches 3436308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->ACR &= ~(FLASH_ACR_DCEN | FLASH_ACR_ICEN); 3446308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->ACR |= (FLASH_ACR_DCRST | FLASH_ACR_ICRST); 3456308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 346e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blWriteBytes(dst, src, length); 3476308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 3486308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->ACR = acr_cache; 3496308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema flash->CR = cr_cache; 3506308b4d8391441dbb4158bd6723c7d6cee5f5595Ben Fennema 351e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blRestoreInts(int_state); 352bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return true; 3537704485a8c6171cef203acbcee98f4ed9514f02fDmitry Grinberg} 3547704485a8c6171cef203acbcee98f4ed9514f02fDmitry Grinberg 355bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovuint32_t blDisableInts(void) 356639605691efc26e9671bf584b1a37782ab688ed1Ben Fennema{ 357bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t state; 358639605691efc26e9671bf584b1a37782ab688ed1Ben Fennema 359bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov asm volatile ( 360bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov "mrs %0, PRIMASK \n" 361bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov "cpsid i \n" 362bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov :"=r"(state) 363bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov ); 364639605691efc26e9671bf584b1a37782ab688ed1Ben Fennema 365bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return state; 366d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov} 367d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov 368bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blRestoreInts(uint32_t state) 369d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov{ 370bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov asm volatile( 371bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov "msr PRIMASK, %0 \n" 372bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov ::"r"((uint32_t)state) 373bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov ); 374d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov} 375d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov 376bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blReboot(void) 377d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov{ 378bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov SCB->AIRCR = 0x05FA0004; 379bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //we never get here 380bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov while(1); 381d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov} 382d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov 383bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blResetRxData() 384a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg{ 385bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov (void)SPI->DR; 386bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov while (!(SPI->SR & 1)); 387bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov (void)SPI->DR; 388a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg} 389a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 390bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovuint8_t blSpiTxRxByte(uint32_t val) 3912c2c28b9e97ec57ba4f67f0a6394a95b28cb8961Captain Dmitry Grinberg IV{ 392bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov while (!(SPI->SR & 2)); 393bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov SPI->DR = val; 394bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov while (!(SPI->SR & 1)); 395bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return SPI->DR; 3962c2c28b9e97ec57ba4f67f0a6394a95b28cb8961Captain Dmitry Grinberg IV} 3972c2c28b9e97ec57ba4f67f0a6394a95b28cb8961Captain Dmitry Grinberg IV 398bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovuint32_t blGetSnum(uint32_t *snum, uint32_t length) 39979b5f7745d88342ddae69c2cbe457221702061cfDmitry Grinberg{ 400bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov struct StmUdid *reg = (struct StmUdid *)UDID_BASE; 40179b5f7745d88342ddae69c2cbe457221702061cfDmitry Grinberg uint32_t i; 40279b5f7745d88342ddae69c2cbe457221702061cfDmitry Grinberg 403bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (length > 3) 404bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov length = 3; 405d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov 406bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov for (i = 0; i < length; i++) 407bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov snum[i] = reg->U_ID[i]; 408e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 409bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return (length << 2); 410e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 411e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 412bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blSetup() 413e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 414bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov SPI = (struct StmSpi*)SPI1_BASE; 415bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA = (struct StmGpio*)GPIOA_BASE; 416bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC = (struct StmRcc*)RCC_BASE; 417e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 418bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (SH_INT_WAKEUP < GPIO_PA(0) || SH_INT_WAKEUP > GPIO_PA(15)) { 419d1040d8e06013a383c0d1258db7b88d3d536566bAlexey Polyudov 420bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //link time assert :) 421bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov extern void ThisIsAnError_BlIntPinNotInGpioA(void); 422bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov ThisIsAnError_BlIntPinNotInGpioA(); 423e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg } 424e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 425bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //SPI & GPIOA on 426bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov mOldApb2State = RCC->APB2ENR; 427bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov mOldAhb1State = RCC->AHB1ENR; 428bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2ENR |= PERIPH_APB2_SPI1; 429bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1ENR |= PERIPH_AHB1_GPIOA; 430e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 431bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //reset units 432bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2RSTR |= PERIPH_APB2_SPI1; 433bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA; 434bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2RSTR &=~ PERIPH_APB2_SPI1; 435bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA; 43667dd3e880c05f246865598a40028c1275e3f3fe3Ben Fennema 437bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //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 438bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA->AFR[0] = (GPIOA->AFR[0] & 0x0000ffff & ~(0x0f << (INT_IN_PIN * 4))) | 0x55550000; 439bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA->OSPEEDR |= 0x0000ff00 | (3 << (INT_IN_PIN * 2)); 440bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA->PUPDR &=~ (0x0000ff00 | (3 << (INT_IN_PIN * 2))); 441bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA->OTYPER &=~ (0x00f0 | (1 << INT_IN_PIN)); 442bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov GPIOA->MODER = (GPIOA->MODER & 0xffff00ff & ~(0x03 << (INT_IN_PIN * 2))) | 0x0000aa00; 443e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 444e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 445bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blCleanup() 446e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 447bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //reset units & return APB2 & AHB1 to initial state 448bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2RSTR |= PERIPH_APB2_SPI1; 449bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1RSTR |= PERIPH_AHB1_GPIOA; 450bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2RSTR &=~ PERIPH_APB2_SPI1; 451bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1RSTR &=~ PERIPH_AHB1_GPIOA; 452bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->APB2ENR = mOldApb2State; 453bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov RCC->AHB1ENR = mOldAhb1State; 4548b5393ed02b015577c6a845b0311064f99f9512fBen Fennema} 4558b5393ed02b015577c6a845b0311064f99f9512fBen Fennema 456bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovbool blHostActive() 4578b5393ed02b015577c6a845b0311064f99f9512fBen Fennema{ 458bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return !(GPIOA->IDR & (1 << INT_IN_PIN)); 459e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 460e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 461bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovvoid blConfigIo() 462e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 463bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //config SPI 464bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov SPI->CR1 = 0x00000040; //spi is on, configured same as bootloader would 465bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov SPI->CR2 = 0x00000000; //spi is on, configured same as bootloader would 466e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 467e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 468bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovbool blSyncWait(uint32_t syncCode) 469e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 470bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov uint32_t nRetries; 471bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //wait for sync 472bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov for (nRetries = 10000; nRetries; nRetries--) { 473bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (SPI->SR & 1) { 474bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov if (SPI->DR == syncCode) 475bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov break; 476bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov (void)SPI->SR; //re-read to clear overlfow condition (if any) 477e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg } 478e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg } 479bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov return nRetries > 0; 480e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 481e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 482bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic void __blEntry(void) 483e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg{ 484bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov extern char __code_start[], __bss_end[], __bss_start[], __data_end[], __data_start[], __data_data[]; 485b928147358283f2c3e733afe60b96017038eca6eDmitry Grinberg uint32_t appBase = ((uint32_t)&__code_start) & ~1; 486e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 487e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg //make sure we're the vector table and no ints happen (BL does not use them) 488e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blDisableInts(); 489e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg SCB->VTOR = (uint32_t)&BL; 490e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 491515f84084123dd42de0ba58445b2d65976132dc7Dmitry Grinberg //init things a little for the higher levels 492515f84084123dd42de0ba58445b2d65976132dc7Dmitry Grinberg memset(__bss_start, 0, __bss_end - __bss_start); 493515f84084123dd42de0ba58445b2d65976132dc7Dmitry Grinberg memcpy(__data_start, __data_data, __data_end - __data_start); 494515f84084123dd42de0ba58445b2d65976132dc7Dmitry Grinberg 495bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov blMain(appBase); 496e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 497bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //call OS with ints off 498e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg blDisableInts(); 499e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg SCB->VTOR = appBase; 500e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg asm volatile( 501e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg "LDR SP, [%0, #0] \n" 502e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg "LDR PC, [%0, #4] \n" 503e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg : 504e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg :"r"(appBase) 505e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg :"memory", "cc" 506e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg ); 507e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg 508e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg //we should never return here 509e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg while(1); 510e3aa7770fd83abf57b3a8a5678d2c022216bcc19Dmitry Grinberg} 511bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 512bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovstatic void blSpuriousIntHandler(void) 513bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov{ 514bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov //BAD! 515bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov blReboot(); 516bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov} 517bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 518bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovextern uint8_t __stack_top[]; 519bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovuint64_t __attribute__ ((section (".stack"))) _STACK[BL_STACK_SIZE / sizeof(uint64_t)]; 520bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 521bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudovconst struct BlVecTable __attribute__((section(".blvec"))) __BL_VEC = 522bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov{ 523bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blStackTop = (uint32_t)&__stack_top, 524bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blEntry = &__blEntry, 525bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blNmiHandler = &blSpuriousIntHandler, 526bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blMmuFaultHandler = &blSpuriousIntHandler, 527bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blBusFaultHandler = &blSpuriousIntHandler, 528bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov .blUsageFaultHandler = &blSpuriousIntHandler, 529bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov}; 530