| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- --- 模块功能:W25Q32/BH25Q32驱动代码
- -- @module SPIFlash
- -- @author openLuat
- -- @license MIT
- -- @copyright openLuat
- -- @release 2018.8.26
- module(..., package.seeall)
- local READ_ID = 0x90
- local WRITE_ENABLE = 0x06
- local READ_STATUS = 0x05
- local FLASH_READ = 0x03
- local ERASE_SECTOR_4K = 0x20
- local BLOCK_ERASE_64K = 0xD8
- local ERASE_CHIP = 0x60
- local PAGE_PROGRAM = 0x02
- local gpio_set = pio.pin.setval
- local mt = { __index = {} }
- local function address24bit(addr)
- return pack.pack('>I', addr):sub(2, 4)
- end
- --- 创建spi flash驱动实例
- -- @param id spi id
- -- @param timeout 等待flash busy状态解除的最长超时时间,默认60000ms
- -- @return 返回spi flash驱动实例
- -- @usage w25q32 = spiFlash.setup(spi.SPI_1, pio.P0_10)
- function setup(id, timeout)
- if not spi.setup(id, 0, 0, 8, 13000000, 1) then
- log.error('BH25Q32.setup', 'spi setup failed')
- end
- local o = {
- id = id,
- timeout = timeout or 60000, -- ms
- pagesize = 256,
- }
- setmetatable(o, mt)
- return o
- end
- --- 释放spi flash驱动实例
- -- @param
- -- @return
- -- @usage w25q32:close()
- function mt.__index:close()
- spi.close(self.id)
- end
- --- 读取flash id
- -- @return manufactureID, deviceID 返回两个参数 厂商id,设备id
- function mt.__index:readFlashID()
- log.info("send",pack.pack('bAA', READ_ID, address24bit(0), '\255\255'):toHex())
- local r = spi.send_recv(self.id, pack.pack('bAA', READ_ID, address24bit(0), '\255\255'))
- if r then
- return string.byte(r, 5, 6)
- else
- return false
- end
- end
- --- 读取flash状态寄存器 STATUS S0-S7
- -- @return 返回flash状态寄存器bit0-bit7的值
- function mt.__index:readStatus()
- local r = spi.send_recv(self.id, string.char(READ_STATUS, 0xff))
- return r and string.byte(r, 2)
- end
- --- 查询flash是否处于busy状态
- -- @return true - 繁忙 false - 空闲
- function mt.__index:busy()
- return self:readStatus() % 2 == 1
- end
- --- 等待flash空闲
- -- @param timeout 超时时间 单位ms
- --
- function mt.__index:waitNotBusy(timeout)
- local status
- local step = 50
- local count = 0
- timeout = timeout or self.timeout
- while true do
- if not self:busy() then break end
- sys.wait(step)
- count = count + 1
- if count > timeout / step then
- log.error('BH25Q32.waitNotBusy', 'timeout')
- return false
- end
- end
- return true
- end
- --- 向spi flash 传输数据
- -- @param send_data 要发送的数据
- -- @param read_size 可选参数,需要读取的数据长度,如果是写指令,不填参数或者填0
- -- @return nil - 失败 true - 写指令发送成功 string - 返回读取到的数据
- function mt.__index:transfer(send_data, read_size)
- if not self:waitNotBusy() then return end
- if type(send_data) == 'number' then send_data = string.char(send_data) end
- if not read_size then read_size = 0 end
- if read_size == 0 then
- spi.send_recv(self.id, string.char(WRITE_ENABLE))
- end
- local r = spi.send_recv(self.id, send_data .. string.rep('\255', read_size))
- if read_size > 0 then
- return string.sub(r, send_data:len() + 1, -1)
- end
- return true
- end
- --- 读取spi flash 指定地址的数据
- -- @param addr flash地址
- -- @param len 长度
- -- @return nil - 读取失败 string - 读取到的数据
- -- @usage w25q32 = spiFlash.setup(spi.SPI_1, pio.P0_10); w25q32:read(0x1000, 6);
- function mt.__index:read(addr, len)
- return self:transfer(string.char(FLASH_READ) .. address24bit(addr), len)
- end
- --- 按擦除sector(4K)的方式擦除指定地址的数据
- -- @param addr 擦除的起始地址,会自动做4K对齐
- -- @return true - 成功 false - 失败
- function mt.__index:erase4K(addr)
- return self:transfer(string.char(ERASE_SECTOR_4K) .. address24bit(addr - addr % 0x1000)) and self:waitNotBusy()
- end
- --- 按擦除block 64K的方式擦除指定地址的数据
- -- @param addr 擦除的起始地址,会自动做64K对齐
- -- @return true - 成功 false - 失败
- function mt.__index:erase64K(addr)
- return self:transfer(string.char(BLOCK_ERASE_64K) .. address24bit(addr - addr % 0x10000)) and self:waitNotBusy()
- end
- --- 擦除整个flash芯片的数据
- -- @param 无
- -- @return true - 成功 false - 失败
- function mt.__index:eraseChip()
- return self:transfer(ERASE_CHIP) and self:waitNotBusy()
- end
- --- 向spi flash指定地址写入数据
- -- @param address 写入的地址
- -- @param data 数据
- -- @return number - 成功写入的数据长度
- function mt.__index:write(address, data)
- local ending_address = address + data:len()
- local wrote_len = 0
- local bytes_to_write = 0
- while address < ending_address do
- bytes_to_write = self.pagesize - (address % self.pagesize)
- if wrote_len + bytes_to_write > data:len() then bytes_to_write = data:len() - wrote_len end
- if not self:transfer(pack.pack('bAA', PAGE_PROGRAM, address24bit(address), data:sub(wrote_len + 1, wrote_len + bytes_to_write))) then
- break
- end
- address = address + bytes_to_write
- wrote_len = wrote_len + bytes_to_write
- end
- return wrote_len
- end
|