spiFlash.lua 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. --- 模块功能:W25Q32/BH25Q32驱动代码
  2. -- @module SPIFlash
  3. -- @author openLuat
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2018.8.26
  7. module(..., package.seeall)
  8. local READ_ID = 0x90
  9. local WRITE_ENABLE = 0x06
  10. local READ_STATUS = 0x05
  11. local FLASH_READ = 0x03
  12. local ERASE_SECTOR_4K = 0x20
  13. local BLOCK_ERASE_64K = 0xD8
  14. local ERASE_CHIP = 0x60
  15. local PAGE_PROGRAM = 0x02
  16. local gpio_set = pio.pin.setval
  17. local mt = { __index = {} }
  18. local function address24bit(addr)
  19. return pack.pack('>I', addr):sub(2, 4)
  20. end
  21. --- 创建spi flash驱动实例
  22. -- @param id spi id
  23. -- @param timeout 等待flash busy状态解除的最长超时时间,默认60000ms
  24. -- @return 返回spi flash驱动实例
  25. -- @usage w25q32 = spiFlash.setup(spi.SPI_1, pio.P0_10)
  26. function setup(id, timeout)
  27. if not spi.setup(id, 0, 0, 8, 13000000, 1) then
  28. log.error('BH25Q32.setup', 'spi setup failed')
  29. end
  30. local o = {
  31. id = id,
  32. timeout = timeout or 60000, -- ms
  33. pagesize = 256,
  34. }
  35. setmetatable(o, mt)
  36. return o
  37. end
  38. --- 释放spi flash驱动实例
  39. -- @param
  40. -- @return
  41. -- @usage w25q32:close()
  42. function mt.__index:close()
  43. spi.close(self.id)
  44. end
  45. --- 读取flash id
  46. -- @return manufactureID, deviceID 返回两个参数 厂商id,设备id
  47. function mt.__index:readFlashID()
  48. log.info("send",pack.pack('bAA', READ_ID, address24bit(0), '\255\255'):toHex())
  49. local r = spi.send_recv(self.id, pack.pack('bAA', READ_ID, address24bit(0), '\255\255'))
  50. if r then
  51. return string.byte(r, 5, 6)
  52. else
  53. return false
  54. end
  55. end
  56. --- 读取flash状态寄存器 STATUS S0-S7
  57. -- @return 返回flash状态寄存器bit0-bit7的值
  58. function mt.__index:readStatus()
  59. local r = spi.send_recv(self.id, string.char(READ_STATUS, 0xff))
  60. return r and string.byte(r, 2)
  61. end
  62. --- 查询flash是否处于busy状态
  63. -- @return true - 繁忙 false - 空闲
  64. function mt.__index:busy()
  65. return self:readStatus() % 2 == 1
  66. end
  67. --- 等待flash空闲
  68. -- @param timeout 超时时间 单位ms
  69. --
  70. function mt.__index:waitNotBusy(timeout)
  71. local status
  72. local step = 50
  73. local count = 0
  74. timeout = timeout or self.timeout
  75. while true do
  76. if not self:busy() then break end
  77. sys.wait(step)
  78. count = count + 1
  79. if count > timeout / step then
  80. log.error('BH25Q32.waitNotBusy', 'timeout')
  81. return false
  82. end
  83. end
  84. return true
  85. end
  86. --- 向spi flash 传输数据
  87. -- @param send_data 要发送的数据
  88. -- @param read_size 可选参数,需要读取的数据长度,如果是写指令,不填参数或者填0
  89. -- @return nil - 失败 true - 写指令发送成功 string - 返回读取到的数据
  90. function mt.__index:transfer(send_data, read_size)
  91. if not self:waitNotBusy() then return end
  92. if type(send_data) == 'number' then send_data = string.char(send_data) end
  93. if not read_size then read_size = 0 end
  94. if read_size == 0 then
  95. spi.send_recv(self.id, string.char(WRITE_ENABLE))
  96. end
  97. local r = spi.send_recv(self.id, send_data .. string.rep('\255', read_size))
  98. if read_size > 0 then
  99. return string.sub(r, send_data:len() + 1, -1)
  100. end
  101. return true
  102. end
  103. --- 读取spi flash 指定地址的数据
  104. -- @param addr flash地址
  105. -- @param len 长度
  106. -- @return nil - 读取失败 string - 读取到的数据
  107. -- @usage w25q32 = spiFlash.setup(spi.SPI_1, pio.P0_10); w25q32:read(0x1000, 6);
  108. function mt.__index:read(addr, len)
  109. return self:transfer(string.char(FLASH_READ) .. address24bit(addr), len)
  110. end
  111. --- 按擦除sector(4K)的方式擦除指定地址的数据
  112. -- @param addr 擦除的起始地址,会自动做4K对齐
  113. -- @return true - 成功 false - 失败
  114. function mt.__index:erase4K(addr)
  115. return self:transfer(string.char(ERASE_SECTOR_4K) .. address24bit(addr - addr % 0x1000)) and self:waitNotBusy()
  116. end
  117. --- 按擦除block 64K的方式擦除指定地址的数据
  118. -- @param addr 擦除的起始地址,会自动做64K对齐
  119. -- @return true - 成功 false - 失败
  120. function mt.__index:erase64K(addr)
  121. return self:transfer(string.char(BLOCK_ERASE_64K) .. address24bit(addr - addr % 0x10000)) and self:waitNotBusy()
  122. end
  123. --- 擦除整个flash芯片的数据
  124. -- @param 无
  125. -- @return true - 成功 false - 失败
  126. function mt.__index:eraseChip()
  127. return self:transfer(ERASE_CHIP) and self:waitNotBusy()
  128. end
  129. --- 向spi flash指定地址写入数据
  130. -- @param address 写入的地址
  131. -- @param data 数据
  132. -- @return number - 成功写入的数据长度
  133. function mt.__index:write(address, data)
  134. local ending_address = address + data:len()
  135. local wrote_len = 0
  136. local bytes_to_write = 0
  137. while address < ending_address do
  138. bytes_to_write = self.pagesize - (address % self.pagesize)
  139. if wrote_len + bytes_to_write > data:len() then bytes_to_write = data:len() - wrote_len end
  140. if not self:transfer(pack.pack('bAA', PAGE_PROGRAM, address24bit(address), data:sub(wrote_len + 1, wrote_len + bytes_to_write))) then
  141. break
  142. end
  143. address = address + bytes_to_write
  144. wrote_len = wrote_len + bytes_to_write
  145. end
  146. return wrote_len
  147. end