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