| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- /*
- * Flash-based Non-Volatile Memory (NVM)
- *
- * This file supports storing and loading persistent configuration based on
- * the STM32 builtin flash memory.
- *
- * The STM32F405xx has 12 flash sectors of heterogeneous size. We use the last
- * two sectors for configuration data. These pages have a size of 128kB each.
- * Setting any bit in these sectors to 0 is always possible, but setting them
- * to 1 requires erasing the whole sector.
- *
- * We consider each sector as an array of 64-bit fields except the first N bytes, which we
- * instead use as an allocation block. The allocation block is a compact bit-field (2 bit per entry)
- * that keeps track of the state of each field (erased, invalid, valid).
- *
- * One sector is always considered the valid (read) sector and the other one is the
- * target for the next write access: they can be considered to be ping-pong or double buffred.
- *
- * When writing a block of data, instead of always erasing the whole writable sector the
- * new data is appended in the erased area. This presumably increases flash life span.
- * The writable sector is only erased if there is not enough space for the new data.
- *
- * On startup, if there is exactly one sector
- * whose last non-erased value has the state "valid" that sector is considered
- * the valid sector. In any other case the selection is undefined.
- *
- *
- * To write a new block of data atomically we first mark all associated fields
- * as "invalid" (in the allocation table) then write the data and then mark the
- * fields as "valid" (in the direction of increasing address).
- */
- #include <string.h>
- #include <stdbool.h>
- //#include <types.h>
- #include "flash.h"
- #include "stm32f405xx.h"
- #include "stm32f4xx_board.h"
- #include "can.h"
- //#include "main.h"
- //#include "tim.h"
- //#include "gpio.h"
- #define K(v) (v<<10)
- static uint32_t sectors_size[12] = {K(16), K(16), K(16), K(16), K(64), K(128), K(128), K(128), K(128), K(128), K(128), K(128)};
- static const uint32_t FLASH_ERR_FLAGS =
- #if defined(FLASH_FLAG_EOP)
- FLASH_FLAG_EOP |
- #endif
- #if defined(FLASH_FLAG_OPERR)
- FLASH_FLAG_OPERR |
- #endif
- #if defined(FLASH_FLAG_WRPERR)
- FLASH_FLAG_WRPERR |
- #endif
- #if defined(FLASH_FLAG_PGAERR)
- FLASH_FLAG_PGAERR |
- #endif
- #if defined(FLASH_FLAG_PGSERR)
- FLASH_FLAG_PGSERR |
- #endif
- #if defined(FLASH_FLAG_PGPERR)
- FLASH_FLAG_PGPERR |
- #endif
- 0;
- void HAL_FLASH_ClearError() {
- __HAL_FLASH_CLEAR_FLAG(FLASH_ERR_FLAGS);
- }
- static uint32_t _sector_frame_address(uint32_t Address)
- {
- uint32_t sector = 0;
- if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
- {
- sector = FLASH_SECTOR_0;
- }
- else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
- {
- sector = FLASH_SECTOR_1;
- }
- else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
- {
- sector = FLASH_SECTOR_2;
- }
- else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
- {
- sector = FLASH_SECTOR_3;
- }
- else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
- {
- sector = FLASH_SECTOR_4;
- }
- else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
- {
- sector = FLASH_SECTOR_5;
- }
- else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
- {
- sector = FLASH_SECTOR_6;
- }
- else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
- {
- sector = FLASH_SECTOR_7;
- }
- else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
- {
- sector = FLASH_SECTOR_8;
- }
- else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
- {
- sector = FLASH_SECTOR_9;
- }
- else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
- {
- sector = FLASH_SECTOR_10;
- }else {
- sector = FLASH_SECTOR_11;
- }
- return sector;
- }
- void flash_unlock(void)
- {
- /* Authorize the FLASH Registers access */
- WRITE_REG(FLASH->KEYR, FLASH_KEY1);
- WRITE_REG(FLASH->KEYR, FLASH_KEY2);
- }
- /**
- * @brief Locks the FLASH control register access
- * @retval HAL Status
- */
- void flash_lock(void)
- {
- /* Set the LOCK Bit to lock the FLASH Registers access */
- FLASH->CR |= FLASH_CR_LOCK;
- }
- void flash_wait_ready(uint32_t Timeout)
- {
- uint32_t tickstart = 0U;
- tickstart = HAL_GetTick();
- while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET)
- {
- // wdog_reload();
- if(Timeout != HAL_MAX_DELAY)
- {
- if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
- {
- return;
- }
- }
- }
- /* Check FLASH End of Operation flag */
- if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != RESET)
- {
- /* Clear FLASH End of Operation pending bit */
- __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
- }
- }
- void flash_erase_sector(uint32_t Sector)
- {
- uint32_t tmp_psize = 0U;
- uint8_t VoltageRange = FLASH_VOLTAGE_RANGE_3;
- if (VoltageRange == FLASH_VOLTAGE_RANGE_1)
- {
- tmp_psize = FLASH_PSIZE_BYTE;
- }
- else if (VoltageRange == FLASH_VOLTAGE_RANGE_2)
- {
- tmp_psize = FLASH_PSIZE_HALF_WORD;
- }
- else if (VoltageRange == FLASH_VOLTAGE_RANGE_3)
- {
- tmp_psize = FLASH_PSIZE_WORD;
- }
- else
- {
- tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
- }
- /* Need to add offset of 4 when sector higher than FLASH_SECTOR_11 */
- if (Sector > FLASH_SECTOR_11)
- {
- Sector += 4U;
- }
- /* If the previous operation is completed, proceed to erase the sector */
- CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
- FLASH->CR |= tmp_psize;
- CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
- FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);
- FLASH->CR |= FLASH_CR_STRT;
- flash_wait_ready(2000);
- CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB));
- }
- static void flash_write_word(uint32_t Address, uint32_t Data)
- {
- /* If the previous operation is completed, proceed to program the new data */
- CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
- FLASH->CR |= FLASH_PSIZE_WORD;
- FLASH->CR |= FLASH_CR_PG;
- *(__IO uint32_t*)Address = Data;
- flash_wait_ready(10);
- FLASH->CR &= (~FLASH_CR_PG);
- }
- //不能用
- static void flash_write_byte(uint32_t Address, uint8_t Data)
- {
- /* If the previous operation is completed, proceed to program the new data */
- CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
- FLASH->CR |= FLASH_PSIZE_BYTE;
- FLASH->CR |= FLASH_CR_PG;
- *(__IO uint8_t*)Address = Data;
- flash_wait_ready(10);
- FLASH->CR &= (~FLASH_CR_PG);
- }
- // @brief Erases a flash sector. This sets all bits in the sector to 1.
- // The sector's current index is reset to the minimum value (n_reserved).
- // @returns 0 on success or a non-zero error code otherwise
- int flash_erase_page(uint32_t address) {
- // wdog_reload();
- flash_unlock();
- HAL_FLASH_ClearError();
- flash_erase_sector(_sector_frame_address(address));
- flash_lock();
- // wdog_reload();
- return 0;
- }
- int flash_erase_pages(uint32_t address, uint32_t size) {
- for (; size > 0; ) {
- flash_erase_page(address);
- uint8_t sector = _sector_frame_address(address);
- address += sectors_size[sector];
- size -= sectors_size[sector];;
- }
- return 0;
- }
- int flash_erase_app(uint8_t app_num) {
- if(app_num == 1) {
- app_status_set(1,false);
- //total = 16+64+128+128=336k
- flash_erase_page(ADDR_FLASH_SECTOR_3);//16k
- flash_erase_page(ADDR_FLASH_SECTOR_4);//64k
- flash_erase_page(ADDR_FLASH_SECTOR_5);//128k
- flash_erase_page(ADDR_FLASH_SECTOR_6);//128k
- }
- else if(app_num == 2) {
- app_status_set(2,false);
- //total = 128+128+128=384k
- flash_erase_page(ADDR_FLASH_SECTOR_7);//128k
- flash_erase_page(ADDR_FLASH_SECTOR_8);//128k
- flash_erase_page(ADDR_FLASH_SECTOR_9);//128k
- }
- return 0;
- }
- void app_status_set(uint8_t app_num,bool status) {
- uint8_t app_ok_flag[2];
- if(app_num == 1) {
- app_ok_flag[0] = status;
- app_ok_flag[1] = *(volatile uint8_t*)(CONFIG_IAP_INFO_ADDR+1);
- flash_erase_page(CONFIG_IAP_INFO_ADDR);
- flash_write_page(CONFIG_IAP_INFO_ADDR, app_ok_flag, 2, false);
- }
- else if(app_num == 2) {
- app_ok_flag[0] = *(volatile uint8_t*)(CONFIG_IAP_INFO_ADDR);
- app_ok_flag[1] = status;
- flash_erase_page(CONFIG_IAP_INFO_ADDR);
- flash_write_page(CONFIG_IAP_INFO_ADDR, app_ok_flag, 2, false);
- }
- }
- int flash_write_page(uint32_t target_addr, uint8_t *data, uint32_t length, bool erase) {
- uint32_t offset = target_addr & 0x3;
- target_addr -= offset;
- if (erase && flash_erase_page(target_addr) != 0) {
- return -1;
- }
- // wdog_reload();
- flash_unlock();
- HAL_FLASH_ClearError();
- // handle unaligned start
- for (; (offset & 0x3) && length; ++data, ++offset, --length) {
- flash_write_byte(target_addr + offset, *data);
- }
- // write 32-bit values (64-bit doesn't work)
- for (; length >= 4; data += 4, offset += 4, length -=4) {
- flash_write_word(target_addr + offset, *(uint32_t *)data);
- }
- // handle unaligned end
- for (; length; ++data, ++offset, --length) {
- flash_write_byte(target_addr + offset, *data);
- }
- flash_lock();
- return 0;
- }
- int flash_test(void) {
- int reg = 0;
- uint8_t buffer[1024];
- reg = flash_erase_pages(ADDR_FLASH_SECTOR_2, ADDR_FLASH_SECTOR_10-ADDR_FLASH_SECTOR_2);
- memset(buffer, 0x55, sizeof(buffer));
- reg = flash_erase_page(ADDR_FLASH_SECTOR_10);
- reg = flash_write_page(ADDR_FLASH_SECTOR_10, buffer, sizeof(buffer), false);
- memset(buffer, 0xAA, sizeof(buffer));
- reg = flash_write_page(ADDR_FLASH_SECTOR_10, buffer, sizeof(buffer), true);
- memset(buffer, 0x55, sizeof(buffer));
- reg = flash_erase_page(ADDR_FLASH_SECTOR_11);
- reg = flash_write_page(ADDR_FLASH_SECTOR_11, buffer, sizeof(buffer), false);
- memset(buffer, 0xAA, sizeof(buffer));
- reg = flash_write_page(ADDR_FLASH_SECTOR_11, buffer, sizeof(buffer), true);
- return reg;
- }
- #if 1
- //APP1_ADRESS 内容复制到 APP2_ADRESS
- void app1_copy_to_app2(void) {
- uint8_t data[1];
- //1、擦除APP2的flash和完整性标志位
- flash_erase_app(2);
- //2、从APP1_ADDRESS读出APP2_ADDRESS - APP1_ADDRESS个数据,复制写入到APP2_ADDRESS
- for (uint32_t i = 0; i < APP2_ADDRESS - APP1_ADDRESS; i++) {
- data[0] = *(volatile uint8_t*)(APP1_ADDRESS + i);
- flash_write_page(APP2_ADDRESS + i, data, 1, false);
- }
- }
- void app2_copy_to_app1(void) {
- uint8_t data[1];
- //1、擦除APP1的flash和完整性标志位
- flash_erase_app(1);
- //2、从APP2_ADDRESS读出APP2_ADDRESS - APP1_ADDRESS个数据,复制写入到APP1_ADDRESS
- for (uint32_t i = 0; i < APP2_ADDRESS - APP1_ADDRESS; i++) {
- data[0] = *(volatile uint8_t*)(APP2_ADDRESS + i);
- flash_write_page(APP1_ADDRESS + i, data, 1, false);
- }
- }
- #else
- //使用字(32位)为单位批量复制,提效不大
- void app1_copy_to_app2(void) {
- uint32_t app_size = APP2_ADDRESS - APP1_ADDRESS;
- // 1. 擦除APP2区域
- flash_erase_app(2);
- // 2. 一次性读取较多数据,批量写入
- uint32_t buffer[256]; // 1KB缓冲区
- uint32_t offset = 0;
- while (offset < app_size) {
- // 计算本次复制的数据量(不超过缓冲区大小)
- uint32_t copy_size = app_size - offset;
- if (copy_size > sizeof(buffer)) {
- copy_size = sizeof(buffer);
- }
- // 按字(32位)读取
- uint32_t word_count = (copy_size + 3) / 4; // 向上取整到4字节
- for (uint32_t i = 0; i < word_count; i++) {
- buffer[i] = *(volatile uint32_t*)(APP1_ADDRESS + offset + i * 4);
- }
- // 批量写入
- flash_write_page(APP2_ADDRESS + offset, (uint8_t*)buffer, copy_size, false);
- offset += copy_size;
- }
- }
- #endif
- void jump_to_app(uint32_t app_addr)
- {
- __disable_irq();
- // 3. 清除所有中断挂起位(非常重要!)
- for (int i = 0; i < 8; i++) {
- NVIC->ICPR[i] = 0xFFFFFFFF; // 清除挂起
- NVIC->ICER[i] = 0xFFFFFFFF; // 禁用中断
- }
- SysTick->CTRL = 0;
- HAL_CAN_DeInit(&hcan1);
- HAL_DeInit();
- __set_MSP(REG32(app_addr));
- // SCB->VTOR = app_addr;
- ((void (*)(void))(REG32(app_addr + 4)))();
- }
- #if 0
- void flash_write_magic(uint32_t magic) {
- uint32_t buffer[16];
- if (magic == REG32(CONFIG_IAP_INFO_ADDR + 8)) {
- return;
- }
- memcpy(buffer, (void *)CONFIG_IAP_INFO_ADDR, sizeof(buffer));
- buffer[2] = magic;
- flash_write_page(CONFIG_IAP_INFO_ADDR, (u8 *)buffer, sizeof(buffer), true);
- }
- uint32_t flash_read_magic(void) {
- return REG32(CONFIG_IAP_INFO_ADDR + 8);
- }
- #endif
|