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ū)大小:0~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__




