• 欢迎大家分享资料!前往留言板评论即可!

均衡擦写spiflash,数据掉电后不丢失.

合宙 模组资料网 2年前 (2021-05-15) 379次浏览 0个评论 扫描二维码

线性均衡擦写spiflash,掉电后,能够找到上次的地址,接着读写。

— 验证spi flash驱动接口 目前该驱动兼容w25q32 bh25q32
require“spiFlash”
require “pm”
require“utils”

pm.wake(“testSpiFlash”)

local flashlist = {
    [0xEF15] = ‘w25q32’,
    [0xEF16] = ‘w25q64’,
    [0xEF17] = ‘w25q128’,
    [0x6815] = ‘bh25q32’,
}
function HexToChar(bChar)
    if((bChar>=0x30)and(bChar<=0x39)) then
            bChar=bChar 0x30;
    else if((bChar>=0x41)and(bChar<=0x46)) then–// Capital    
                    bChar=bChar 0x37;             
        else if((bChar>=0x61)and(bChar<=0x66)) then –//littlecase             
                    bChar=bChar 0x57;            
                else             
                    bChar = 0xff;             
                end
        end
    end
    return bChar;
end
— spiflash 大小 256*16*4*1024 字节
FLASH_COUNT=10*16 –数量*4K
SPI_MAXSIZE=FLASH_COUNT*16
SPI_COUNT=0
ReadIndex=0
ReadIndex_S=1
WriteIndex=0
WriteIndex_S=1
spi_flash = spiFlash.setup(spi.SPI_1, pio.P0_10)

–把数据格式化为16进制 高位补0 ,2字节    写入spiflash指定地址
function write_Index(addr,data)
    local strhex=string.format(“%04X”,data)
    spi_flash:write(addr,string.fromHex(strhex))
    local readindexdata= spi_flash:read(addr, 2)
    local readdatahex=string.toHex(readindexdata)
    if(readdatahex==strhex) then
      
    else
        spi_flash:write(addr,string.fromHex(strhex))
        readindexdata= spi_flash:read(addr, 2)
         readdatahex=string.toHex(readindexdata)
         log.error(“index err”,readdatahex,addr,data)

    end
end

function SPI_READ()
   local indexaddr=0
    if (ReadIndex==WriteIndex) then —  //空队列,直接返回
        log.info(“empty”)
    else
       — local readSPIdata_pre= spi_flash:read(ReadIndex*256, 10)
       — local readSPIdata_pre_hex=string.toHex(readSPIdata_pre)
    
        –if( (readSPIdata_pre_hex~=’30303030303030303030′) and (readSPIdata_pre_hex~=’FFFFFFFFFFFFFFFFFFFF’) ) then   –预读 不等于空 或者 0
            readSPIdata= spi_flash:read(ReadIndex*256, 60)
           — STRLENGTH=string.len(readSPIdata)
           — log.info(“leng:”,STRLENGTH)
           spi_flash:write(ReadIndex*256,“000000000000”–读取完毕后清零

          — log.debug(“W”,WriteIndex)
          
       — else  –队列非空  但是预读不准确,强制清零
           — log.error(“RF:”,ReadIndex)
           — log.info(“W”,WriteIndex)
            –log.error(“RFF:”,readSPIdata_pre_hex)
          
          — spi_flash:write(ReadIndex*256,”000000000000″)
       — end

        ReadIndex= (ReadIndex+ 1) %SPI_MAXSIZE;
        if(ReadIndex%16==0) then
            if(ReadIndex==0) then    –第一次读地址
                spi_flash:erase4K((FLASH_COUNT1)*4096)
            else  —   >=16
             spi_flash:erase4K((ReadIndex1)*256)
            end
             log.error(“erase4K”,ReadIndex)
        end
         if(ReadIndex%2048==0) then
            spi_flash:erase4K((FLASH_COUNT+6)*4*1024)
            spi_flash:erase4K((FLASH_COUNT+7)*4*1024)
            spi_flash:erase4K((FLASH_COUNT+8)*4*1024)
         end  –索引写完了一遍
            indexaddr=ReadIndex%2048
            write_Index(indexaddr*2+(FLASH_COUNT+6)*4096,ReadIndex)
            write_Index(indexaddr*2+(FLASH_COUNT+7)*4096,ReadIndex)
            write_Index(indexaddr*2+(FLASH_COUNT+8)*4096,ReadIndex)

        –strhex_index=string.format(“%04X”,ReadIndex)
       — spi_flash:write(ReadIndex*2+(FLASH_COUNT+4)*4096,string.fromHex(strhex_index))
        log.debug(“+”,readSPIdata)
        log.debug(“R”,ReadIndex)
    end

   — return readSPIdata

end

–判断spiflash 是否有剩余空间   返回 0-没有空间    1-有空间
function SPI_Free()
    local result=0
    –注意: WriteIndex+16不可以大于65535  否则为nil 报错!!!!!!
    if((WriteIndex+16)% SPI_MAXSIZE==ReadIndex)   then — //队列已满时,不执行入队操作
        result=0
    else  –队列空
        result=1
    end
    return result
end

function SPI_WRITE(SPI_user_data)
local result=0

         writeDataLength=string.len(SPI_user_data)
        local readSPIdata_pre= spi_flash:read((WriteIndex)*256, 10)
        local readSPIdata_pre_hex=string.toHex(readSPIdata_pre)
        local indexaddr=0
        if(readSPIdata_pre_hex==‘FFFFFFFFFFFFFFFFFFFF’) then  — 预写地址数据正确
            spi_flash:write(WriteIndex*256,SPI_user_data)
            DATA01= spi_flash:read(WriteIndex*256, writeDataLength)
            if( DATA01==SPI_user_data) then  –写入正确
                result=1
            else   –写入错误
                result=0
            end

        else
            result=0
        end

        WriteIndex= (WriteIndex+1) % SPI_MAXSIZE; –//尾部元素指向下一个空间位置,取模运算保证了索引不越界(余数一定小于除数)
        if(WriteIndex%2048==0) then
            spi_flash:erase4K((FLASH_COUNT+3)*4*1024)
             spi_flash:erase4K((FLASH_COUNT+4)*4*1024)
             spi_flash:erase4K((FLASH_COUNT+5)*4*1024)
           

        end  –索引写完了一遍
             indexaddr=WriteIndex%2048
             write_Index(indexaddr*2+(FLASH_COUNT+3)*4096,WriteIndex)
            write_Index(indexaddr*2+(FLASH_COUNT+4)*4096,WriteIndex)
            write_Index(indexaddr*2+(FLASH_COUNT+5)*4096,WriteIndex)
        
        –local strhex=string.format(“%04X”,WriteIndex)
        –spi_flash:write(WriteIndex*2+(FLASH_COUNT+3)*4096,string.fromHex(strhex))   –记录下一个地址索引
        log.debug(“W”,WriteIndex)
   

    return result
end
–带比较写入spiflash   返回 0-满了    1-写入成功
function spiWriteDataCheck(userdata)
    local result=0
    if(SPI_Free()==1) then  –有空间
        result=SPI_WRITE(userdata)
        if(result==0) then  –写入错误 再写一遍
             if(SPI_Free()==1) then
                 SPI_WRITE(teststr)
             else
                result=0          
            end
        end
    else
        result=0
    end 
    return result
end
— 从spiflash读qu size个字节数据 转为16进制
function spiHexToDec(address,size)
    local hexdata=spi_flash:read(address,size)
    local readdatahex=string.toHex(hexdata)
    return readdatahex
end
–二分查找索引
function findIndex(MAXINDEX,baseAddress1,baseAddress2,baseAddress3,W_R_index)
    local miniindex=0
    local maxindex=MAXINDEX
    local read_flags1=‘0000’
    local read_flags2=‘0000’
    local read_flags3=‘0000’
    local offsetAddress=0
    local erFenCount=11  –分11段查找
   
    while(erFenCount>0) do
        offsetAddress=(maxindexminiindex)/2+miniindex  — 重新确定偏移量 对于基地址的绝对位置
        read_flags1=spiHexToDec(baseAddress1+offsetAddress,2)
        read_flags2=spiHexToDec(baseAddress2+offsetAddress,2)
        read_flags3=spiHexToDec(baseAddress3+offsetAddress,2)
        if((read_flags1==read_flags2) and (read_flags2==read_flags3) and (read_flags1==‘FFFF’)) then  –全部相等
                maxindex=offsetAddress
        else   –取后半部分
            miniindex=offsetAddress
        end

        erFenCount=erFenCount1
        sys.wait(2)
    end
        if((maxindexminiindex)==2) then  log.info(‘%%%%%’,miniindex,maxindex) end

        readflags1=spi_flash:read(baseAddress1+miniindex,2)
        readflags2=spi_flash:read(baseAddress2+miniindex,2)
        readflags3=spi_flash:read(baseAddress3+miniindex,2)
        readIndex_fromhex1=string.toHex(readflags1)
        readIndex_fromhex2=string.toHex(readflags2)
        readIndex_fromhex3=string.toHex(readflags3)
        readIndex1=tonumber(readIndex_fromhex1,16–十进制数
        readIndex2=tonumber(readIndex_fromhex2,16–十进制数
        readIndex3=tonumber(readIndex_fromhex3,16–十进制数
        if((readIndex_fromhex1==readIndex_fromhex2)   and (readIndex_fromhex1~=‘FFFF’) ) then
           — readIndex1=tonumber(readIndex_fromhex1,16)  –十进制数
            if(W_R_index==1) then   –写索引            
                WriteIndex=readIndex1
                log.error(“W index1”,readIndex_fromhex1)
                log.error(“writeIndex1”,readIndex1)
                spi_flash:erase4K((FLASH_COUNT+5)*4*1024)                  
                findresult=1
            else    –读索引
                ReadIndex=readIndex1
                log.error(“R index1”,readIndex_fromhex1)
                log.error(“readIndex1”,readIndex1)
                spi_flash:erase4K((FLASH_COUNT+8)*4*1024)
                findresult=1
            end
        else
            if((readIndex_fromhex2==readIndex_fromhex3)   and (readIndex_fromhex2~=‘FFFF’) ) then
               — readIndex2=tonumber(readIndex_fromhex2,16)  –十进制数
                if(W_R_index==1) then   –写索引            
                    WriteIndex=readIndex2
                    log.error(“W index2”,readIndex_fromhex2)
                    log.error(“writeIndex2”,readIndex2)
                    spi_flash:erase4K((FLASH_COUNT+4)*4*1024)                  
                    findresult=1
                else    –读索引
                    ReadIndex=readIndex2
                    log.error(“R index2”,readIndex_fromhex2)
                    log.error(“readIndex2”,readIndex2)
                    spi_flash:erase4K((FLASH_COUNT+7)*4*1024)
                    findresult=1
                end
            else
                if((readIndex_fromhex1==readIndex_fromhex3)   and (readIndex_fromhex1~=‘FFFF’) ) then
                   — readIndex3=tonumber(readIndex_fromhex3,16)  –十进制数
                    if(W_R_index==1) then   –写索引            
                        WriteIndex=readIndex3
                        log.error(“W index3”,readIndex_fromhex3)
                        log.error(“writeIndex3”,readIndex3)
                        spi_flash:erase4K((FLASH_COUNT+4)*4*1024)
                        findresult=1
                    else    –读索引
                        ReadIndex=readIndex3
                        log.error(“R index3”,readIndex_fromhex3)
                        log.error(“readIndex3”,readIndex3)
                        spi_flash:erase4K((FLASH_COUNT+7)*4*1024)
                   
                        findresult=1
                    end
                else
                    if(miniindex>=2) then
                        readflags1=spi_flash:read(baseAddress1+miniindex2,2)
                        readflags2=spi_flash:read(baseAddress2+miniindex2,2)
                        readflags3=spi_flash:read(baseAddress3+miniindex2,2)
                        readIndex_fromhex1=string.toHex(readflags1)
                        readIndex_fromhex2=string.toHex(readflags2)
                        readIndex_fromhex3=string.toHex(readflags3)
                        if((readIndex_fromhex1==readIndex_fromhex2) and (readIndex_fromhex2==readIndex_fromhex3) and (readIndex_fromhex1~=‘FFFF’) ) then
                            –这是最后的救命稻草了
                            readIndex1=tonumber(readIndex_fromhex1,16–十进制数
                            if(W_R_index==1) then   –写索引            
                                WriteIndex=readIndex1
                                log.error(“W index_pre”,readIndex_fromhex1)
                                log.error(“writeIndex_pre”,readIndex1)                 
                                findresult=1
                            else    –读索引
                                ReadIndex=readIndex1
                                log.error(“R index_pre”,readIndex_fromhex1)
                                log.error(“readIndex_pre”,readIndex1)
                                findresult=1
                            end 

                        else — 前一个也不对  死定了
                            findresult=0
                        end
                    else –接收死刑吧,确实找不到索引了  重新初始化。
                        findresult=0
                    end
                end
            end
        end
        –出现异常情况,理论上不可能为nil 
        if((readIndex1==nil) or (readIndex2==nil) or (readIndex3==nil) ) then  log.error(“nil  err  err”)  findresult=0  end
end
–;预读初始化
flash_Inint_Flags=“17513167902”
function SPI_ININT_PRE()
    ReadIndex=0
    WriteIndex=0
    spi_flash:erase4K((FLASH_COUNT+1)*4*1024–清除必须操作  必须清楚后才能写数据
    local writeOK_flag= spi_flash:read((FLASH_COUNT+2)*4*1024,11–是否第一次写入数据
    local next_step=0
    print(“writeOK_flag”,writeOK_flag)
    if(writeOK_flag==flash_Inint_Flags) then
        next_step=1
    else
        spi_flash:erase4K((FLASH_COUNT+2)*4*1024)
        print(“writeOK_flag14”, spi_flash:write((FLASH_COUNT+2)*4*1024,flash_Inint_Flags))
        next_step=2
    end
    print(“next_step=”,next_step)
    local count=0
    local readindex_start=0
    local writeindex_start=0
    local readIndex_flag=0
    if(next_step==1) then
               if(findIndex(4096,(FLASH_COUNT+3)*4096,(FLASH_COUNT+4)*4096,(FLASH_COUNT+5)*4096,1)==0) then –没有找到上次的 写索引 全部清除
                        next_step=2
               end
               print(“========================”)
               if(findIndex(4096,(FLASH_COUNT+6)*4096,(FLASH_COUNT+7)*4096,(FLASH_COUNT+8)*4096,0)==0) then –没有找到上次的 读索引 全部清除
                         next_step=2
                end
                if(next_step==1) then
                    log.error(“indexR_W1”,ReadIndex,WriteIndex)
                end
             count=0
             readIndex_flag=0
    end
   
  
     count=0
    if(next_step==2) then
        log.error(“indexR_W2”,ReadIndex,WriteIndex)
        print(‘spi flash erase……….’)
        while(count<(FLASH_COUNT/16)) do             
            spi_flash:erase64K(count*1024*4*16) count=count+1  sys.wait(1)    –清除数据区
        end
        –清除读写索引区
         spi_flash:erase4K((FLASH_COUNT+3)*4*1024)
         spi_flash:erase4K((FLASH_COUNT+4)*4*1024)
         spi_flash:erase4K((FLASH_COUNT+5)*4*1024)
         spi_flash:erase4K((FLASH_COUNT+6)*4*1024)
         spi_flash:erase4K((FLASH_COUNT+7)*4*1024)
         spi_flash:erase4K((FLASH_COUNT+8)*4*1024)
         –第一次读写flash 索引置零
        ReadIndex=0
        WriteIndex=0
        –把下一次预读写的索引写入spiflash
        write_Index(WriteIndex*2+(FLASH_COUNT+3)*4096,WriteIndex)
        write_Index(WriteIndex*2+(FLASH_COUNT+4)*4096,WriteIndex)
        write_Index(WriteIndex*2+(FLASH_COUNT+5)*4096,WriteIndex)

        write_Index(ReadIndex*2+(FLASH_COUNT+6)*4096,ReadIndex)
        write_Index(ReadIndex*2+(FLASH_COUNT+7)*4096,ReadIndex)
        write_Index(ReadIndex*2+(FLASH_COUNT+8)*4096,ReadIndex)
        print(‘spi flash eraseinit OK’)
        sys.wait(1000)
    end
end
SPI_ININT_OK=0
SPI_ININT_PRE()
SPI_ININT_OK=2

yesycount=1
xinhaoliang=0
function writespiflashtest()
    syserrrcode=0
    while(true) do
       — if(xinhaoliang==0) then
            if(SPI_ININT_OK==2) then
                teststr=string.format(“test adcde:ftydtyfdfdfgurgjfdhguirhgujgh#>:      %d”, yesycount)
                if(spiWriteDataCheck(teststr)==1) then  –写入正确
                    yesycount=yesycount+1
                else –满了
                    print(“full”,WriteIndex)
                end                                      
            end
        sys.wait(5)
    end
end
sys.taskInit(writespiflashtest)
    while true do
        if(SPI_ININT_OK==2) then            
      SPI_READ()
            end
        sys.wait(15)
    end
end)


喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址