#include "SN_FLASH.h" /* 文件名:SN_FLASH.c/.h 作者: SN_FAE_黄泽洪 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证 本人不担负商业使用上带来的风险。 */ /* SN_FLASH 模块使用方法是: 注意: flash有十万次擦写寿命,SN_FLASH_Write_PAGE 千万不要放在死循环里面。 //写入flash数据 uint8_t flash_data_in[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //读出flash数据 uint8_t flash_data_out[20] = {0}; int main(void) { SN_SYSCLK_set(SYSCLK_48MHZ); std_delay_init(); //写入flash数据,扇区选择后面的,不能使用写有代码的扇区 SN_FLASH_Write_PAGE(0x20,flash_data_in, 12); SN_FLASH_ReadE(0x00004000, flash_data_out, 12); while(1); } */ /* 函数:SN_FLASH_Write_PAGE(uint8_t PAGE_NUM,uint8_t * data , uint16_t len) 功能:往一个扇区里面写入最大支持512个字节长度的数据 每次写入同一个扇区,该扇区的512个字节都会被擦除 然后重新写入数据,如果要往同一个扇区写入新数据, 并且保留部分旧数据。就要把这部分旧数据先读取出来, 然后在合在一起,重新写入该扇区。 由于003只有3k的sram,所为该接口不考虑开辟缓冲空间 写入操作都是按扇区的,如果需要跨扇区操作,需要用户 自行完成 参数:扇区号 (注意不要写在代码处) 范围:( 0 - 47 ) 参数:数组 参数:数组长度(现在长度512字节) 返回:成功0 失败1 */ uint8_t SN_FLASH_Write_PAGE(uint8_t PAGE_NUM,uint8_t * data1 , uint16_t len){ uint16_t LEN = len / 4 ; uint8_t *data = data1; uint16_t remainder = (len % 4); //不对齐4位的字节数是多少 uint32_t temp = 0 , temp1 = 0 ,word_count = 0; //中间变量 std_flash_clear_flag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR); //清除所有标志位 std_flash_unlock(); //关闭flash控制寄存器锁 if (STD_OK != std_flash_erase(FLASH_MODE_PAGE_ERASE, (PAGE_NUM * 0x200)))return 1; //flash擦除 //对齐处理 if(LEN){ for (word_count = 0; word_count < LEN; word_count++) { for(int i = 0; i < 4 ; i++){ //4字节合并成一个字 temp1 = ((uint32_t)data[word_count*4 + i]) << (i * 8); temp |= temp1; } //写入32bit if (STD_OK != std_flash_word_program(((PAGE_NUM * 0x200) + ((word_count)*4) ), temp)) return 1; temp = 0;temp1 = 0; } if(!remainder)return 0; //刚好对齐没有尾部 } //不对齐处理 switch(remainder){ case 1 : temp |= ((uint32_t)data[len-1]) | 0xffffff00; break; case 2 : temp1 = ((uint32_t)data[len-1]) << 8; temp1 |= ((uint32_t)data[len-2]) ; temp = temp1 | 0xffff0000; break; case 3 : temp1 = ((uint32_t)data[len-1]) << 16; temp1 |= ((uint32_t)data[len-2]) << 8; temp1 |= ((uint32_t)data[len-3]) ; temp = temp1 | 0xff000000; break; default: return 0; } if(LEN){ if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200)+ (LEN*4) , temp))return 1; //尾部不对齐 }else{ if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200) , temp)) return 1; //头部不凑整 } //开启flash控制寄存器锁 std_flash_lock(); return 0; } /* 函数:SN_FLASH_ReadE(uint8_t flash_add, uint8_t* date, uint16_t len) 功能:检查扇区是否为空 参数:物理地址 (扇区转换为物理地址: flash_add = 扇区号*512) 参数:接收数组 参数:数组长度 返回:无 */ void SN_FLASH_ReadE(uint32_t flash_add, uint8_t* date, uint16_t len){ uint16_t word_count; for( word_count = 0; word_count < len ; word_count++){ date[word_count] = *(uint8_t *)(flash_add + word_count ); } } /* 函数:SN_FLASH_PAGE_null(uint8_t PAGE_NUM) 功能:检查扇区是否为空 参数:扇区号 返回:空返回 0 非空返回 1 */ uint8_t SN_FLASH_PAGE_null(uint8_t PAGE_NUM){ uint16_t word_count = 0 ; uint16_t count = 512 >> 4; for (word_count = 0; word_count < count; word_count++) { /* 校验编程数据 */ if (*(uint32_t *)(0x00000000 + (word_count << 2)) != 0xffffffff) { return 1; } } return 0; } /* 函数:SN_MUC_UID(uint32_t UID[3]) 功能:检查扇区是否为空 参数:接收96位UID的数组 返回:无 */ void SN_MUC_UID(uint32_t UID[3]){ UID[0] = *((uint32_t*)0x1FFF0340+0); UID[1] = *((uint32_t*)0x1FFF0340+1); UID[2] = *((uint32_t*)0x1FFF0340+2); }