電影網(wǎng)站模板htmlseo互聯(lián)網(wǎng)營銷培訓
文章目錄
- 一、概要
- 二、內部FLASH排布
- 三、內部FLASH主要特色
- 四、OTP函數(shù)介紹
- 五、測試驗證
一、概要
??STM32系列是一款強大而靈活的微控制器,它的片內Flash存儲器可以用來存儲有關代碼和數(shù)據(jù),在實際應用中,我們也需要對這個存儲器進行讀寫操作。
??STM32的FLASH主存儲塊按頁組織,有的產(chǎn)品每頁1KB,有的能到2KB,頁面典型的用途就是用于按頁擦除FLASH,STM32F407的FLASH頁大一點,能到16K,我們也叫做扇區(qū)。
二、內部FLASH排布
1. 根據(jù)用途,STM32片內的FLASH分成兩部分:主存儲塊、信息塊。
2. 主存儲塊
:用于存儲程序,我們寫的程序一般存儲在這里,用戶還可以存儲數(shù)據(jù)。信息塊
又分成兩部分:系統(tǒng)存儲器、OTP、選項字節(jié)。
3. 系統(tǒng)存儲器存儲用于存放在系統(tǒng)存儲器自舉模式下的啟動程序(BootLoader),當使用ISP方式加載程序時,就是由這個程序執(zhí)行。這個區(qū)域由芯片廠寫入BootLoader,然后鎖死,用戶是無法改變這個區(qū)域的。
4. OTP(One Time Program)區(qū)域,指的是只能寫入一次的存儲區(qū)域,容量為528字節(jié),寫入后數(shù)據(jù)就無法再更改,OTP常用于存儲應用程序的加密密鑰。
5. 選項字節(jié)存儲芯片的配置信息及對主存儲塊的保護信息,主要有寫保護字節(jié),讀保護字節(jié)等。
三、內部FLASH主要特色
- 容量大的芯片可以高達 1 MB 容量
- 128 位寬數(shù)據(jù)讀取
- 字節(jié)、半字、字和雙字數(shù)據(jù)寫入
- 扇區(qū)擦除與批量擦除
- 存儲器構成
??Flash 結構如下:
??— 主存儲器塊,含 4 個 16 KB 扇區(qū)、1 個 64 KB 扇區(qū) 和 7 個 128 KB 扇區(qū)。
??— 系統(tǒng)存儲器,器件在系統(tǒng)存儲器自舉模式下從該存儲器自舉。此區(qū)域為意法半導體預留,其中包含自舉程序,用以通過以下接口之一對 Flash 進行重新編程:USART1、USART3、CAN2、USB OTG FS 設備模式(DFU:設備固件升級)。自舉程序由 ST 在器件制造期間編寫,用于防止誤寫/誤擦除操作。
??— 512 OTP(一次性可編程)字節(jié),用于存儲用戶數(shù)據(jù)。OTP 區(qū)域包含 16 個附加字節(jié),用于鎖定相應的 OTP 數(shù)據(jù)塊。
??— 選項字節(jié):讀寫保護、BOR 級別、軟件/硬件看門狗以及器件在待機或停機模式下的復位。
四、OTP函數(shù)介紹
1. HAL_StatusTypeDef HAL_FLASH_Unlock(void);
??作用:解鎖FLASH控制寄存器訪問
??返回值:寫寄存器的狀態(tài)
2. HAL_StatusTypeDef HAL_FLASH_Lock(void);
??作用:鎖定FLASH控制寄存器訪問
??返回值:寫寄存器的狀態(tài)
3. HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void);
??作用:解鎖FLASH選項控制寄存器訪問
??返回值:寫寄存器的狀態(tài)
4. HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void);
??作用:鎖定FLASH選項控制寄存器訪問
??返回值:寫寄存器的狀態(tài)
5. HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
??作用:啟動選項字節(jié)加載
??返回值:寫寄存器的狀態(tài)
6. HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
??作用通過選定的字節(jié)類型進行數(shù)據(jù)寫入
??返回值:寫寄存器的狀態(tài)
7. OPT數(shù)據(jù)讀寫過程代碼:由于OPT是用戶數(shù)據(jù)的一次性寫入,所有需要確定寫入的數(shù)據(jù)無誤,不然存儲的數(shù)據(jù)一旦寫入,就無法再進行更改,但是可以進行無數(shù)次的讀寫。
// 定義OPT區(qū)域的起始地址和結束地址
#define OPT_START_ADDR 0x1FFF7800
#define OPT_END_ADDR 0x1FFF7A0F/*** @brief 寫入數(shù)據(jù)到OPT區(qū)域* @param data:需要寫的用戶數(shù)據(jù)* @param size:數(shù)據(jù)個數(shù)*/
void write_to_opt(uint32_t *data, uint32_t size)
{uint32_t addr = OPT_START_ADDR;HAL_StatusTypeDef status;// 檢查數(shù)據(jù)大小是否超過OPT區(qū)域的大小if ((size * 4) > (OPT_END_ADDR - OPT_START_ADDR)){return;}HAL_FLASH_Unlock(); // 解鎖FLASHstatus = HAL_FLASH_OB_Unlock(); // 解鎖選項字節(jié)區(qū)域HAL_FLASH_OB_Launch(); // 生效設置// 寫入OPT數(shù)據(jù)for (uint32_t i = 0; i < size; i++){// 按字寫入數(shù)據(jù)status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, data[i]);if (status != HAL_OK){rt_kprintf("opt data write error!!!\n");break;}addr += 4;}// 鎖定FLASHHAL_FLASH_OB_Lock();HAL_FLASH_Lock();
}// 讀取OPT區(qū)域的數(shù)據(jù)
void read_from_opt(uint32_t *data, uint32_t size)
{uint32_t addr = OPT_START_ADDR;for (uint32_t i = 0; i < size; i++){data[i] = *(uint32_t*) addr;addr += 4;}
}/*** @brief 設置OPT數(shù)據(jù)*/
int write_opt_data(int argc, char **argv)
{if (argc != 2 && argc != 3){return -RT_ERROR;}else{if (strcmp(argv[0], "opt") == 0){if (argc == 3){if (strcmp(argv[1], "w") == 0){int size = atoi(argv[2]);uint32_t time[50] = {0};if (atoi(argv[2]) <= 50){read_from_opt(time, size);for (int i = 0; i < size; ++i){rt_kprintf("time[%d]:%u\n", i, time[i]);}}}}else{uint32_t time = (uint32_t)strtol(argv[1], NULL, 16);rt_kprintf("time:%u(0x%X)\n", time, time);write_to_opt(&time, 1);}}else{return -RT_ERROR;}}return RT_TRUE;
}
MSH_CMD_EXPORT_ALIAS(write_opt_data, opt, write_opt_data);
五、測試驗證
??通過下面的測試數(shù)據(jù)可以看到,當?shù)谝淮螌懭霐?shù)據(jù)之后,可以正常讀取導數(shù)據(jù),讀取的數(shù)據(jù)是寫入的數(shù)據(jù)。當?shù)诙沃匦聦懭霐?shù)據(jù)的時候,讀取到的數(shù)據(jù)還是之前寫入的數(shù)據(jù),沒有改變,因此說明OPT數(shù)據(jù)只會被寫入一次,然后無法再次寫入。