ST意法半导体
直播中

李巍

8年用户 1532经验值
私信 关注
[问答]

STM32F407 Flash写入数据失败的原因?怎么解决?

STM32F407VGT6 标准库
    往Flash中写入数据,写入完成后再次读取,发现没有写入成功。printf 打印擦除和写入的步骤发现,返回的 FLASH_Status 都是 7。关于错误码,在网上找到的一些解释都比较模糊,没有具体的案例说明问题出现的原因和解决方案。
    把其他的代码全部注释掉,只保留Flash和串口打印相关的代码,再次执行,发现返回值都是9,说明擦除和写入无异常。
    请问出现这种问题的原因在哪里?如果是程序的问题,该从哪方面排查?

部分代码:
/**************************************************************************
*函  数:给指定地址写入指定长度的数据
*参  数:
*        @address:要写入数据的首地址
*        @data:要写入的数据
*        @len:数据长度
*备  注:要实现确保写入数据的区域没有写入其他数据,如果有,会执行全扇区的擦除,
*        可能会导致其他数据丢失。
**************************************************************************/
void FLASH_WriteData(uint32_t address, uint8_t *data, uint32_t len)
{
        uint32_t end_address = address + len;
        uint32_t index_address = address;
        if(index_address < FLASH_BASE_ADDRESS || index_address > FLASH_END_ADDRESS)//地址不合法
        {
                return;
        }
        FLASH_Unlock();
        FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存
        while(index_address < end_address)
        {
                if(*(vu32*)index_address != 0xFFFFFFFF)//内容不为0xFFFFFFFF
                {
                        FLASH_Status i = FLASH_EraseSector(FLASH_getSectorNum(index_address), VoltageRange_3);//擦除所在扇区
                        printf("Erase FLASH_Status: %dn", i);
                        if(FLASH_getSectorNum(index_address) == FLASH_Sector_11)//是最后一个扇区
                        {
                                break;
                        }
                        index_address = FLASH_getSectorHeadAddress(index_address) + FLASH_getSectorSize(index_address);//所在扇区已经擦除,直接跳转到下一个扇区的首地址
                }
                else
                {
                        index_address += 4;
                }
        }
        index_address = address;
        while(index_address < end_address)//按8bit大小写入数据
        {
                FLASH_Status i = FLASH_ProgramByte(index_address, *data);
                printf("write FLASH_Status: %dn", i);
                index_address ++;
                data++;
        }
        FLASH_DataCacheCmd(ENABLE);//FLASH擦除期间,必须禁止数据缓存
        FLASH_Lock();
}

回帖(3)

高澜栖

2025-3-11 15:48:25
擦除之前是否进行了擦除操作,另外,擦除的时候尽量关闭一下中断功能。
举报

杨雪

2025-3-11 15:48:35
建议参考下例程的写法,按部就班来,这个是标准流程操作。


标准库里也有例程,写得很清晰的。


STM32F4xx_DSP_StdPeriph_Lib_V1.8.0ProjectSTM32F4xx_StdPeriph_ExamplesFLASHFLASH_Program


先验证sector擦除是否成功;


然后验证单位数据的写操作;


再就是注意那些基本的信息给对,比方地址啊、扇区号等。
举报

马占云

2025-3-11 18:13:43

在STM32F407VGT6中使用标准库进行Flash写入时,如果写入失败,可能的原因有很多。以下是一些常见的原因和解决方案:


1. Flash锁状态



  • 原因:Flash可能被锁住,导致无法写入。


  • 解决方案:在写入之前,确保Flash已解锁。可以使用FLASH_Unlock()函数解锁Flash。


    FLASH_Unlock();



2. Flash擦除不彻底



  • 原因:如果Flash扇区没有正确擦除,写入操作可能会失败。


  • 解决方案:在写入之前,确保目标扇区已被正确擦除。可以使用FLASH_EraseSector()函数擦除扇区。


    FLASH_Status status = FLASH_EraseSector(sector, VoltageRange_3);
    if (status != FLASH_COMPLETE) {
       // 处理错误
    }



3. 写入地址对齐问题



  • 原因:STM32的Flash写入要求数据必须是半字(16位)对齐的,如果地址不对齐,写入会失败。


  • 解决方案:确保写入地址是半字对齐的。


    if ((uint32_t)address & 0x1) {
       // 地址不对齐,处理错误
    }



4. Flash写入过程中断



  • 原因:如果在Flash写入过程中发生了中断,可能会导致写入失败。


  • 解决方案:在写入Flash之前,禁用全局中断,写入完成后再启用。


    __disable_irq();
    FLASH_ProgramHalfWord(address, data);
    __enable_irq();



5. Flash保护位



  • 原因:Flash的保护位可能被设置,导致无法写入。


  • 解决方案:检查并清除Flash的保护位。可以使用FLASH_OB_Unlock()FLASH_OB_Launch()函数来操作选项字节。


    FLASH_OB_Unlock();
    FLASH_OB_Launch();



6. 电压范围不正确



  • 原因:STM32的Flash操作需要正确的电压范围,如果电压范围设置不正确,操作可能会失败。


  • 解决方案:确保在擦除和写入时设置了正确的电压范围。


    FLASH_EraseSector(sector, VoltageRange_3);



7. 硬件问题



  • 原因:硬件问题,如电源不稳定或Flash芯片损坏,也可能导致写入失败。

  • 解决方案:检查硬件连接和电源稳定性。


8. 程序逻辑错误



  • 原因:程序逻辑错误,如重复擦除或写入,可能导致Flash操作失败。

  • 解决方案:仔细检查程序逻辑,确保每一步操作都正确执行。


9. Flash操作超时



  • 原因:Flash操作可能需要较长时间,如果超时,操作可能会失败。

  • 解决方案:增加超时时间或检查是否在操作完成前进行了其他操作。


10. 标准库函数使用错误



  • 原因:标准库函数使用错误,如参数传递错误,可能导致操作失败。

  • 解决方案:仔细检查标准库函数的使用,确保参数正确。


示例代码


以下是一个简单的Flash写入示例:


#include "stm32f4xx.h"

void Flash_Write(uint32_t address, uint16_t data) {
    FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);

    FLASH_Status status = FLASH_EraseSector(FLASH_Sector_5, VoltageRange_3);
    if (status != FLASH_COMPLETE) {
        // 处理错误
        return;
    }

    status = FLASH_ProgramHalfWord(address, data);
    if (status != FLASH_COMPLETE) {
        // 处理错误
        return;
    }

    FLASH_Lock();
}

int main(void) {
    uint32_t address = 0x08020000; // 示例地址
    uint16_t data = 0x1234;

    Flash_Write(address, data);

    while (1) {
        // 主循环
    }
}

总结


通过以上步骤,可以逐步排查和解决STM32F407 Flash写入失败的问题。如果问题仍然存在,建议使用调试工具逐步跟踪代码执行过程,查看每一步的返回值和状态,以找到问题的根源。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分