FLASH 写数据函数

#define W25Q64_PAGE_SIZE          FLASH_PAGE_SIZE                        // 一个page 256 (Byte) 
#define W25Q64_SECTOR_SIZE      (W25Q64_PAGE_SIZE*16)    // 16个page组成一个sector: PAGE * 16 = 4K (Byte) //擦除的最小操作单元
#define W25Q64_BLOCK_SIZE       (W25Q64_SECTOR_SIZE*16)    // 16个sector组成一个block: SECTOR * 16 = 64K (Byte)
#define W25Q64_CHIP_SIZE        (W25Q64_BLOCK_SIZE*128)    // 128个block组成整个flash空间: BLOCK * 128 = 8M

/**************************************************************
 *功能:写数据到外部flash
 *输入:u32Address要写的地址,
             pBuf要写入的数据,
             u32NbrToWrite要写的字节数
 *输出:
 *条件:要写入的数据不能为空
 *返回:成功:写入的字节数 
             失败:0 
 注意: 按一页写SPI flash
***************************************************************/
static T_U32 _SPIFlash_Write(T_U32 u32Address, T_U8 *pBuf, T_U32 u32NbrToWrite) 
{    
    T_U32 iNumByteToWrite = u32NbrToWrite, u32CountByte=0;
    T_U32 u32SectorPos = 0;
    T_U32 u32PagePos = 0;
    T_U32 u32PageOff = 0;
    T_U32 u32PageRemain = 0;
    T_U32 u32PageAddr = 0;
    T_U32 i = 0, j = 0;   

    T_S8 s8Buf[W25Q64_PAGE_SIZE] = {0};
    
    ASSERT_EQUAL_RETVAL(pBuf, T_NULL, 0);

    while(1)
    {
        /* 计算一些地址和关键值 */  
        // 一个page:256byte
        // 一个 sector:4kByte  是擦除的最小单元
        u32SectorPos = u32Address & (~(W25Q64_SECTOR_SIZE - 1));    //Sector地址 
        u32PagePos = u32Address & (~(W25Q64_PAGE_SIZE - 1));        //page地址 //page的地址  取256的整数倍
        u32PageOff = u32Address & (W25Q64_PAGE_SIZE - 1);            //在page内的偏移 取2048的余数
        u32PageRemain = W25Q64_PAGE_SIZE - u32PageOff;                 //page剩余空间大小 
        if(iNumByteToWrite <= u32PageRemain) 
        {
            u32PageRemain = iNumByteToWrite;                
        }
        
        /* 读出对应扇区全部数据存到缓冲区*/
        _SPIFlash_SectorErase((T_U32)FLASH_CACHE_START);  //擦除1个扇区4k
        for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
        {
            memset(s8Buf, 0, W25Q64_PAGE_SIZE);
            _SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
            _SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
        }
        _SPIFlash_SectorErase(u32SectorPos);   //擦除要写数据区4K
            
        /* 从缓冲区读出数据修改对应位置后写入对应扇区 */
        for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
        {
            u32PageAddr = u32SectorPos + i*W25Q64_PAGE_SIZE;
            
            memset(s8Buf, 0, W25Q64_PAGE_SIZE);
            _SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);

            if(u32PageAddr == u32PagePos)
            { 
                u32CountByte += u32PageRemain;
                for(j=0; j<u32PageRemain; j++) 
                {  //复制
                    s8Buf[j+u32PageOff] = pBuf[j];  
                }

                if(iNumByteToWrite != u32PageRemain)
                {
                    u32PagePos += W25Q64_PAGE_SIZE;
                    u32PageOff = 0;                             //偏移位置为0 
                    pBuf += u32PageRemain;                        //指针偏移
                    u32Address += u32PageRemain;                //写地址偏移 
                    iNumByteToWrite -= u32PageRemain;            //字节数递减
                    if(iNumByteToWrite > W25Q64_PAGE_SIZE) 
                    {
                        u32PageRemain = W25Q64_PAGE_SIZE;        //下一个扇区还是写不完
                    }else
                    {
                        u32PageRemain = iNumByteToWrite;        //下一个扇区可以写完了
                    }
                }
            
            }
            _SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
        }
        
        //跨扇区写
        while(u32CountByte != u32NbrToWrite)
        {
             u32SectorPos = u32SectorPos+ W25Q64_SECTOR_SIZE;  //地址偏移到下一个扇区
            /* 读出对应扇区全部数据存到缓冲区*/
            _SPIFlash_SectorErase((T_U32)FLASH_CACHE_START);  //擦除1个扇区4k
            
            for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
            {
                memset(s8Buf, 0, W25Q64_PAGE_SIZE);
                _SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
                _SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);
            }
            
            //擦掉下一个扇区4k 
            _SPIFlash_SectorErase(u32SectorPos);  

            for(i=0; i<(W25Q64_SECTOR_SIZE/W25Q64_PAGE_SIZE); i++)
            {
                memset(s8Buf, 0, W25Q64_PAGE_SIZE);
                _SPIFlash_ReadBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, FLASH_CACHE_START+i*W25Q64_PAGE_SIZE);

                u32PageAddr = u32SectorPos + i*W25Q64_PAGE_SIZE;
                
                if(u32PageAddr == u32PagePos)
                {
                    u32CountByte += u32PageRemain;
                    for(j=0; j<u32PageRemain; j++) 
                    {  //复制
                        s8Buf[j+u32PageOff] = pBuf[j];  
                    }

                    if(iNumByteToWrite != u32PageRemain)
                    {
                        u32PagePos += W25Q64_PAGE_SIZE;
                        u32PageOff = 0;                             //偏移位置为0 
                        pBuf += u32PageRemain;                        //指针偏移
                        u32Address += u32PageRemain;                //写地址偏移 
                        iNumByteToWrite -= u32PageRemain;            //字节数递减
                        if(iNumByteToWrite > W25Q64_PAGE_SIZE) 
                        {
                            u32PageRemain = W25Q64_PAGE_SIZE;        //下一个扇区还是写不完
                        }else
                        {
                            u32PageRemain = iNumByteToWrite;        //下一个扇区可以写完了
                        }
                    }
                }
                 _SPIFlash_WriteBuf((T_S8*)&s8Buf[0], W25Q64_PAGE_SIZE, u32SectorPos+i*W25Q64_PAGE_SIZE);
            }
        }
        
        if(u32CountByte == u32NbrToWrite)   //
        {
            break;
        }
    }

    return u32NbrToWrite; 
}
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
stm32flash是一个用于在STM32单片机上进行固件编程的开源工具,它提供了一组读函数,用于操纵STM32内部的闪存存储器。 stm32flash函数包括以下几个主要函数: 1. `flash_identify()` 函数用于识别目标单片机的型号和闪存大小,它会发送读标识命令到目标单片机,并解析返回的信息。通过该函数,我们可以获取目标单片机的型号和闪存容量,以便后续的操作。 2. `flash_emit_bootloader()` 函数用于向目标单片机的闪存中编程bootloader程序。该函数会将bootloader的二进制文件读取到内存中,并通过发送编程命令将其入目标单片机的闪存。 3. `flash_emit_firmware()` 函数用于向目标单片机的闪存中编程应用程序固件。该函数会将应用程序固件的二进制文件读取到内存中,并通过发送编程命令将其入目标单片机的闪存。 4. `flash_read()` 函数用于从目标单片机的闪存中读取数据。该函数会发送读取命令到目标单片机,并接收返回的数据。我们可以指定要读取的地址和数据长度,以及接收数据的缓冲区。通过该函数,我们可以获取目标单片机闪存中指定地址的数据。 5. `flash_write()` 函数用于向目标单片机的闪存中数据。该函数会发送入命令和要入的数据到目标单片机。我们可以指定要入的地址和数据长度,以及要入的数据。通过该函数,我们可以往目标单片机闪存中指定地址数据。 这些函数都是通过与目标单片机进行通信,发送特定的命令来实现相应的功能。通过stm32flash函数,我们可以对STM32单片机的闪存进行编程和读取操作,实现固件的更新和数据的读

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值