w25qxx spi flash WP写保护引脚的正确使用方式

您所在的位置:网站首页 怎么关掉写保护 w25qxx spi flash WP写保护引脚的正确使用方式

w25qxx spi flash WP写保护引脚的正确使用方式

2023-08-24 18:07| 来源: 网络整理| 查看: 265

WP引脚使用方式

spi flash有一个外部写保护引脚WP, 此引脚并不是直接保护flash上的数据内容,而是保护状态寄存器不被异常改写.flash上的内容写保护是通过状态寄存器的BPxbit的不同组合来实现的. 对于环境相对恶劣的使用场景(供电不稳等.)需要对flash上的内容加以保护.整体的设计思路就是 使用状态寄存器的BPx位组合实现flash上数据内容的局部或整体写保护. 外部WP引脚的电平状态结合状态寄存器的SRP位实现状态寄存器的保护进而间接保护flash上受保护的数据内容.

通过BPx位组合实现的flash写保护,其实是把flash受保护区域置为了只读状态. 这种情况下除非改变flash状态寄存器的BPx位,解除写保护,否则无法擦写受保护区域.

针对相对重要或者是基本不会变动的数据,比如字库等,就可以放置在flash的受保护区域,作为只读数据存在.确保恶劣条件下数据的稳定性.

关键寄存器描述

这里仅贴出一些关键的寄存器,更详细的描述还需要参考数据手册.

状态寄存器写保护测试

通过状态寄存器的写保护位配合外部WP引脚状态,达到状态寄存器的写保护效果.

#define WP_HIGH() GPIO_Set_Output_Data_Bits(GPIOC_SFR,GPIO_PIN_MASK_0,Bit_SET) #define WP_LOW() GPIO_Set_Output_Data_Bits(GPIOC_SFR,GPIO_PIN_MASK_0,Bit_RESET) #define SPI_FLASH_RDSR 0x05 /* read status register */ #define SPI_FLASH_WRSR 0x01 /* write status register */ static uint8_t flash_readstatus(uint8_t addr) { uint8_t datain, i; SPI_FLASH_ENABLE(); SpiWrite(&addr, 1); datain = SpiReadByte(); SPI_FLASH_DISABLE(); return datain; } static void flash_writestatus(uint8_t addr, uint8_t status) { uint8_t dataout[2] = {0}; SpiSimpleCmd(SPI_FLASH_WREN); dataout[0] = addr; dataout[1] = status; SPI_FLASH_ENABLE(); SpiWrite(dataout, 2); SPI_FLASH_DISABLE(); while(1){ if ((flash_readstatus(SPI_FLASH_RDSR) & 0x01) == 0) // 等待flash操作完成. break; delay_ms(5); } } uint8_t flash_statustest(void) { uint8_t get_data = 0; /* 写入0x80, 此时拉低WP引脚,即状态寄存器处于hardware protedted模式.状态寄存器不可写入. 拉高WP引脚, 状态寄存器处于hardware unprotected,状态寄存器可写. */ get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); flash_writestatus(SPI_FLASH_WRSR, 0x80); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); WP_LOW(); // 拉低时, 写入无效. flash_writestatus(SPI_FLASH_WRSR, 0x8C); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); WP_HIGH(); // 拉高时, 写入有效. flash_writestatus(SPI_FLASH_WRSR, 0x8C); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n\r\n", get_data); } //打印结果 status = 0x8c status = 0x80 status = 0x80 // 拉低后写入0x8C无效 状态寄存器仍为0x80. status = 0x8c // 拉高后写入0x8C生效 flash数据内容写保护测试

通过BPx位组合实现的flash写保护,其实是把flash受保护区域置为了只读状态. 这种情况下除非改变flash状态寄存器的BPx位,解除写保护,否则无法擦写受保护区域.

uint8_t flash_datatest(void) { uint8_t get_data = 0; uint8_t write_data[3] = {0x01,0x02,0x03}; uint8_t read_data[3] = {0}; /* 1.所有数据区域都不设置保护, 读写flash测试. 正常擦写. 2.所有数据区域都设置保护(flash数据区处于只读状态), 读写flash测试. 擦写无效. */ WP_HIGH(); // 拉高时, 写入有效. flash_writestatus(SPI_FLASH_WRSR, 0x80); get_data = flash_readstatus(SPI_FLASH_RDSR); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); // 输出0x80 /* 状态寄存器的BPx位组合不保护任何flash数据区域时, 无论外部WP引脚拉高还是拉低, 都数据都能正常写入. */ WP_LOW(); flash_sector_erase(0); flash_write(0, write_data, sizeof (write_data)); flash_read(0, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); WP_HIGH(); write_data[0] = 0x04; write_data[1] = 0x05; write_data[2] = 0x06; flash_sector_erase(0); flash_write(0, write_data, sizeof (write_data)); flash_read(0, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); WP_HIGH(); flash_writestatus(SPI_FLASH_WRSR, 0x9C); // 设置写保护所有扇区 get_data = flash_readstatus(SPI_FLASH_RDSR); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); // 输出0x9C /* flash状态寄存器对所有的flash数据内容设置了写保护.此时无论外部引脚拉高还是拉低. 都无法对flash数据内容进行擦写. 必须解除写保护,才能正常擦写. */ WP_HIGH(); write_data[0] = 0x07; write_data[1] = 0x07; write_data[2] = 0x07; flash_sector_erase(0); flash_write(0, write_data, sizeof (write_data)); flash_read(0, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); WP_LOW(); write_data[0] = 0x07; write_data[1] = 0x07; write_data[2] = 0x07; flash_sector_erase(0); flash_write(0, write_data, sizeof (write_data)); flash_read(0, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); /* 设置状态寄存器保护低8K数据. */ WP_HIGH(); flash_writestatus(SPI_FLASH_WRSR, 0xE8); // 设置写保护低8K数据 get_data = flash_readstatus(SPI_FLASH_RDSR); get_data = flash_readstatus(SPI_FLASH_RDSR); uart_printf("status = 0x%x\r\n", get_data); // 输出0xE8 /* 设置了保护低8K数据, 即低8K为只读.无法擦写. */ write_data[0] = 0x07; write_data[1] = 0x07; write_data[2] = 0x07; flash_sector_erase(0); flash_write(0, write_data, sizeof (write_data)); flash_read(0, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); /* 高于8K地址的数据不受保护,可正常擦写. */ flash_sector_erase(0x1000*2); flash_write(0x1000*2, write_data, sizeof (write_data)); flash_read(0x1000*2, read_data, sizeof (read_data)); uart_printf("get_data = 0x%x 0x%x 0x%x\r\n", read_data[0],read_data[1],read_data[2]); // 打印结果. status = 0x80 // 未保护数据区域 flash正常擦写 get_data = 0x1 0x2 0x3 get_data = 0x4 0x5 0x6 status = 0x9c // 保护全部区域 flash无法擦写 保持之前的值 get_data = 0x4 0x5 0x6 get_data = 0x4 0x5 0x6 status = 0xe8 // 保护低8K 0地址保持之前的值 8K之后正常擦写. get_data = 0x4 0x5 0x6 get_data = 0x7 0x7 0x7 } 总结

本文对spi flash 的WP引脚做了相对深入的分析.结合数据手册给了其基本用法,读者如需更深入的用法, 还需结合数据手册进行深入分析.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3