diskio_blkdev.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "diskio_blkdev.h"
  41. /**
  42. * @brief Registered drives array.
  43. * */
  44. static diskio_blkdev_t * m_drives;
  45. /**
  46. * @brief Number of registered drives.
  47. * */
  48. static BYTE m_drives_count;
  49. /**
  50. * @brief Block device handler.
  51. *
  52. * @ref nrf_block_dev_ev_handler
  53. * */
  54. static void block_dev_handler(struct nrf_block_dev_s const * p_blk_dev,
  55. nrf_block_dev_event_t const * p_event)
  56. {
  57. uint8_t drv = (uint8_t)(uint32_t) p_event->p_context;
  58. ASSERT(drv < m_drives_count);
  59. switch (p_event->ev_type)
  60. {
  61. case NRF_BLOCK_DEV_EVT_INIT:
  62. case NRF_BLOCK_DEV_EVT_UNINIT:
  63. case NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE:
  64. case NRF_BLOCK_DEV_EVT_BLK_READ_DONE:
  65. m_drives[drv].last_result = p_event->result;
  66. m_drives[drv].busy = false;
  67. break;
  68. default:
  69. break;
  70. }
  71. }
  72. /**
  73. * @brief Default IO operation wait function.
  74. * */
  75. static void default_wait_func(void)
  76. {
  77. __WFE();
  78. }
  79. DSTATUS disk_initialize(BYTE drv)
  80. {
  81. ASSERT(m_drives);
  82. if (drv >= m_drives_count)
  83. {
  84. return (STA_NODISK | STA_NOINIT);
  85. }
  86. if (!m_drives[drv].config.p_block_device)
  87. {
  88. return (STA_NODISK | STA_NOINIT);
  89. }
  90. if (!(m_drives[drv].state & STA_NOINIT))
  91. {
  92. // Disk already initialized.
  93. return m_drives[drv].state;
  94. }
  95. if (m_drives[drv].config.wait_func == NULL)
  96. {
  97. m_drives[drv].config.wait_func = default_wait_func;
  98. }
  99. m_drives[drv].busy = true;
  100. ret_code_t err_code = nrf_blk_dev_init(m_drives[drv].config.p_block_device,
  101. block_dev_handler,
  102. (void *) (uint32_t) drv);
  103. if (err_code == NRF_SUCCESS)
  104. {
  105. while (m_drives[drv].busy)
  106. {
  107. m_drives[drv].config.wait_func();
  108. }
  109. if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  110. {
  111. m_drives[drv].state &= ~STA_NOINIT;
  112. }
  113. }
  114. return m_drives[drv].state;
  115. }
  116. DSTATUS disk_uninitialize(BYTE drv)
  117. {
  118. ASSERT(m_drives);
  119. if (drv >= m_drives_count)
  120. {
  121. return (STA_NODISK | STA_NOINIT);
  122. }
  123. if (!m_drives[drv].config.p_block_device)
  124. {
  125. return (STA_NODISK | STA_NOINIT);
  126. }
  127. if (m_drives[drv].state & STA_NOINIT)
  128. {
  129. // Disk already uninitialized.
  130. return m_drives[drv].state;
  131. }
  132. (void)nrf_blk_dev_ioctl(m_drives[drv].config.p_block_device,
  133. NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
  134. NULL);
  135. ret_code_t ret;
  136. do
  137. {
  138. /*Perform synchronous uninit.*/
  139. ret = nrf_blk_dev_uninit(m_drives[drv].config.p_block_device);
  140. } while (ret == NRF_ERROR_BUSY);
  141. if (ret == NRF_SUCCESS)
  142. {
  143. while (m_drives[drv].busy)
  144. {
  145. m_drives[drv].config.wait_func();
  146. }
  147. }
  148. if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  149. {
  150. m_drives[drv].state |= STA_NOINIT;
  151. }
  152. return m_drives[drv].state;
  153. }
  154. DSTATUS disk_status(BYTE drv)
  155. {
  156. ASSERT(m_drives);
  157. if (drv >= m_drives_count)
  158. {
  159. return STA_NOINIT;
  160. }
  161. return m_drives[drv].state;
  162. }
  163. DRESULT disk_read(BYTE drv, BYTE *buff, DWORD sector, UINT count)
  164. {
  165. ASSERT(m_drives);
  166. if ((drv >= m_drives_count) || (!count))
  167. {
  168. return RES_PARERR; // Invalid parameter(s).
  169. }
  170. if ((m_drives[drv].config.p_block_device == NULL)
  171. || (m_drives[drv].state & STA_NOINIT))
  172. {
  173. return RES_NOTRDY; // Disk not initialized.
  174. }
  175. const nrf_block_req_t req = {
  176. .p_buff = buff,
  177. .blk_id = sector,
  178. .blk_count = count
  179. };
  180. m_drives[drv].busy = true;
  181. ret_code_t err_code = nrf_blk_dev_read_req(m_drives[drv].config.p_block_device, &req);
  182. if (err_code == NRF_SUCCESS)
  183. {
  184. while (m_drives[drv].busy)
  185. {
  186. m_drives[drv].config.wait_func();
  187. }
  188. if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  189. {
  190. return RES_OK;
  191. }
  192. }
  193. return RES_ERROR;
  194. }
  195. DRESULT disk_write(BYTE drv, const BYTE *buff, DWORD sector, UINT count)
  196. {
  197. ASSERT(m_drives);
  198. if ((drv >= m_drives_count) || (!count))
  199. {
  200. return RES_PARERR; // Invalid parameter(s).
  201. }
  202. if ((m_drives[drv].config.p_block_device == NULL)
  203. || (m_drives[drv].state & STA_NOINIT))
  204. {
  205. return RES_NOTRDY; // Disk not initialized.
  206. }
  207. if (m_drives[drv].state & STA_PROTECT)
  208. {
  209. return RES_WRPRT; // Disk protection is enabled.
  210. }
  211. const nrf_block_req_t req = {
  212. .p_buff = (void *)buff,
  213. .blk_id = sector,
  214. .blk_count = count
  215. };
  216. m_drives[drv].busy = true;
  217. ret_code_t err_code = nrf_blk_dev_write_req(m_drives[drv].config.p_block_device, &req);
  218. if (err_code == NRF_SUCCESS)
  219. {
  220. while (m_drives[drv].busy)
  221. {
  222. m_drives[drv].config.wait_func();
  223. }
  224. if (m_drives[drv].last_result == NRF_BLOCK_DEV_RESULT_SUCCESS)
  225. {
  226. return RES_OK;
  227. }
  228. }
  229. return RES_ERROR;
  230. }
  231. DRESULT disk_ioctl(BYTE drv, BYTE cmd, void *buff)
  232. {
  233. ASSERT(m_drives);
  234. if (drv >= m_drives_count)
  235. {
  236. return RES_PARERR;
  237. }
  238. switch (cmd)
  239. {
  240. case CTRL_SYNC:
  241. {
  242. bool flush_in_progress = true;
  243. do {
  244. /*Perform synchronous FLUSH operation on block device*/
  245. ret_code_t ret = nrf_blk_dev_ioctl(m_drives[drv].config.p_block_device,
  246. NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH,
  247. &flush_in_progress);
  248. if (ret != NRF_SUCCESS && ret != NRF_ERROR_BUSY)
  249. {
  250. break;
  251. }
  252. } while (flush_in_progress);
  253. return RES_OK;
  254. }
  255. case GET_SECTOR_COUNT:
  256. {
  257. if (m_drives[drv].config.p_block_device == NULL)
  258. {
  259. return RES_NOTRDY;
  260. }
  261. DWORD * val = buff;
  262. *val = nrf_blk_dev_geometry(m_drives[drv].config.p_block_device)->blk_count;
  263. return RES_OK;
  264. }
  265. case GET_SECTOR_SIZE:
  266. {
  267. if (m_drives[drv].config.p_block_device == NULL)
  268. {
  269. return RES_NOTRDY;
  270. }
  271. WORD * val = buff;
  272. *val = nrf_blk_dev_geometry(m_drives[drv].config.p_block_device)->blk_size;
  273. return RES_OK;
  274. }
  275. default:
  276. break;
  277. }
  278. return RES_ERROR;
  279. }
  280. void diskio_blockdev_register(diskio_blkdev_t * diskio_blkdevs, size_t count)
  281. {
  282. ASSERT(diskio_blkdevs);
  283. m_drives = diskio_blkdevs;
  284. m_drives_count = count;
  285. }