flash

Flash的操作:

stm32大容量的flash不仅用来存储程序代码,还可用来存储一些数据和系统用户的参数。程序的代码一般保存在从flash开始区域,剩下的区域空间大小可以用来存储用户数据(大小取决于Flash的大小和代码占用空间的大小)。如果存储的数据很少可以用最后一页用于专门的存贮用户数据,这样可以防止和程序代码空间冲突。

 

1STM32Flash有读写次数和寿命的限制,所以不要放在循环中反复执行读写操作

2FLASH的读写均需要时间,设置等待周期是为了确保正确的读写。因为cpu的速度远远大于FLASH的操作速度。用库函数FLASH_SetLatency(FLASH_Latency_2)来设置。

3开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的
用法:FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

4、打开内部振荡器RCC_HSICmd(ENABLE);

5STM32Flash的操作必须遵循一定的步骤,必须先擦除再写入,擦除必须以PAGE(页)位单位,写(编程)必须以Word(两字节)为单位。

6、关于读保护和写保护

配置了读保护之后,Flash中的代码和数据无法通过JTAGRAM中的程序读出,起到了加密的作用。写保护是以页(或多页)为单位的,配置之后无法被擦除或修改,加强了代码的可靠性。 读保护和写保护都是在自己的程序中配置的。你可以在第一次运行程序是配置相关选择字。

 

程序是从0x0800f800开始写入2个半字的数据,然后在MAIN函数中用串口返回:

void flash_write()

{u16 cnt 0;

u16 data[2]={0x1234,0x5678};

FLASH_Unlock();

FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);

FLASH_ErasePage(0x0800f800);

for(cnt=0;cnt<</span>2;cnt++)

FLASH_ProgramHalfWord((0x0800f800 +cnt*2),data[cnt]);  

FLASH_Lock();

}

MAIN函数关于Flash操作的代码:

  uint8_t i;

  FLASH_SetLatency(FLASH_Latency_2);

  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

  flash_write();

  *( uint32_t *)(0x0800f802);//读取改地址的数据,赋值i

  send_byte(i);//串口返回0x0800f802地址处的数据 


因为之前想写一个字节老是出错,所以翻翻手册,果然看到不能写1个字节数据。而且还发现,flash写地址为奇数时也会出错。所以这份代码里面

flash的地址只能是偶数。浏览过程中还发现,手册里面说写flash和擦除flash的时候会影响cpu的运行速度,没仔细看(真心不想看)。


1.  -DataFlash.c----------------------------------  

2.    

3.  #include "DataFlash.h"  


4  uint16_t Flash_Write_Without_check(uint32_t iAddress, uint8_t *buf, uint16_t iNumByteToWrite) {  

9.      uint16_t i;  

10.    volatile FLASH_Status FLASHStatus FLASH_COMPLETE;  

11.    0;  

12.      

13.//    FLASH_UnlockBank1();  

14.    while((i iNumByteToWrite) && (FLASHStatus == FLASH_COMPLETE))  

15.     

16.      FLASHStatus FLASH_ProgramHalfWord(iAddress, *(uint16_t*)buf);  

17.      i+2;  

18.      iAddress iAddress 2;  

19.      buf buf 2;  

20.     

21.      

22.    return iNumByteToWrite;  

23. 

24.//  

33.int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite)  

34.                /  

35.        uint32_t secpos;  

36.        uint32_t iNumByteToWrite iNbrToWrite;  

37.uint16_t secoff;  

38.uint16_t secremain;    

39.  uint16_t 0;      

40.        uint8_t tmp[FLASH_PAGE_SIZE];  

41.          

42.        FLASH_UnlockBank1();  

43.secpos=iAddress (~(FLASH_PAGE_SIZE -1 )) ;//扇区地址   

44.secoff=iAddress (FLASH_PAGE_SIZE -1);     //在扇区内的偏移  

45.secremain=FLASH_PAGE_SIZE-secoff;           //扇区剩余空间大小   

46.        volatile FLASH_Status FLASHStatus FLASH_COMPLETE;  

47.          

48.        if(iNumByteToWrite<=secremain) secremain iNumByteToWrite;//不大于4096个字节  

49.          

50.        while 

51.            Flash_Read(secpos, tmp, FLASH_PAGE_SIZE);   //读出整个扇区  

52.            for(i=0;i//校验数据  

53.       if(tmp[secoff+i]!=0XFF)break      //需要擦除   

54.    

55.            if(i//需要擦除  

56.                FLASHStatus FLASH_ErasePage(secpos); //擦除这个扇区  

57.                if(FLASHStatus != FLASH_COMPLETE)  

58.                  return -1;  

59.                for(i=0;i//复制  

60.                        tmp[i+secoff]=buf[i];    

61.                 

62.                Flash_Write_Without_check(secpos ,tmp ,FLASH_PAGE_SIZE);//写入整个扇区    

63.            else  

64.                Flash_Write_Without_check(iAddress,buf,secremain);//写已经擦除了的,直接写入扇区剩余区间.  

65.             

66.              

67.            if(iNumByteToWrite==secremain) //写入结束了  

68.                break 

69.            else  

70.                secpos += FLASH_PAGE_SIZE;  

71.                secoff 0;//偏移位置为  

72.                buf += secremain;  //指针偏移  

73.                iAddress += secremain;//写地址偏移     

74.                iNumByteToWrite -= secremain; //字节数递减  

75.                if(iNumByteToWrite>FLASH_PAGE_SIZE) secremain=FLASH_PAGE_SIZE;//下一个扇区还是写不完  

76.                else secremain iNumByteToWrite; //下一个扇区可以写完了  

77.             

78.              

79.          

80.          

81.        FLASH_LockBank1();  

82.        return iNbrToWrite;   

83. 


90.  

99.int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead)  

100.        int 0;  

101.        while(i iNbrToRead  

102.           *(buf i) *(__IO uint8_t*) iAddress++;  

103.           i++;  

104.         

105.        return i;  

106.}  

110.-------------------DataFlash.h----------------------------------  

111.  

112.#ifndef   __DATAFLASH_H__  

113.#define   __DATAFLASH_H__  

114.  

115.  

116.#include "stm32f10x.h"  

117.#include "stm32f10x_flash.h"  

#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)  

123.  #define FLASH_PAGE_SIZE    ((uint16_t)0x800)  

124.    

125.#else  

126.  #define FLASH_PAGE_SIZE    ((uint16_t)0x400)  

127.#endif  

132.int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead)  

133.int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite);  

134.  

135.  

136.#endif  


///

实践过的代码:

void SetSysClockFromHSI(void) //设置高速内部时钟

{

// SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   

// RCC system reset(for debug purpose) */

RCC_DeInit();

// Enable HSI */

RCC_HSICmd(ENABLE);//打开内部振荡器RCC_HSICmd(ENABLE);


// Enable Prefetch Buffer */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//开启FLASH预读缓冲功能,加速FLASH的读取

// 0 wait state from 0 to 24 MHz 

// 1 wait state from 24 to 48 MHz

// 2 wait states above.

// Flash wait state */

if(RCC_PLLMul_Config <= RCC_PLLMul_6)// <=24 MHz

//#define FLASH_Latency_0     ((uint32_t)0x00000000)  //< FLASH Zero Latency cycle */

FLASH_SetLatency(FLASH_Latency_0);//设置代码延时值 

else if(RCC_PLLMul_Config <= RCC_PLLMul_12)// <=48 MHz

//#define FLASH_Latency_1      ((uint32_t)0x00000001)  //< FLASH One Latency cycle */

FLASH_SetLatency(FLASH_Latency_1);

else

//#define FLASH_Latency_2      ((uint32_t)0x00000002)  //< FLASH Two Latency cycles */ FLASH两个延迟周期

FLASH_SetLatency(FLASH_Latency_2);

//HCLK = SYSCLK */

RCC_HCLKConfig(RCC_SYSCLK_Div1); 

// PCLK2 = HCLK */

RCC_PCLK2Config(RCC_HCLK_Div1); 

// PCLK1 = HCLK */

RCC_PCLK1Config(RCC_HCLK_Div1);

// PLLCLK = 4MHz * RCC_PLLMul_Config */

RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_Config);

//Enable PLL */ 

RCC_PLLCmd(ENABLE);

// Wait till PLL is ready */

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}

//Select PLL as system clock source */

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

// Wait till PLL is used as system clock source */

/

while(RCC_GetSYSCLKSource() != 0x08){}

 

}

/

u8 FLASH_WriteNByte(u32 addr, s16 *dat_buf, u8 no)

{

//Unlock the Flash Program Erase controller */

FLASH_Unlock(); // FLASH解锁


if(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET) return FALSE; // 以确认没有其他正在进行的编程操作,则返回错误退出


// Clear All pending flags */

FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); // 清标志位


while(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET);

FLASHStatus = FLASH_ErasePage(addr);

  while(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET);


while(no && (FLASHStatus == FLASH_COMPLETE))

{

FLASHStatus = FLASH_ProgramHalfWord(addr, *dat_buf); // 以16bit宽度写入,内部包含设置FLASH_CR寄存器的PG位为1的步骤

addr += 2; //flash写地址为奇数时也会出错

dat_buf++;

no--;

while(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET); // 等待写入结束

}

FLASH_Lock(); // FLASH上锁

while(FLASH_GetFlagStatus(FLASH_FLAG_BSY) == SET);


if(no == 0) return TRUE;

else return FALSE;

}


/

void FLASH_ReadNByte(u32 addr, s16 *dat_buf, u8 no)

{

u8 HalfWordN = 0;

while(no)

{

dat_buf[HalfWordN] = *(vs16*)(addr + HalfWordN * 2);//偏移量 FLASH为偶数地址

HalfWordN++;

no--;

}

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值