nrf_block_dev_sdc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  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 "nrf_block_dev_sdc.h"
  41. /**@file
  42. *
  43. * @ingroup nrf_block_dev_sdc
  44. * @{
  45. *
  46. * @brief This module implements block device API. It should be used as a reference block device.
  47. */
  48. static volatile sdc_result_t m_last_result;
  49. /**
  50. * @brief Active SDC block device handle. Only one instance.
  51. * */
  52. static nrf_block_dev_sdc_t const * m_active_sdc_dev;
  53. static ret_code_t block_dev_sdc_uninit(nrf_block_dev_t const * p_blk_dev);
  54. static void wait_func(void)
  55. {
  56. }
  57. static void sdc_wait()
  58. {
  59. while (app_sdc_busy_check())
  60. {
  61. wait_func();
  62. }
  63. }
  64. static void sdc_handler(sdc_evt_t const * p_event)
  65. {
  66. m_last_result = p_event->result;
  67. nrf_block_dev_sdc_t const * p_sdc_dev = m_active_sdc_dev;
  68. nrf_block_dev_sdc_work_t * p_work = p_sdc_dev->p_work;
  69. switch (p_event->type)
  70. {
  71. case SDC_EVT_INIT:
  72. {
  73. if (p_event->result != SDC_SUCCESS)
  74. {
  75. nrf_block_dev_t const * block_dev = &(p_sdc_dev->block_dev);
  76. ret_code_t err_code = block_dev_sdc_uninit(block_dev);
  77. APP_ERROR_CHECK(err_code);
  78. }
  79. p_work->geometry.blk_count = app_sdc_info_get()->num_blocks;
  80. p_work->geometry.blk_size = SDC_SECTOR_SIZE;
  81. if (m_active_sdc_dev->p_work->ev_handler)
  82. {
  83. const nrf_block_dev_event_t ev = {
  84. NRF_BLOCK_DEV_EVT_INIT,
  85. ((p_event->result == SDC_SUCCESS) ? \
  86. NRF_BLOCK_DEV_RESULT_SUCCESS : NRF_BLOCK_DEV_RESULT_IO_ERROR),
  87. NULL,
  88. p_work->p_context
  89. };
  90. p_work->ev_handler(&p_sdc_dev->block_dev, &ev);
  91. }
  92. }
  93. break;
  94. case SDC_EVT_READ:
  95. if (m_active_sdc_dev->p_work->ev_handler)
  96. {
  97. const nrf_block_dev_event_t ev = {
  98. NRF_BLOCK_DEV_EVT_BLK_READ_DONE,
  99. ((p_event->result == SDC_SUCCESS) ? \
  100. NRF_BLOCK_DEV_RESULT_SUCCESS : NRF_BLOCK_DEV_RESULT_IO_ERROR),
  101. &p_work->req,
  102. p_work->p_context
  103. };
  104. p_work->ev_handler(&p_sdc_dev->block_dev, &ev);
  105. }
  106. break;
  107. case SDC_EVT_WRITE:
  108. if (m_active_sdc_dev->p_work->ev_handler)
  109. {
  110. const nrf_block_dev_event_t ev = {
  111. NRF_BLOCK_DEV_EVT_BLK_WRITE_DONE,
  112. ((p_event->result == SDC_SUCCESS) ? \
  113. NRF_BLOCK_DEV_RESULT_SUCCESS : NRF_BLOCK_DEV_RESULT_IO_ERROR),
  114. &p_work->req,
  115. p_work->p_context
  116. };
  117. p_work->ev_handler(&p_sdc_dev->block_dev, &ev);
  118. }
  119. break;
  120. default:
  121. APP_ERROR_CHECK(NRF_ERROR_INTERNAL);
  122. return;
  123. }
  124. }
  125. static ret_code_t block_dev_sdc_init(nrf_block_dev_t const * p_blk_dev,
  126. nrf_block_dev_ev_handler ev_handler,
  127. void const * p_context)
  128. {
  129. ASSERT(p_blk_dev);
  130. nrf_block_dev_sdc_t const * p_sdc_dev =
  131. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  132. nrf_block_dev_sdc_work_t * p_work = p_sdc_dev->p_work;
  133. if (p_sdc_dev->sdc_bdev_config.block_size != SDC_SECTOR_SIZE)
  134. {
  135. /* Unsupported block size. */
  136. return NRF_ERROR_NOT_SUPPORTED;
  137. }
  138. if (m_active_sdc_dev)
  139. {
  140. /* SDC instance is busy. */
  141. return NRF_ERROR_BUSY;
  142. }
  143. p_work->p_context = p_context;
  144. p_work->ev_handler = ev_handler;
  145. m_active_sdc_dev = p_sdc_dev;
  146. ret_code_t err_code = NRF_SUCCESS;
  147. err_code = app_sdc_init(&p_sdc_dev->sdc_bdev_config.sdc_config, sdc_handler);
  148. if (err_code == NRF_SUCCESS)
  149. {
  150. if (!ev_handler)
  151. {
  152. /* Synchronous mode - wait for the card. */
  153. sdc_wait();
  154. err_code = ((m_last_result == SDC_SUCCESS) ? NRF_SUCCESS : NRF_ERROR_TIMEOUT);
  155. }
  156. }
  157. if (err_code != NRF_SUCCESS)
  158. {
  159. m_active_sdc_dev = NULL;
  160. if (ev_handler)
  161. {
  162. /* Call the user handler with an error status. */
  163. const nrf_block_dev_event_t ev = {
  164. NRF_BLOCK_DEV_EVT_INIT,
  165. NRF_BLOCK_DEV_RESULT_IO_ERROR,
  166. NULL,
  167. p_work->p_context
  168. };
  169. p_work->ev_handler(p_blk_dev, &ev);
  170. }
  171. }
  172. return err_code;
  173. }
  174. static ret_code_t block_dev_sdc_uninit(nrf_block_dev_t const * p_blk_dev)
  175. {
  176. ASSERT(p_blk_dev);
  177. nrf_block_dev_sdc_t const * p_sdc_dev =
  178. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  179. nrf_block_dev_sdc_work_t * p_work = p_sdc_dev->p_work;
  180. if (m_active_sdc_dev != p_sdc_dev)
  181. {
  182. /* SDC instance is busy. */
  183. return NRF_ERROR_BUSY;
  184. }
  185. if (app_sdc_busy_check())
  186. {
  187. /* Previous asynchronous operation in progress. */
  188. return NRF_ERROR_BUSY;
  189. }
  190. ret_code_t err_code = app_sdc_uninit();
  191. if (err_code == NRF_SUCCESS)
  192. {
  193. /* Free the instance on success. */
  194. m_active_sdc_dev = NULL;
  195. }
  196. if (p_work->ev_handler)
  197. {
  198. /* SDC uninitialization is a synchronous operation. Call event handler. */
  199. const nrf_block_dev_event_t ev = {
  200. NRF_BLOCK_DEV_EVT_UNINIT,
  201. ((err_code == NRF_SUCCESS) ? \
  202. NRF_BLOCK_DEV_RESULT_SUCCESS : NRF_BLOCK_DEV_RESULT_IO_ERROR),
  203. NULL,
  204. p_work->p_context
  205. };
  206. p_work->ev_handler(p_blk_dev, &ev);
  207. }
  208. return err_code;
  209. }
  210. static ret_code_t block_dev_sdc_read_req(nrf_block_dev_t const * p_blk_dev,
  211. nrf_block_req_t const * p_blk)
  212. {
  213. ASSERT(p_blk_dev);
  214. ASSERT(p_blk);
  215. nrf_block_dev_sdc_t const * p_sdc_dev =
  216. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  217. nrf_block_dev_sdc_work_t * p_work = p_sdc_dev->p_work;
  218. ret_code_t err_code = NRF_SUCCESS;
  219. if (m_active_sdc_dev != p_sdc_dev)
  220. {
  221. /* SDC instance is busy. */
  222. return NRF_ERROR_BUSY;
  223. }
  224. if (app_sdc_busy_check())
  225. {
  226. /* Previous asynchronous operation in progress. */
  227. return NRF_ERROR_BUSY;
  228. }
  229. p_work->req = *p_blk;
  230. err_code = app_sdc_block_read(p_blk->p_buff, p_blk->blk_id, p_blk->blk_count);
  231. if (err_code == NRF_SUCCESS)
  232. {
  233. if (!p_work->ev_handler)
  234. {
  235. /* Synchronous mode - wait for the card. */
  236. sdc_wait();
  237. err_code = ((m_last_result == SDC_SUCCESS) ? NRF_SUCCESS : NRF_ERROR_TIMEOUT);
  238. }
  239. }
  240. if ((p_work->ev_handler) && (err_code != NRF_SUCCESS))
  241. {
  242. /* Call the user handler with an error status. */
  243. const nrf_block_dev_event_t ev = {
  244. NRF_BLOCK_DEV_EVT_BLK_READ_DONE,
  245. NRF_BLOCK_DEV_RESULT_IO_ERROR,
  246. &p_work->req,
  247. p_work->p_context
  248. };
  249. p_work->ev_handler(p_blk_dev, &ev);
  250. }
  251. return err_code;
  252. }
  253. static ret_code_t block_dev_sdc_write_req(nrf_block_dev_t const * p_blk_dev,
  254. nrf_block_req_t const * p_blk)
  255. {
  256. ASSERT(p_blk_dev);
  257. ASSERT(p_blk);
  258. nrf_block_dev_sdc_t const * p_sdc_dev =
  259. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  260. nrf_block_dev_sdc_work_t * p_work = p_sdc_dev->p_work;
  261. ret_code_t err_code = NRF_SUCCESS;
  262. if (m_active_sdc_dev != p_sdc_dev)
  263. {
  264. /* SDC instance is busy. */
  265. return NRF_ERROR_BUSY;
  266. }
  267. if (app_sdc_busy_check())
  268. {
  269. /* Previous asynchronous operation in progress. */
  270. return NRF_ERROR_BUSY;
  271. }
  272. p_work->req = *p_blk;
  273. err_code = app_sdc_block_write(p_blk->p_buff, p_blk->blk_id, p_blk->blk_count);
  274. if (err_code == NRF_SUCCESS)
  275. {
  276. if (!p_work->ev_handler)
  277. {
  278. /* Synchronous mode - wait for the card. */
  279. sdc_wait();
  280. err_code = ((m_last_result == SDC_SUCCESS) ? NRF_SUCCESS : NRF_ERROR_TIMEOUT);
  281. }
  282. }
  283. if ((p_work->ev_handler) && (err_code != NRF_SUCCESS))
  284. {
  285. /* Call the user handler with an error status. */
  286. const nrf_block_dev_event_t ev = {
  287. NRF_BLOCK_DEV_EVT_BLK_READ_DONE,
  288. NRF_BLOCK_DEV_RESULT_IO_ERROR,
  289. &p_work->req,
  290. p_work->p_context
  291. };
  292. p_work->ev_handler(p_blk_dev, &ev);
  293. }
  294. return err_code;
  295. }
  296. static ret_code_t block_dev_sdc_ioctl(nrf_block_dev_t const * p_blk_dev,
  297. nrf_block_dev_ioctl_req_t req,
  298. void * p_data)
  299. {
  300. nrf_block_dev_sdc_t const * p_sdc_dev =
  301. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  302. switch (req)
  303. {
  304. case NRF_BLOCK_DEV_IOCTL_REQ_CACHE_FLUSH:
  305. {
  306. bool * p_flushing = p_data;
  307. if (p_flushing)
  308. {
  309. *p_flushing = false;
  310. }
  311. return NRF_SUCCESS;
  312. }
  313. case NRF_BLOCK_DEV_IOCTL_REQ_INFO_STRINGS:
  314. {
  315. if (p_data == NULL)
  316. {
  317. return NRF_ERROR_INVALID_PARAM;
  318. }
  319. nrf_block_dev_info_strings_t const * * pp_strings = p_data;
  320. *pp_strings = &p_sdc_dev->info_strings;
  321. return NRF_SUCCESS;
  322. }
  323. default:
  324. break;
  325. }
  326. return NRF_ERROR_NOT_SUPPORTED;
  327. }
  328. static nrf_block_dev_geometry_t const * block_dev_sdc_geometry(nrf_block_dev_t const * p_blk_dev)
  329. {
  330. ASSERT(p_blk_dev);
  331. nrf_block_dev_sdc_t const * p_sdc_dev =
  332. CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
  333. nrf_block_dev_sdc_work_t const * p_work = p_sdc_dev->p_work;
  334. return &p_work->geometry;
  335. }
  336. const nrf_block_dev_ops_t nrf_block_device_sdc_ops = {
  337. .init = block_dev_sdc_init,
  338. .uninit = block_dev_sdc_uninit,
  339. .read_req = block_dev_sdc_read_req,
  340. .write_req = block_dev_sdc_write_req,
  341. .ioctl = block_dev_sdc_ioctl,
  342. .geometry = block_dev_sdc_geometry,
  343. };
  344. /** @} */