twodiamond 发表于 2023-7-15 17:19:55

F407 写FLASH SECTOR 第1个字节不成功

请教:

在F407中,做写数据到 FLASH 块,第1个字节总是不能成功,后面都可以正确写入:

       writeAddr= 0x0800C000;

        HAL_FLASH_Unlock();
        FLASH->ACR&=~(1<<10);
        for(i=0; i<=len; i++)
        {
                data = *pData++;
                status = HAL_FLASH_Program(TYPEPROGRAM_BYTE, writeAddr, (uint64_t)data); //i=0时(第1次),status总是返回error
                writeAddr ++;
        }
        FLASH->ACR |= 1<<10;
        HAL_FLASH_Lock();


请问大侠们有遇到过没?

谢谢!!!

eric2013 发表于 2023-7-16 10:18:29

我们也是单字节的,没问题

/*
*********************************************************************************************************
*
*        模块名称 : cpu内部falsh操作模块(for F4)
*        文件名称 : bsp_cpu_flash.c
*        版    本 : V1.0
*        说    明 : 提供读写CPU内部Flash的函数
*        修改记录 :
*                版本号日期      作者   说明
*                V1.0    2013-02-01 armfly正式发布
*
*        Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/

#include "bsp.h"


/*
*********************************************************************************************************
*        函 数 名: bsp_GetSector
*        功能说明: 根据地址计算扇区首地址
*        形    参:无
*        返 回 值: 扇区首地址
*********************************************************************************************************
*/
uint32_t bsp_GetSector(uint32_t Address)
{
        uint32_t sector = 0;

        if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
        {
                sector = FLASH_SECTOR_0;
        }
        else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
        {
                sector = FLASH_SECTOR_1;
        }
        else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
        {
                sector = FLASH_SECTOR_2;
        }
        else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
        {
                sector = FLASH_SECTOR_3;
        }
        else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
        {
                sector = FLASH_SECTOR_4;
        }
        else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
        {
                sector = FLASH_SECTOR_5;
        }
        else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
        {
                sector = FLASH_SECTOR_6;
        }
        else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
        {
                sector = FLASH_SECTOR_7;
        }
        else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
        {
                sector = FLASH_SECTOR_8;
        }
        else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
        {
                sector = FLASH_SECTOR_9;
        }
        else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
        {
                sector = FLASH_SECTOR_10;
        }
        else        /*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
        {
                sector = FLASH_SECTOR_11;
        }

        return sector;
}

/*
*********************************************************************************************************
*        函 数 名: bsp_ReadCpuFlash
*        功能说明: 读取CPU Flash的内容
*        形    参:_ucpDst : 目标缓冲区
*                       _ulFlashAddr : 起始地址
*                       _ulSize : 数据大小(单位是字节)
*        返 回 值: 0=成功,1=失败
*********************************************************************************************************
*/
uint8_t bsp_ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize)
{
        uint32_t i;

        /* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
        if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
        {
                return 1;
        }

        /* 长度为0时不继续操作,否则起始地址为奇地址会出错 */
        if (_ulSize == 0)
        {
                return 1;
        }

        for (i = 0; i < _ulSize; i++)
        {
                *_ucpDst++ = *(uint8_t *)_ulFlashAddr++;
        }

        return 0;
}

/*
*********************************************************************************************************
*        函 数 名: bsp_CmpCpuFlash
*        功能说明: 比较Flash指定地址的数据.
*        形    参: _ulFlashAddr : Flash地址
*                       _ucpBuf : 数据缓冲区
*                       _ulSize : 数据大小(单位是字节)
*        返 回 值:
*                        FLASH_IS_EQU                0   Flash内容和待写入的数据相等,不需要擦除和写操作
*                        FLASH_REQ_WRITE                1        Flash不需要擦除,直接写
*                        FLASH_REQ_ERASE                2        Flash需要先擦除,再写
*                        FLASH_PARAM_ERR                3        函数参数错误
*********************************************************************************************************
*/
uint8_t bsp_CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize)
{
        uint32_t i;
        uint8_t ucIsEqu;        /* 相等标志 */
        uint8_t ucByte;

        /* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
        if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
        {
                return FLASH_PARAM_ERR;                /* 函数参数错误 */
        }

        /* 长度为0时返回正确 */
        if (_ulSize == 0)
        {
                return FLASH_IS_EQU;                /* Flash内容和待写入的数据相等 */
        }

        ucIsEqu = 1;                        /* 先假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为 0 */
        for (i = 0; i < _ulSize; i++)
        {
                ucByte = *(uint8_t *)_ulFlashAddr;

                if (ucByte != *_ucpBuf)
                {
                        if (ucByte != 0xFF)
                        {
                                return FLASH_REQ_ERASE;                /* 需要擦除后再写 */
                        }
                        else
                        {
                                ucIsEqu = 0;        /* 不相等,需要写 */
                        }
                }

                _ulFlashAddr++;
                _ucpBuf++;
        }

        if (ucIsEqu == 1)
        {
                return FLASH_IS_EQU;        /* Flash内容和待写入的数据相等,不需要擦除和写操作 */
        }
        else
        {
                return FLASH_REQ_WRITE;        /* Flash不需要擦除,直接写 */
        }
}

/*
*********************************************************************************************************
*        函 数 名: bsp_EraseCpuFlash
*        功能说明: 擦除CPU FLASH一个扇区 (128KB)
*        形    参: _ulFlashAddr : Flash地址
*        返 回 值: 0 成功, 1 失败
*                          HAL_OK       = 0x00,
*                          HAL_ERROR    = 0x01,
*                          HAL_BUSY   = 0x02,
*                          HAL_TIMEOUT= 0x03
*
*********************************************************************************************************
*/
uint8_t bsp_EraseCpuFlash(uint32_t _ulFlashAddr)
{
        uint32_t FirstSector = 0, NbOfSectors = 0;
        FLASH_EraseInitTypeDef EraseInitStruct;
        uint32_t SECTORError = 0;
        uint8_t re;

        /* 解锁 */
        HAL_FLASH_Unlock();
       
        /* 获取此地址所在的扇区 */
        FirstSector = bsp_GetSector(_ulFlashAddr);
       
        /* 固定1个扇区 */
        NbOfSectors = 1;       

        /* 擦除扇区配置 */
        EraseInitStruct.TypeErase   = FLASH_TYPEERASE_SECTORS;
        EraseInitStruct.VoltageRange= FLASH_VOLTAGE_RANGE_3;
       
        EraseInitStruct.Banks         = FLASH_BANK_1;

        EraseInitStruct.Sector      = FirstSector;
        EraseInitStruct.NbSectors   = NbOfSectors;
       
        /* 扇区擦除 */       
        re = HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError);
       
        /* 擦除完毕后,上锁 */
        HAL_FLASH_Lock();       
       
        return re;
}

/*
*********************************************************************************************************
*        函 数 名: bsp_WriteCpuFlash
*        功能说明: 写数据到CPU 内部Flash。
*        形    参: _ulFlashAddr : Flash地址
*                       _ucpSrc : 数据缓冲区
*                       _ulSize : 数据大小(单位是字节)
*        返 回 值: 0-成功,1-数据长度或地址溢出,2-写Flash出错(估计Flash寿命到)
*********************************************************************************************************
*/
uint8_t bsp_WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize)
{
        uint32_t i;
        uint8_t ucRet;

        /* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
        if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
        {
                return 1;
        }

        /* 长度为0时不继续操作*/
        if (_ulSize == 0)
        {
                return 0;
        }

        ucRet = bsp_CmpCpuFlash(_ulFlashAddr, _ucpSrc, _ulSize);

        if (ucRet == FLASH_IS_EQU)
        {
                return 0;
        }

        __set_PRIMASK(1);                /* 关中断 */


        /* 需要擦除 */
        if (ucRet == FLASH_REQ_ERASE)
        {
                bsp_EraseCpuFlash(_ulFlashAddr);
        }

        /* FLASH 解锁 */
        HAL_FLASH_Unlock();
       
        /* 按字节模式编程(为提高效率,可以按字编程,一次写入4字节) */
        for (i = 0; i < _ulSize; i++)
        {
                HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, _ulFlashAddr++, *_ucpSrc++);
        }

        /* Flash 加锁,禁止写Flash控制寄存器 */
        HAL_FLASH_Lock();

        __set_PRIMASK(0);                /* 开中断 */

        return 0;
}

/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/

页: [1]
查看完整版本: F407 写FLASH SECTOR 第1个字节不成功