--- 验证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)