STM32F4 內(nèi)部flash驅(qū)動(dòng)(寄存器操作)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
STM32F4 內(nèi)部flash驅(qū)動(dòng)(寄存器操作)
stm32f4_flash.c
/************************************************************************************************************* ?*?文件名: stm32f4_flash.c ?*?功能: STM32F4?內(nèi)部FLASH編程驅(qū)動(dòng)函數(shù) ?*?作者: cp1300@139.com ?*?創(chuàng)建時(shí)間: 2013-10-20 ?*?最后修改時(shí)間: 2018-01-13 ?*?詳細(xì): 用于STM32F4內(nèi)部flash讀寫驅(qū)動(dòng) 2018-01-13:初始版本,默認(rèn)位寬為32位,寫入的數(shù)據(jù)必須32位對(duì)齊,供電必須在2.7-3.6V之間,建議使用3.3V供電 2018-01-16:修復(fù)扇區(qū)擦除時(shí)沒有解鎖問題 *************************************************************************************************************/ #include?"stm32f4_flash.h" #include?"system.h" //FLASH?扇區(qū)的起始地址 #define?ADDR_FLASH_SECTOR_0?????((u32)0x08000000)? //扇區(qū)0起始地址,?16?Kbytes?? #define?ADDR_FLASH_SECTOR_1?????((u32)0x08004000)? //扇區(qū)1起始地址,?16?Kbytes?? #define?ADDR_FLASH_SECTOR_2?????((u32)0x08008000)? //扇區(qū)2起始地址,?16?Kbytes?? #define?ADDR_FLASH_SECTOR_3?????((u32)0x0800C000)? //扇區(qū)3起始地址,?16?Kbytes?? #define?ADDR_FLASH_SECTOR_4?????((u32)0x08010000)? //扇區(qū)4起始地址,?64?Kbytes?? #define?ADDR_FLASH_SECTOR_5?????((u32)0x08020000)? //扇區(qū)5起始地址,?128?Kbytes?? #define?ADDR_FLASH_SECTOR_6?????((u32)0x08040000)? //扇區(qū)6起始地址,?128?Kbytes?? #define?ADDR_FLASH_SECTOR_7?????((u32)0x08060000)? //扇區(qū)7起始地址,?128?Kbytes?? #define?ADDR_FLASH_SECTOR_8?????((u32)0x08080000)? //扇區(qū)8起始地址,?128?Kbytes?? #define?ADDR_FLASH_SECTOR_9?????((u32)0x080A0000)? //扇區(qū)9起始地址,?128?Kbytes?? #define?ADDR_FLASH_SECTOR_10????((u32)0x080C0000)? //扇區(qū)10起始地址,128?Kbytes?? #define?ADDR_FLASH_SECTOR_11????((u32)0x080E0000)? //扇區(qū)11起始地址,128?Kbytes?? /************************************************************************************************************************* *?函數(shù) : void?STM32FLASH_Unlock(void) *?功能 : 解鎖STM32的FLASH *?參數(shù) : 無 *?返回 : 無 *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2013-10-20 *?說明 :? *************************************************************************************************************************/ void?STM32FLASH_Unlock(void) { FLASH->KEYR=FLASH_KEY1; //寫入解鎖序列. FLASH->KEYR=FLASH_KEY2; } /************************************************************************************************************************* *?函數(shù) : void?STM32FLASH_Lock(void) *?功能 : 上鎖STM32的FLASH *?參數(shù) : 無 *?返回 : 無 *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2018-01-13 *?說明 :? *************************************************************************************************************************/ void?STM32FLASH_Lock(void) { FLASH->CR|=(u32)1<SR;? if(temp&(1<<16))return?STM32FLASH_BUSY; //忙 else?if(temp&(1<<4))return?STM32FLASH_WPRERR; //寫保護(hù)錯(cuò)誤 else?if(temp&(1<<5))return?STM32FLASH_PGAERR; //編程對(duì)齊錯(cuò)誤 else?if(temp&(1<<6))return?STM32FLASH_PGPERR; //并行位數(shù)錯(cuò)誤 else?if(temp&(1<<7))return?STM32FLASH_PGSERR; //編程順序錯(cuò)誤 return?STM32FLASH_OK; //操作完成 } /************************************************************************************************************************* *?函數(shù) : STM32FLASH_STATUS?STM32FLASH_WaitDone(u32?time) *?功能 : 等待操作完成 *?參數(shù) : time:要延時(shí)的長短,單位us *?返回 : STM32FLASH_STATUS *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2018-01-03 *?說明 :? *************************************************************************************************************************/ STM32FLASH_STATUS?STM32FLASH_WaitDone(u32?time) { STM32FLASH_STATUS?status; if(time?<?1)?time?=?1; do { status=STM32FLASH_GetStatus(); //獲取狀態(tài) if(status!=STM32FLASH_BUSY)break; //非忙,無需等待了,直接退出. Delay_US(1); time--; ?}while(time); ?return?status; } /************************************************************************************************************************* *?函數(shù) : STM32FLASH_STATUS?STM32FLASH_EraseSector(u8?sectoraddr) *?功能 : 扇區(qū)擦除 *?參數(shù) : sectoraddr:扇區(qū)地址,0-11 *?返回 : STM32FLASH_STATUS *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2018-01-03 *?最后修改時(shí)間? :? 2018-01-03 *?說明 :? 扇區(qū)大?。?~3:16KB扇區(qū);4:64KB扇區(qū);5~11:128KB扇區(qū) 128KB扇區(qū)擦除足最大2秒 2018-01-16:修復(fù)扇區(qū)擦除時(shí)沒有解鎖問題 *************************************************************************************************************************/ STM32FLASH_STATUS?STM32FLASH_EraseSector(u8?sectoraddr) { STM32FLASH_STATUS?status; status=STM32FLASH_WaitDone(200000); //等待上次操作完成,最大時(shí)間2秒,如果已經(jīng)操作完成了會(huì)直接跳過 STM32FLASH_Unlock(); //解鎖? if(status==STM32FLASH_OK) //沒有錯(cuò)誤 {? FLASH->CR&=~(3<CR|=2<CR&=~(0X1F<CR|=sectoraddr<CR|=1<CR|=1<CR&=~(1<CR&=~(3<CR|=2<CR|=1<CR&=~(1<<0); //清除PG位. } }? return?status; }? /************************************************************************************************************************* *?函數(shù) : u32?STM32FLASH_ReadWord(u32?faddr) *?功能 : 讀取指定地址的一個(gè)字(32位數(shù)據(jù))? *?參數(shù) : faddr:指定地址(此地址必須為4的倍數(shù)!!); *?返回 : 數(shù)據(jù) *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2018-01-03 *?最后修改時(shí)間? :? 2018-01-03 *?說明 :? 警告:地址必須是4的整數(shù)倍 *************************************************************************************************************************/ u32?STM32FLASH_ReadWord(u32?faddr) { return?*(vu32*)faddr;? } /************************************************************************************************************************* *?函數(shù) : u8?STM32FLASH_GetFlashSector(u32?faddr) *?功能 : 獲取某個(gè)地址所在的扇區(qū) *?參數(shù) : faddr:指定地址 *?返回 : 刪除編號(hào),0-11,如果超出了也會(huì)限制到11 *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2018-01-03 *?最后修改時(shí)間? :? 2018-01-03 *?說明 :? 地址請(qǐng)不要超出范圍 *************************************************************************************************************************/ u8?STM32FLASH_GetFlashSector(u32?faddr) { if(faddr<ADDR_FLASH_SECTOR_1) return?0; else?if(faddr<ADDR_FLASH_SECTOR_2) return?1; else?if(faddr<ADDR_FLASH_SECTOR_3) return?2; else?if(faddr<ADDR_FLASH_SECTOR_4) return?3; else?if(faddr<ADDR_FLASH_SECTOR_5) return?4; else?if(faddr<ADDR_FLASH_SECTOR_6) return?5; else?if(faddr<ADDR_FLASH_SECTOR_7) return?6; else?if(faddr<ADDR_FLASH_SECTOR_8) return?7; else?if(faddr<ADDR_FLASH_SECTOR_9) return?8; else?if(faddr<ADDR_FLASH_SECTOR_10) return?9; else?if(faddr<ADDR_FLASH_SECTOR_11) return?10;? else?return?11; } /************************************************************************************************************************* *?函數(shù) : STM32FLASH_STATUS?STM32FLASH_Write_NoCheck(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite)?? *?功能 : 不檢查的寫入 *?參數(shù) : WriteAddr:起始地址(必須是4個(gè)整數(shù)倍);pBuffer:數(shù)據(jù)指針;NumToWrite:半(32位)數(shù)? *?返回 : 狀態(tài) *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2018-01-03 *?說明 :? 地址必須為4對(duì)齊,如果出現(xiàn)了非FF寫入程序會(huì)報(bào)錯(cuò)并返回(由于STM32硬件會(huì)對(duì)寫入?yún)^(qū)域進(jìn)行檢查,非FF區(qū)域不允許寫入) *************************************************************************************************************************/ STM32FLASH_STATUS?STM32FLASH_Write_NoCheck(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite)??? {? ? ? u16?i; STM32FLASH_STATUS?status; if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return?STM32FLASH_PGPERR?; //非法地址,如果不是4的倍數(shù),返回并行錯(cuò)誤 STM32FLASH_Unlock(); //解鎖? for(i=0;i<NumToWrite;i++) { status?=?STM32FLASH_WriteWord(WriteAddr,pBuffer[i]); if(status?!=?STM32FLASH_OK)?break; //寫入出錯(cuò),直接返回 ????WriteAddr+=4; //地址增加4. } STM32FLASH_Lock(); //上鎖 return?status; }? /************************************************************************************************************************* *?函數(shù) : STM32FLASH_STATUS?STM32FLASH_Write(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite) *?功能 : 從指定地址開始寫入指定長度的數(shù)據(jù)(數(shù)據(jù)長度字為單位) *?參數(shù) : WriteAddr:起始地址(此地址必須為4的倍數(shù)!!);pBuffer:數(shù)據(jù)指針;NumToWrite:字(32位)數(shù)(就是要寫入的32位數(shù)據(jù)的個(gè)數(shù).) *?返回 : 0:完成;1:忙;2:錯(cuò)誤;3:寫保護(hù) *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2016-01-07 *?說明 :? 警告:由于STM32F4的扇區(qū)太大,無法使用內(nèi)存進(jìn)行緩存,如果要寫入的位置有非FF,會(huì)直接將整個(gè)扇區(qū)進(jìn)行擦除,并丟失其它的數(shù)據(jù) *************************************************************************************************************************/? STM32FLASH_STATUS?STM32FLASH_Write(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite) { STM32FLASH_STATUS?status; u32?addrx=0; u32?endaddr=0; ?? if(WriteAddrACR&=~(1<<10); //FLASH擦除期間,必須禁止數(shù)據(jù)緩存!!!搞了我兩晚上才發(fā)現(xiàn)這個(gè)問題! addrx=WriteAddr; //寫入的起始地址 endaddr=WriteAddr+NumToWrite*4; //寫入的結(jié)束地址 if(addrx<0X1FFF0000) //只有主存儲(chǔ)區(qū),才需要執(zhí)行擦除操作!! { while(addrx<endaddr) //掃清一切障礙.(對(duì)非FFFFFFFF的地方,先擦除) { if(STM32FLASH_ReadWord(addrx)!=0XFFFFFFFF) //有非0XFFFFFFFF的地方,要擦除這個(gè)扇區(qū) {??? status=STM32FLASH_EraseSector(STM32FLASH_GetFlashSector(addrx)); if(status?!=?STM32FLASH_OK)break; //發(fā)生錯(cuò)誤了 }else?addrx+=4; }? } if(status==STM32FLASH_OK) { STM32FLASH_Unlock(); //解鎖? while(WriteAddrACR|=1<<10; //FLASH擦除結(jié)束,開啟數(shù)據(jù)fetch return?status; } /************************************************************************************************************************* *?函數(shù) : u16?STM32FLASH_Read(u32?ReadAddr,u32?*pBuffer,u16?NumToRead)? *?功能 : 從指定地址開始讀出指定長度的數(shù)據(jù) *?參數(shù) : ReadAddr:起始地址;pBuffer:數(shù)據(jù)指針;NumToWrite:字(32位)數(shù) *?返回 : 讀取的數(shù)據(jù)長度(字為單位) *?依賴 : 底層 *?作者 : cp1300@139.com *?時(shí)間 : 2013-10-20 *?最后修改時(shí)間? :? 2016-01-07 *?說明 :? 地址必須為4對(duì)齊 *************************************************************************************************************************/ u16?STM32FLASH_Read(u32?ReadAddr,u32?*pBuffer,u16?NumToRead)??? { u16?i; u16?cnt?=?0; if(ReadAddr<STM32_FLASH_BASE||ReadAddr%4)return?0; //非法地址 for(i=0;i<NumToRead;i++) { pBuffer[i]=STM32FLASH_ReadWord(ReadAddr); //讀取4個(gè)字節(jié). cnt++; ReadAddr+=4; //偏移4個(gè)字節(jié). } return?cnt; }
//stm32f4_flash.h
/************************************************************************************************************* ?*?文件名: stm32f4_flash.h ?*?功能: STM32F4?內(nèi)部FLASH編程驅(qū)動(dòng)函數(shù) ?*?作者: cp1300@139.com ?*?創(chuàng)建時(shí)間: 2013-10-20 ?*?最后修改時(shí)間: 2018-01-13 ?*?詳細(xì): 用于STM32F4內(nèi)部flash讀寫驅(qū)動(dòng) 2018-01-13:初始版本 *************************************************************************************************************/ #ifndef?__STM32F4_FLASH_H__ #define?__STM32F4_FLASH_H__ #include?"system.h"?? //FLASH起始地址 #define?STM32_FLASH_BASE?0x08000000? //STM32?FLASH的起始地址 //FLASH解鎖鍵值 #define?FLASH_KEY1???????????????0X45670123 #define?FLASH_KEY2???????????????0XCDEF89AB //STM32F4?Flash操作狀態(tài) typedef?enum { STM32FLASH_OK = 0, //操作完成 STM32FLASH_BUSY = 1, //忙 STM32FLASH_WPRERR = 2, //寫保護(hù)錯(cuò)誤 STM32FLASH_PGAERR = 3, //編程對(duì)齊錯(cuò)誤,必須128位對(duì)齊 STM32FLASH_PGPERR = 4, //并行位數(shù)錯(cuò)誤 STM32FLASH_PGSERR = 5, //編程順序錯(cuò)誤 }STM32FLASH_STATUS; //相關(guān)接口函數(shù) void?STM32FLASH_Unlock(void); //FLASH解鎖 void?STM32FLASH_Lock(void); ?? //FLASH上鎖 STM32FLASH_STATUS?STM32FLASH_GetStatus(void); ?? //獲得狀態(tài) STM32FLASH_STATUS?STM32FLASH_EraseSector(u8?sectoraddr); ?? //擦除扇區(qū) STM32FLASH_STATUS?STM32FLASH_WriteWord(u32?faddr,?u32?data); //在FLASH指定地址寫入一個(gè)字的數(shù)據(jù)(32bit寫入)?【警告:地址必須是4的整數(shù)倍】 u32?STM32FLASH_ReadWord(u32?faddr); //讀取指定地址的一個(gè)字(32位數(shù)據(jù))?【警告:地址必須是4的整數(shù)倍】 STM32FLASH_STATUS?STM32FLASH_Write_NoCheck(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite)?;?//不檢查的寫入? STM32FLASH_STATUS?STM32FLASH_Write(u32?WriteAddr,u32?*pBuffer,u16?NumToWrite); //從指定地址開始寫入指定長度的數(shù)據(jù)(數(shù)據(jù)長度字為單位) u16?STM32FLASH_Read(u32?ReadAddr,u32?*pBuffer,u16?NumToRead); //從指定地址開始讀出指定長度的數(shù)據(jù) #endif //__STM32F4_FLASH_H__