nrf_fstorage.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 "sdk_config.h"
  41. #if NRF_FSTORAGE_ENABLED
  42. #include "nrf_fstorage.h"
  43. #include <stddef.h>
  44. #include <stdint.h>
  45. #include "sdk_errors.h"
  46. #include "sdk_macros.h"
  47. #include "nrf_section.h"
  48. #define NRF_LOG_MODULE_NAME nrf_fstorage
  49. #include "nrf_log.h"
  50. NRF_LOG_MODULE_REGISTER();
  51. /* Create the section "fs_data". */
  52. NRF_SECTION_DEF(fs_data, nrf_fstorage_t);
  53. /**@brief Macro to handle user input validation.
  54. *
  55. * If @p _cond evaluates to true, does nothing. Otherwise,
  56. * if the NRF_FSTORAGE_PARAM_CHECK_DISABLED is not set, logs an error message and returns @p _err.
  57. * If the NRF_FSTORAGE_PARAM_CHECK_DISABLED is set, behaves like the @ref ASSERT macro.
  58. *
  59. * Parameter checking implemented using this macro can be optionally turned off for release code.
  60. * Only disable runtime parameter checks if size if a major concern.
  61. *
  62. * @param _cond The condition to be evaluated.
  63. * @param _err The error code to be returned.
  64. */
  65. #define NRF_FSTORAGE_PARAM_CHECK(_cond, _err) \
  66. NRF_PARAM_CHECK(NRF_FSTORAGE, _cond, _err, NRF_LOG_ERROR)
  67. static bool addr_is_aligned32(uint32_t addr);
  68. static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, uint32_t addr);
  69. static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len);
  70. ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs,
  71. nrf_fstorage_api_t * p_api,
  72. void * p_param)
  73. {
  74. NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
  75. NRF_FSTORAGE_PARAM_CHECK(p_api, NRF_ERROR_NULL);
  76. p_fs->p_api = p_api;
  77. return (p_fs->p_api)->init(p_fs, p_param);
  78. }
  79. ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs,
  80. void * p_param)
  81. {
  82. ret_code_t rc;
  83. NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
  84. NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
  85. rc = (p_fs->p_api)->uninit(p_fs, p_param);
  86. /* Uninitialize the API. */
  87. p_fs->p_api = NULL;
  88. p_fs->p_flash_info = NULL;
  89. return rc;
  90. }
  91. ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs,
  92. uint32_t src,
  93. void * p_dest,
  94. uint32_t len)
  95. {
  96. NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
  97. NRF_FSTORAGE_PARAM_CHECK(p_dest, NRF_ERROR_NULL);
  98. NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
  99. NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
  100. /* Source addres must be word-aligned. */
  101. NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(src), NRF_ERROR_INVALID_ADDR);
  102. NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, src, len), NRF_ERROR_INVALID_ADDR);
  103. return (p_fs->p_api)->read(p_fs, src, p_dest, len);
  104. }
  105. ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs,
  106. uint32_t dest,
  107. void const * p_src,
  108. uint32_t len,
  109. void * p_context)
  110. {
  111. NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
  112. NRF_FSTORAGE_PARAM_CHECK(p_src, NRF_ERROR_NULL);
  113. NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
  114. NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
  115. /* Length must be a multiple of the program unit. */
  116. NRF_FSTORAGE_PARAM_CHECK(!(len % p_fs->p_flash_info->program_unit), NRF_ERROR_INVALID_LENGTH);
  117. /* Source and destination addresses must be word-aligned. */
  118. NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(dest), NRF_ERROR_INVALID_ADDR);
  119. NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32((uint32_t)p_src), NRF_ERROR_INVALID_ADDR);
  120. NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, dest, len), NRF_ERROR_INVALID_ADDR);
  121. return (p_fs->p_api)->write(p_fs, dest, p_src, len, p_context);
  122. }
  123. ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs,
  124. uint32_t page_addr,
  125. uint32_t len,
  126. void * p_context)
  127. {
  128. NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
  129. NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
  130. NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
  131. /* Address must be aligned to a page boundary. */
  132. NRF_FSTORAGE_PARAM_CHECK(addr_is_page_aligned(p_fs, page_addr), NRF_ERROR_INVALID_ADDR);
  133. NRF_FSTORAGE_PARAM_CHECK(
  134. addr_is_within_bounds(p_fs, page_addr, (len * p_fs->p_flash_info->erase_unit)),
  135. NRF_ERROR_INVALID_ADDR
  136. );
  137. return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context);
  138. }
  139. uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
  140. {
  141. if ((p_fs == NULL) || (p_fs->p_api == NULL))
  142. {
  143. return NULL;
  144. }
  145. return (p_fs->p_api)->rmap(p_fs, addr);
  146. }
  147. uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
  148. {
  149. if ((p_fs == NULL) || (p_fs->p_api == NULL))
  150. {
  151. return NULL;
  152. }
  153. return (p_fs->p_api)->wmap(p_fs, addr);
  154. }
  155. bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs)
  156. {
  157. /* If a NULL instance is provided, return true if any instance is busy.
  158. * Uninitialized instances are considered not busy. */
  159. if ((p_fs == NULL) || (p_fs->p_api == NULL))
  160. {
  161. for (uint32_t i = 0; i < NRF_FSTORAGE_INSTANCE_CNT; i++)
  162. {
  163. p_fs = NRF_FSTORAGE_INSTANCE_GET(i); /* cannot be NULL. */
  164. if (p_fs->p_api != NULL)
  165. {
  166. /* p_api->is_busy() cannot be NULL. */
  167. if (p_fs->p_api->is_busy(p_fs))
  168. {
  169. return true;
  170. }
  171. }
  172. }
  173. return false;
  174. }
  175. return p_fs->p_api->is_busy(p_fs);
  176. }
  177. static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs,
  178. uint32_t addr,
  179. uint32_t len)
  180. {
  181. return ( (addr >= p_fs->start_addr)
  182. && (addr + len - 1 <= p_fs->end_addr));
  183. }
  184. static bool addr_is_aligned32(uint32_t addr)
  185. {
  186. return !(addr & 0x03);
  187. }
  188. static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs,
  189. uint32_t addr)
  190. {
  191. return (addr & (p_fs->p_flash_info->erase_unit - 1)) == 0;
  192. }
  193. #endif // NRF_FSTORAGE_ENABLED