03.FLASH读写操作

nor-flash:MX29LV640EBXEI-70G

image.png

● MX29LV640EB 的前 8 个扇区是 8KB,之后的扇区是 64KB。
● 启动扇区8个,每个大小8KB
● 主扇区127个,每个大小64KB

存储大小概念

● 8位数据 = 1个字节
● 比如8K扇区,那么它的大小就是 1024 * 8 = 8192字节
● 在16位的模式下,1次就是2个字节。所以8K的扇区只能存取8192/2 = 4096个数据
● 扇区0的大小是0x000000 - 0x001000

驱动方式:根据电路图,flash是16位模式

image.png

image.png

代码:封装成函数

/**
 * @description: 扇区擦除
 * @param {uint32_t} SectorBaseAddr 某扇区
 * @return {*}
 */
void flash_erase_sector(uint8_t sector_index) {
    uint32_t TimeOut = 0;
    uint16_t status;
    // 1. 获取半字偏移
    uint32_t halfword_offset = SectorOffset[sector_index];

    // 2. 发送解锁和擦除设置命令
    *(FLASH_ADDR + 0x555) = 0x00AA;
    *(FLASH_ADDR + 0x2AA) = 0x0055;
    *(FLASH_ADDR + 0x555) = 0x0080; // 擦除命令

    *(FLASH_ADDR + 0x555) = 0x00AA;
    *(FLASH_ADDR + 0x2AA) = 0x0055;
    // 3. 写入要擦除的扇区地址(注意:偏移量是相对于Flash基址的)
    *(FLASH_ADDR + halfword_offset ) = 0x0030; // 扇区擦除确认

    // 4. 等待擦除完成(擦除耗时较长,通常需几十到几百毫秒)
    while (1) {
        status = *(FLASH_ADDR + halfword_offset);
        if ((status & 0x80) == 0x80)
        {
            break; // DQ7=1 表示擦除完成
        }

        TimeOut++;
        if (TimeOut > 0x2000000) { // 擦除超时设大一些(约几千万次循环)
            shell_uart_write_string("Erase timeout\r\n");
            return;
        }
    }
    shell_uart_write_uint(sector_index);
    shell_uart_write_string(" :sector Erase finish\r\n");
}

/**
 * @description: 向flash读取一个数据
 * @param {unsigned int} sector_index 具体那个扇区
 * @param {unsigned int} index    第几个数据
 * @return {*}
 */
uint16_t flash_read(unsigned int sector_index, unsigned int index) {
    // 1. 计算扇区起始地址(指针类型必须与硬件位宽匹配)
    volatile uint16_t *SectorStart = FLASH_ADDR + SectorOffset[sector_index];

    // 2. 读取目标地址的数据(注意:参数名是 index,不是 num)
    uint16_t data = *(SectorStart + index);

    return data;
}

/**
 * @description: 向flash写入一个16位数据(带超时等待)
 * @param {unsigned int} sector_index 具体那个扇区
 * @param {unsigned int} index 第几个数据
 * @param {unsigned int} udData 要写入的16位数据(取低16位)
 * @return {*} 0:成功, 1:超时失败
 */
unsigned int flash_write(unsigned int sector_index,unsigned int index, unsigned int udData) {
    uint32_t TimeOut = 0;
    uint16_t Data1, Data2;

    // 1. 计算目标地址(基于半字偏移)
    volatile uint16_t *target = FLASH_ADDR + SectorOffset[sector_index] + index;

    // 2. 发送解锁和编程命令序列
    *(FLASH_ADDR + 0x555) = 0x00AA;
    *(FLASH_ADDR + 0x2AA) = 0x0055;
    *(FLASH_ADDR + 0x555) = 0x00A0; // 编程命令

    // 2. 写入目标地址和数据
    *target = (uint16_t)(udData & 0xFFFF);

    // 3. 等待写入完成(使用您已验证过的双重读比较方法)
    while (1) {
        Data1 = *target;
        Data2 = *target;

        if (Data1 == Data2)
            break; // 数据稳定,写入完成

        TimeOut++;
        if (TimeOut > 0x1000000) { // 超时保护
            shell_uart_write_string("Write timeout\r\n");
            return 1; // 返回错误码
        }
    }
    return 0; // 写入成功
}
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容