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

线性均衡擦写spiflash,掉电后,能够找到上次的地址,接着读写。--- 验证spi flash驱动接口 目前该驱动兼容w25q32 bh25q32require"spiFlash"require "pm"require"utils" pm.wake("testSpiFlash"...

线性均衡擦写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_COUNT-1)*4096)
            else  --   >=16
             spi_flash:erase4K((ReadIndex-1)*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=(maxindex-miniindex)/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=erFenCount-1
        sys.wait(2)
    end
        if((maxindex-miniindex)==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+miniindex-2,2)
                        readflags2=spi_flash:read(baseAddress2+miniindex-2,2)
                        readflags3=spi_flash:read(baseAddress3+miniindex-2,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)




  • 发表于 2019-04-27 13:17
  • 阅读 ( 1139 )

你可能感兴趣的文章

相关问题

1 条评论

请先 登录 后评论
不写代码的码农
徐南

电子码农一枚

1 篇文章

作家榜 »

  1. 技术销售Delectate 43 文章
  2. 陈夏 24 文章
  3. 国梁 24 文章
  4. miuser 21 文章
  5. 刘晨旭 20 文章
  6. 朱天华 19 文章
  7. 金艺 19 文章
  8. 杨奉武 18 文章