OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 191|回复: 1

STM32F429 NAND FLASH 驱动问题!

[复制链接]

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2019-9-22
在线时间
36 小时
发表于 5 天前 | 显示全部楼层 |阅读模式
1金钱
uint32_t ftl_find_unused_block(uint32_t sblock, uint8_t flag)
{
    uint32_t temp = 0;
    uint32_t blocknum = 0;

    for (blocknum = sblock + 1; blocknum > 0; blocknum--)
    {
        if (((blocknum - 1) % 2) == flag)   /* 奇偶合格,才检测 */
        {
            nand_readspare((blocknum - 1) * nand_dev.block_pagenum, 0, (uint8_t *)&temp, 4); /* 读块是否被使用标记 */
            if (temp == 0XFFFFFFFF)
            {
                return (blocknum - 1);      /* 找到一个空块,返回块编号 */
            }
        }
    }

    return 0XFFFFFFFF;                      /* 未找到空余块 */
}
此函数是否有问题?我调试的时候,向同一个扇区里面写数据,每次if (temp == 0XFFFFFFFF) 这里永远页无法识别到未使用的块,我记得第一个字节为是否为坏块,第二个字节为是否被占用,第三第四个字节是存储该块所映射到的逻辑地址,如果判断空块的话,应该是判断第一和第二和字节把?

回复

使用道具 举报

0

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2026-1-29
在线时间
12 小时
发表于 3 天前 | 显示全部楼层
此函数存在两个主要问题,导致无法正确识别未使用的块:

问题分析
块号计算错误
循环变量 blocknum 从 sblock + 1 开始递减,但实际处理的是 blocknum - 1 的块号。例如,当 sblock = 3 时,首次循环检查的是块 3(而非预期的块 4),导致始终检查已使用的块。

空闲块判断条件错误
代码将 Spare Area 的前 4 字节合并为 uint32_t 并判断是否全为 0xFFFFFFFF。根据需求,仅需检查前两个字节:

第 1 字节:坏块标记(0xFF 表示正常)
第 2 字节:使用标记(0xFF 表示未使用)

修正后的代码:
uint32_t ftl_find_unused_block(uint32_t sblock, uint8_t flag)
{
    uint8_t spare[2]; // 仅读取前两个字节
    uint32_t blocknum;

    // 从 sblock+1 开始向后遍历所有块
    for (blocknum = sblock + 1; blocknum < nand_dev.total_blocks; blocknum++)
    {
        if ((blocknum % 2) == flag) // 奇偶校验(直接使用 blocknum)
        {
            // 读取块的第一页 Spare Area 的前两个字节
            if (nand_readspare(blocknum * nand_dev.block_pagenum, 0, spare, 2) != 0)
                continue; // 读取失败则跳过

            // 判断是否为未使用的正常块
            if (spare[0] == 0xFF && spare[1] == 0xFF)
            {
                return blocknum; // 返回找到的块号
            }
        }
    }

    // 若未找到,可添加二次遍历逻辑(如从头开始查找)
    return 0XFFFFFFFF;
}

关键修改说明
块号遍历逻辑

将循环改为 递增 遍历(blocknum++),从 sblock + 1 开始向后查找。
直接使用 blocknum 作为块号,避免 blocknum - 1 导致的 Off-by-One 错误。
Spare Area 读取优化
仅读取前两个字节到 uint8_t spare[2],减少不必要的内存操作。
明确检查 spare[0](坏块标记)和 spare[1](使用标记)是否均为 0xFF。
错误处理增强
添加对 nand_readspare 返回值的检查,避免因读取失败导致误判。

扩展建议
循环覆盖所有块:若 sblock 接近末尾时可能遗漏前面的块,可在首次遍历未找到后,从头开始二次遍历。
Bad Block Marker 规范:确认 NAND 厂商文档中 Bad Block 标记的具体位置(某些厂商可能使用多字节标记)。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-4-4 02:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表