|
205 | 205 | /*** QSPI ***/ |
206 | 206 | /* See hal/spi/spi_drv_stm32.c */ |
207 | 207 |
|
| 208 | + |
208 | 209 | /*** FLASH ***/ |
209 | 210 | #define SYSCFG_APB4_CLOCK_ER_VAL (1 << 0) /* RM0433 - 7.7.48 - RCC_APB4ENR - SYSCFGEN */ |
210 | 211 |
|
211 | 212 | #define FLASH_BASE (0x52002000) /* RM0433 - Table 8 */ |
212 | 213 | #define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00)) /* RM0433 - 3.9.1 - FLASH_ACR */ |
213 | | -#define FLASH_OPTSR_CUR (*(volatile uint32_t *)(FLASH_BASE + 0x1C)) |
| 214 | + |
| 215 | +#define FLASH_OPTKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x08)) /* FLASH option key register */ |
| 216 | +#define FLASH_OPTCR (*(volatile uint32_t *)(FLASH_BASE + 0x18)) /* FLASH option control register */ |
| 217 | +#define FLASH_OPTSR_CUR (*(volatile uint32_t *)(FLASH_BASE + 0x1C)) /* FLASH option status register */ |
214 | 218 |
|
215 | 219 | /* Bank 1 */ |
216 | 220 | #define FLASH_KEYR1 (*(volatile uint32_t *)(FLASH_BASE + 0x04)) /* RM0433 - 3.9.2 - FLASH_KEYR 1 */ |
217 | | -#define FLASH_SR1 (*(volatile uint32_t *)(FLASH_BASE + 0x10)) /* RM0433 - 3.9.5 - FLASH_SR 1 */ |
218 | 221 | #define FLASH_CR1 (*(volatile uint32_t *)(FLASH_BASE + 0x0C)) /* RM0433 - 3.9.4 - FLASH_CR 1 */ |
| 222 | +#define FLASH_SR1 (*(volatile uint32_t *)(FLASH_BASE + 0x10)) /* RM0433 - 3.9.5 - FLASH_SR 1 */ |
219 | 223 |
|
220 | 224 | /* Bank 2 */ |
221 | 225 | #define FLASH_KEYR2 (*(volatile uint32_t *)(FLASH_BASE + 0x104)) /* RM0433 - 3.9.24 - FLASH_KEYR 2 */ |
|
255 | 259 |
|
256 | 260 | #define FLASH_OPTSR_CUR_BSY (1 << 0) |
257 | 261 |
|
| 262 | +#define FLASH_OPTCR_OPTLOCK (1 << 0) /* lock option configuration bit */ |
| 263 | +#define FLASH_OPTCR_OPTSTART (1 << 1) /* Option byte start change option configuration bit */ |
| 264 | +#define FLASH_OPTCR_MER (1 << 4) /* Mass erase request */ |
| 265 | +#define FLASH_OPTCR_PG_OTP (1 << 5) /* OTP program control bit */ |
| 266 | +#define FLASH_OPTCR_OPTCHANGEERRIE (1 << 30) /* Option byte change error interrupt enable bit */ |
| 267 | +#define FLASH_OPTCR_SWAP_BANK (1 << 31) /* Bank swapping option configuration bit */ |
| 268 | + |
258 | 269 | #define FLASH_CR_SNB_SHIFT 8 /* SNB bits 10:8 */ |
259 | 270 | #define FLASH_CR_SNB_MASK 0x7 /* SNB bits 10:8 - 3 bits */ |
260 | 271 |
|
261 | | -#define FLASH_KEY1 (0x45670123) |
262 | | -#define FLASH_KEY2 (0xCDEF89AB) |
263 | | - |
| 272 | +#define FLASH_KEY1 (0x45670123U) |
| 273 | +#define FLASH_KEY2 (0xCDEF89ABU) |
| 274 | + |
| 275 | +#define FLASH_OPT_KEY1 (0x08192A3BU) |
| 276 | +#define FLASH_OPT_KEY2 (0x4C5D6E7FU) |
| 277 | + |
| 278 | +#ifdef FLASH_OTP_ROT |
| 279 | + #ifndef FLASH_OTP_BASE |
| 280 | + #define FLASH_OTP_BASE 0x08FFF000 |
| 281 | + #endif |
| 282 | + #ifndef FLASH_OTP_END |
| 283 | + #define FLASH_OTP_END 0x08FFF3FF |
| 284 | + #endif |
| 285 | + #ifndef OTP_SIZE |
| 286 | + #define OTP_SIZE 1024 |
| 287 | + #endif |
| 288 | + #ifndef OTP_BLOCKS |
| 289 | + #define OTP_BLOCKS 16 |
| 290 | + #endif |
| 291 | + |
| 292 | + #define OTP_BLOCK_SIZE (OTP_SIZE / OTP_BLOCKS) /* 64 bytes */ |
| 293 | +#endif |
264 | 294 |
|
265 | 295 | /* STM32H7: Due to ECC functionality, it is not possible to write partition/sector |
266 | 296 | * flags and signature more than once. This flags_cache is used to intercept write operations and |
@@ -777,3 +807,98 @@ void hal_prepare_boot(void) |
777 | 807 | #endif |
778 | 808 | clock_pll_off(); |
779 | 809 | } |
| 810 | + |
| 811 | +#ifdef FLASH_OTP_ROT |
| 812 | + |
| 813 | +static void hal_flash_wait_otp(void) |
| 814 | +{ |
| 815 | + /* Wait for the FLASH operation to complete by polling on QW flag to be reset. */ |
| 816 | + while ( (FLASH_SR1 & FLASH_SR_QW) == FLASH_SR_QW ) { |
| 817 | + /* TODO: check timeout */ |
| 818 | + } |
| 819 | + |
| 820 | + /* Check FLASH End of Operation flag */ |
| 821 | + if ( (FLASH_SR1 & FLASH_SR_EOP) == FLASH_SR_EOP ) { |
| 822 | + FLASH_SR1 &= FLASH_SR_EOP; /* Clear FLASH End of Operation pending bit */ |
| 823 | + } |
| 824 | +} |
| 825 | + |
| 826 | +static void hal_flash_otp_unlock(void) |
| 827 | +{ |
| 828 | + if ((FLASH_OPTCR & FLASH_OPTCR_OPTLOCK) != 0U) { |
| 829 | + FLASH_OPTKEYR = FLASH_OPT_KEY1; |
| 830 | + FLASH_OPTKEYR = FLASH_OPT_KEY2; |
| 831 | + } |
| 832 | +} |
| 833 | + |
| 834 | +static void hal_flash_otp_lock(void) |
| 835 | +{ |
| 836 | + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ |
| 837 | + FLASH_OPTCR |= FLASH_OPTCR_OPTLOCK; |
| 838 | +} |
| 839 | + |
| 840 | +int hal_flash_otp_write(uint32_t flashAddress, uint16_t* data, uint16_t length) |
| 841 | +{ |
| 842 | + volatile uint16_t tmp; |
| 843 | + uint16_t idx = 0; |
| 844 | + if (!(flashAddress >= FLASH_OTP_BASE && flashAddress <= FLASH_OTP_END)) { |
| 845 | + return -1; |
| 846 | + } |
| 847 | + |
| 848 | + hal_flash_unlock(); |
| 849 | + hal_flash_otp_unlock(); |
| 850 | + |
| 851 | + while (idx < length && flashAddress <= FLASH_OTP_END-1) { |
| 852 | + /* Clear errors */ |
| 853 | + flash_clear_errors(0); /* bank 1 */ |
| 854 | + /* Wait for last operation to be completed */ |
| 855 | + hal_flash_wait_otp(); |
| 856 | + |
| 857 | + FLASH_OPTCR &= ~(FLASH_OPTCR_OPTLOCK); /* unlock FLASH_OPTCR register */ |
| 858 | + |
| 859 | + /* Set OTP_PG bit */ |
| 860 | + FLASH_OPTCR |= FLASH_OPTCR_PG_OTP; |
| 861 | + |
| 862 | + ISB(); |
| 863 | + DSB(); |
| 864 | + |
| 865 | + /* Program an OTP word (16 bits) */ |
| 866 | + *(volatile uint16_t*)flashAddress = *(volatile uint16_t*)data; |
| 867 | + |
| 868 | + /* Read it back */ |
| 869 | + tmp = *(volatile uint16_t*)flashAddress; |
| 870 | + (void)tmp; /* avoid unused warnings */ |
| 871 | + flashAddress += sizeof(uint16_t); |
| 872 | + data++; |
| 873 | + idx += sizeof(uint16_t); |
| 874 | + |
| 875 | + /* Wait for last operation to be completed */ |
| 876 | + hal_flash_wait_otp(); |
| 877 | + |
| 878 | + /* clear OTP_PG bit */ |
| 879 | + FLASH_OPTCR &= ~FLASH_OPTCR_PG_OTP; |
| 880 | + } |
| 881 | + |
| 882 | + hal_flash_otp_lock(); |
| 883 | + hal_flash_lock(); |
| 884 | + return 0; |
| 885 | +} |
| 886 | + |
| 887 | +int hal_flash_otp_read(uint32_t flashAddress, uint16_t* data, uint32_t length) |
| 888 | +{ |
| 889 | + uint32_t i; |
| 890 | + if (!(flashAddress >= FLASH_OTP_BASE && flashAddress <= FLASH_OTP_END)) { |
| 891 | + return -1; |
| 892 | + } |
| 893 | + for (i = 0; |
| 894 | + (i < length) && (flashAddress <= (FLASH_OTP_END-1)); |
| 895 | + i += sizeof(uint16_t)) |
| 896 | + { |
| 897 | + *data = *(volatile uint16_t*)flashAddress; |
| 898 | + flashAddress += sizeof(uint16_t); |
| 899 | + data++; |
| 900 | + } |
| 901 | + return 0; |
| 902 | +} |
| 903 | + |
| 904 | +#endif /* FLASH_OTP_ROT */ |
0 commit comments