mem_manager.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /**
  2. * Copyright (c) 2014 - 2019, 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_common.h"
  41. #if NRF_MODULE_ENABLED(MEM_MANAGER)
  42. #include "mem_manager.h"
  43. #include "nrf_assert.h"
  44. #define NRF_LOG_MODULE_NAME mem_mngr
  45. #if MEM_MANAGER_CONFIG_LOG_ENABLED
  46. #define NRF_LOG_LEVEL MEM_MANAGER_CONFIG_LOG_LEVEL
  47. #define NRF_LOG_INFO_COLOR MEM_MANAGER_CONFIG_INFO_COLOR
  48. #define NRF_LOG_DEBUG_COLOR MEM_MANAGER_CONFIG_DEBUG_COLOR
  49. #else //MEM_MANAGER_CONFIG_LOG_ENABLED
  50. #define NRF_LOG_LEVEL 0
  51. #endif //MEM_MANAGER_CONFIG_LOG_ENABLED
  52. #include "nrf_log.h"
  53. NRF_LOG_MODULE_REGISTER();
  54. /**
  55. * @defgroup memory_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
  56. *
  57. * @details Macros used to lock and unlock modules. Currently the SDK does not use mutexes but
  58. * framework is provided in case need arises to use an alternative architecture.
  59. * @{
  60. */
  61. #define MM_MUTEX_LOCK() SDK_MUTEX_LOCK(m_mm_mutex) /**< Lock module using mutex. */
  62. #define MM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_mm_mutex) /**< Unlock module using mutex. */
  63. /** @} */
  64. #undef NULL_PARAM_CHECK
  65. #undef NULL_PARAM_CHECK_VOID
  66. #undef VERIFY_MODULE_INITIALIZED
  67. #undef VERIFY_MODULE_INITIALIZED_VOID
  68. #undef VERIFY_REQUESTED_SIZE
  69. #undef VERIFY_REQUESTED_SIZE_VOID
  70. #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
  71. /**
  72. * @brief Macro for verifying NULL parameters.
  73. * Returning with an appropriate error code on failure.
  74. *
  75. * @param[in] PARAM Parameter checked for NULL.
  76. *
  77. * @retval (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) when @ref PARAM is NULL.
  78. */
  79. #define NULL_PARAM_CHECK(PARAM) \
  80. if ((PARAM) == NULL) \
  81. { \
  82. return (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
  83. }
  84. /**
  85. * @brief Macro for verifying NULL parameters are not passed to API and returning on failure.
  86. *
  87. * @param[in] PARAM Parameter checked for NULL.
  88. */
  89. #define NULL_PARAM_CHECK_VOID(PARAM) \
  90. if ((PARAM) == NULL) \
  91. { \
  92. return; \
  93. }
  94. /**
  95. * @brief Macro for verifying module's initialization status.
  96. * Returning with an appropriate error code on failure.
  97. *
  98. * @retval (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) module is uninitialized.
  99. */
  100. #define VERIFY_MODULE_INITIALIZED() \
  101. do \
  102. { \
  103. if (!m_module_initialized) \
  104. { \
  105. return (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
  106. } \
  107. } while (0)
  108. /**
  109. * @brief Macro for verifying module's initialization status and returning on failure.
  110. */
  111. #define VERIFY_MODULE_INITIALIZED_VOID() \
  112. do \
  113. { \
  114. if (!m_module_initialized) \
  115. { \
  116. return; \
  117. } \
  118. } while (0)
  119. /**
  120. * @brief Macro for verifying requested size of memory does not exceed maximum block
  121. * size supported by the module. Returning with appropriate error code on failure.
  122. *
  123. * @param[in] SIZE Requested size to be allocated.
  124. *
  125. * @retval (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) if requested size is greater
  126. * than the largest block size managed by the module.
  127. */
  128. #define VERIFY_REQUESTED_SIZE(SIZE) \
  129. do \
  130. { \
  131. if (((SIZE) == 0) ||((SIZE) > MAX_MEM_SIZE)) \
  132. { \
  133. return (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
  134. } \
  135. } while (0)
  136. /**
  137. * @brief Macro for verifying requested size of memory does not exceed maximum block
  138. * size supported by the module. Returns on failure.
  139. *
  140. * @param[in] SIZE Requested size to be allocated.
  141. */
  142. #define VERIFY_REQUESTED_SIZE_VOID(SIZE) \
  143. do \
  144. { \
  145. if (((SIZE) == 0) ||((SIZE) > MAX_MEM_SIZE)) \
  146. { \
  147. return; \
  148. } \
  149. } while (0)
  150. /**@} */
  151. #else //MEM_MANAGER_DISABLE_API_PARAM_CHECK
  152. #define NULL_PARAM_CHECK(PARAM)
  153. #define VERIFY_MODULE_INITIALIZED()
  154. #define VERIFY_REQUESTED_SIZE(SIZE)
  155. #endif //MEM_MANAGER_DISABLE_API_PARAM_CHECK
  156. /**@brief Setting defaults in case XXSmall block not used by application. */
  157. #ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT
  158. #define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0
  159. #define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 0
  160. #define XXSMALL_BLOCK_START 0
  161. #define XXSMALL_BLOCK_END 0
  162. #define XXSMALL_MEMORY_START 0
  163. #endif // MEMORY_MANAGER_XXSMALL_BLOCK_SIZE
  164. /**@brief Setting defaults in case XSmall block not used by application. */
  165. #ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT
  166. #define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0
  167. #define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 0
  168. #define XSMALL_BLOCK_START 0
  169. #define XSMALL_BLOCK_END 0
  170. #define XSMALL_MEMORY_START 0
  171. #endif // MEMORY_MANAGER_XSMALL_BLOCK_SIZE
  172. /**@brief Setting defaults in case Small block not used by application. */
  173. #ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT
  174. #define MEMORY_MANAGER_SMALL_BLOCK_COUNT 0
  175. #define MEMORY_MANAGER_SMALL_BLOCK_SIZE 0
  176. #define SMALL_BLOCK_START 0
  177. #define SMALL_BLOCK_END 0
  178. #define SMALL_MEMORY_START 0
  179. #endif // MEMORY_MANAGER_SMALL_BLOCK_COUNT
  180. /**@brief Setting defaults in case Medium block not used by application. */
  181. #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
  182. #define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0
  183. #define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 0
  184. #define MEDIUM_BLOCK_START 0
  185. #define MEDIUM_BLOCK_END 0
  186. #define MEDIUM_MEMORY_START 0
  187. #endif // MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
  188. /**@brief Setting defaults in case Large block not used by application. */
  189. #ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT
  190. #define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0
  191. #define MEMORY_MANAGER_LARGE_BLOCK_SIZE 0
  192. #define LARGE_BLOCK_START 0
  193. #define LARGE_BLOCK_END 0
  194. #define LARGE_MEMORY_START 0
  195. #endif // MEMORY_MANAGER_LARGE_BLOCK_COUNT
  196. /**@brief Setting defaults in case XLarge block not used by application. */
  197. #ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT
  198. #define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0
  199. #define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 0
  200. #define XLARGE_BLOCK_START 0
  201. #define XLARGE_BLOCK_END 0
  202. #define XLARGE_MEMORY_START 0
  203. #endif // MEMORY_MANAGER_XLARGE_BLOCK_COUNT
  204. /**@brief Setting defaults in case XXLarge block not used by application. */
  205. #ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
  206. #define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0
  207. #define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 0
  208. #define XXLARGE_BLOCK_START 0
  209. #define XXLARGE_BLOCK_END 0
  210. #define XXLARGE_MEMORY_START 0
  211. #endif // MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
  212. /**@brief Based on which blocks are defined, MAX_MEM_SIZE is determined.
  213. *
  214. * @note Also, in case none of these are defined, a compile time error is indicated.
  215. */
  216. #if (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT != 0)
  217. #define MAX_MEM_SIZE MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
  218. #elif (MEMORY_MANAGER_XLARGE_BLOCK_COUNT != 0)
  219. #define MAX_MEM_SIZE MEMORY_MANAGER_XLARGE_BLOCK_SIZE
  220. #elif (MEMORY_MANAGER_LARGE_BLOCK_COUNT != 0)
  221. #define MAX_MEM_SIZE MEMORY_MANAGER_LARGE_BLOCK_SIZE
  222. #elif (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT != 0)
  223. #define MAX_MEM_SIZE MEMORY_MANAGER_MEDIUM_BLOCK_SIZE
  224. #elif (MEMORY_MANAGER_SMALL_BLOCK_COUNT != 0)
  225. #define MAX_MEM_SIZE MEMORY_MANAGER_SMALL_BLOCK_SIZE
  226. #elif (MEMORY_MANAGER_XSMALL_BLOCK_COUNT != 0)
  227. #define MAX_MEM_SIZE MEMORY_MANAGER_XSMALL_BLOCK_SIZE
  228. #elif (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT != 0)
  229. #define MAX_MEM_SIZE MEMORY_MANAGER_XXSMALL_BLOCK_SIZE
  230. #else
  231. #err "One of MEMORY_MANAGER_SMALL_BLOCK_COUNT, MEMORY_MANAGER_MEDIUM_BLOCK_COUNT or \
  232. or MEMORY_MANAGER_LARGE_BLOCK_COUNT should be defined."
  233. #endif
  234. /**@brief XXSmall block start index in case XXSmall Block is defined. */
  235. #ifndef XXSMALL_BLOCK_START
  236. #define XXSMALL_BLOCK_START 0
  237. #endif // XXSMALL_BLOCK_START
  238. /**@brief XSmall block start index in case XSmall Block is defined. */
  239. #ifndef XSMALL_BLOCK_START
  240. #define XSMALL_BLOCK_START (XXSMALL_BLOCK_START + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT)
  241. #endif // XSMALL_BLOCK_START
  242. /**@brief Small block start index in case Small Block is defined. */
  243. #ifndef SMALL_BLOCK_START
  244. #define SMALL_BLOCK_START (XSMALL_BLOCK_START + MEMORY_MANAGER_XSMALL_BLOCK_COUNT)
  245. #endif // SMALL_BLOCK_START
  246. /**@brief Medium block start index in case Medium Block is defined. */
  247. #ifndef MEDIUM_BLOCK_START
  248. #define MEDIUM_BLOCK_START (SMALL_BLOCK_START + MEMORY_MANAGER_SMALL_BLOCK_COUNT)
  249. #endif // MEDIUM_BLOCK_START
  250. /**@brief Large block start index in case Large Block is defined. */
  251. #ifndef LARGE_BLOCK_START
  252. #define LARGE_BLOCK_START (MEDIUM_BLOCK_START + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT)
  253. #endif // LARGE_BLOCK_START
  254. /**@brief XLarge block start index in case XLarge Block is defined. */
  255. #ifndef XLARGE_BLOCK_START
  256. #define XLARGE_BLOCK_START (LARGE_BLOCK_START + MEMORY_MANAGER_LARGE_BLOCK_COUNT)
  257. #endif // XLARGE_BLOCK_START
  258. /**@brief XXLarge block start index in case XXLarge Block is defined. */
  259. #ifndef XXLARGE_BLOCK_START
  260. #define XXLARGE_BLOCK_START (XLARGE_BLOCK_START + MEMORY_MANAGER_XLARGE_BLOCK_COUNT)
  261. #endif //XXLARGE_BLOCK_START
  262. /**@brief XXSmall block end index in case XXSmall Block is defined. */
  263. #ifndef XXSMALL_BLOCK_END
  264. #define XXSMALL_BLOCK_END (XXSMALL_BLOCK_START + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT)
  265. #endif // XXSMALL_BLOCK_END
  266. /**@brief XSmall block end index in case XSmall Block is defined. */
  267. #ifndef XSMALL_BLOCK_END
  268. #define XSMALL_BLOCK_END (XSMALL_BLOCK_START + MEMORY_MANAGER_XSMALL_BLOCK_COUNT)
  269. #endif // XSMALL_BLOCK_END
  270. /**@brief Small block end index in case Small Block is defined. */
  271. #ifndef SMALL_BLOCK_END
  272. #define SMALL_BLOCK_END (SMALL_BLOCK_START + MEMORY_MANAGER_SMALL_BLOCK_COUNT)
  273. #endif // SMALL_BLOCK_END
  274. /**@brief Medium block end index in case Medium Block is defined. */
  275. #ifndef MEDIUM_BLOCK_END
  276. #define MEDIUM_BLOCK_END (MEDIUM_BLOCK_START + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT)
  277. #endif // MEDIUM_BLOCK_END
  278. /**@brief Large block end index in case Large Block is defined. */
  279. #ifndef LARGE_BLOCK_END
  280. #define LARGE_BLOCK_END (LARGE_BLOCK_START + MEMORY_MANAGER_LARGE_BLOCK_COUNT)
  281. #endif // LARGE_BLOCK_END
  282. /**@brief XLarge block end index in case XLarge Block is defined. */
  283. #ifndef XLARGE_BLOCK_END
  284. #define XLARGE_BLOCK_END (XLARGE_BLOCK_START + MEMORY_MANAGER_XLARGE_BLOCK_COUNT)
  285. #endif // XLARGE_BLOCK_END
  286. /**@brief XXLarge block end index in case XXLarge Block is defined. */
  287. #ifndef XXLARGE_BLOCK_END
  288. #define XXLARGE_BLOCK_END (XXLARGE_BLOCK_START + MEMORY_MANAGER_XXLARGE_BLOCK_COUNT)
  289. #endif //XXLARGE_BLOCK_END
  290. #define XXSMALL_MEMORY_SIZE (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT * MEMORY_MANAGER_XXSMALL_BLOCK_SIZE)
  291. #define XSMALL_MEMORY_SIZE (MEMORY_MANAGER_XSMALL_BLOCK_COUNT * MEMORY_MANAGER_XSMALL_BLOCK_SIZE)
  292. #define SMALL_MEMORY_SIZE (MEMORY_MANAGER_SMALL_BLOCK_COUNT * MEMORY_MANAGER_SMALL_BLOCK_SIZE)
  293. #define MEDIUM_MEMORY_SIZE (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT * MEMORY_MANAGER_MEDIUM_BLOCK_SIZE)
  294. #define LARGE_MEMORY_SIZE (MEMORY_MANAGER_LARGE_BLOCK_COUNT * MEMORY_MANAGER_LARGE_BLOCK_SIZE)
  295. #define XLARGE_MEMORY_SIZE (MEMORY_MANAGER_XLARGE_BLOCK_COUNT * MEMORY_MANAGER_XLARGE_BLOCK_SIZE)
  296. #define XXLARGE_MEMORY_SIZE (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT * MEMORY_MANAGER_XXLARGE_BLOCK_SIZE)
  297. /**@brief XXSmall memory start index in case XXSmall Block is defined. */
  298. #ifndef XXSMALL_MEMORY_START
  299. #define XXSMALL_MEMORY_START 0
  300. #endif // XXSMALL_MEMORY_START
  301. /**@brief XSmall memory start index in case XSmall Block is defined. */
  302. #ifndef XSMALL_MEMORY_START
  303. #define XSMALL_MEMORY_START (XXSMALL_MEMORY_START + XXSMALL_MEMORY_SIZE)
  304. #endif // XSMALL_MEMORY_START
  305. /**@brief Small memory start index in case Small Block is defined. */
  306. #ifndef SMALL_MEMORY_START
  307. #define SMALL_MEMORY_START (XSMALL_MEMORY_START + XSMALL_MEMORY_SIZE)
  308. #endif // SMALL_MEMORY_START
  309. /**@brief Medium memory start index in case Medium Block is defined. */
  310. #ifndef MEDIUM_MEMORY_START
  311. #define MEDIUM_MEMORY_START (SMALL_MEMORY_START + SMALL_MEMORY_SIZE)
  312. #endif // MEDIUM_MEMORY_START
  313. /**@brief Large memory start index in case Large Block is defined. */
  314. #ifndef LARGE_MEMORY_START
  315. #define LARGE_MEMORY_START (MEDIUM_MEMORY_START + MEDIUM_MEMORY_SIZE)
  316. #endif // LARGE_MEMORY_START
  317. /**@brief XLarge memory start index in case XLarge Block is defined. */
  318. #ifndef XLARGE_MEMORY_START
  319. #define XLARGE_MEMORY_START (LARGE_MEMORY_START + LARGE_MEMORY_SIZE)
  320. #endif // XLARGE_MEMORY_START
  321. /**@brief XXLarge memory start index in case XXLarge Block is defined. */
  322. #ifndef XXLARGE_MEMORY_START
  323. #define XXLARGE_MEMORY_START (XLARGE_MEMORY_START + XLARGE_MEMORY_SIZE)
  324. #endif // XLARGE_MEMORY_START
  325. /**@brief Total count of block managed by the module. */
  326. #define TOTAL_BLOCK_COUNT (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT + \
  327. MEMORY_MANAGER_XSMALL_BLOCK_COUNT + \
  328. MEMORY_MANAGER_SMALL_BLOCK_COUNT + \
  329. MEMORY_MANAGER_MEDIUM_BLOCK_COUNT + \
  330. MEMORY_MANAGER_LARGE_BLOCK_COUNT + \
  331. MEMORY_MANAGER_XLARGE_BLOCK_COUNT + \
  332. MEMORY_MANAGER_XXLARGE_BLOCK_COUNT)
  333. /**@brief Total memory managed by the module. */
  334. #define TOTAL_MEMORY_SIZE (XXSMALL_MEMORY_SIZE + \
  335. XSMALL_MEMORY_SIZE + \
  336. SMALL_MEMORY_SIZE + \
  337. MEDIUM_MEMORY_SIZE + \
  338. LARGE_MEMORY_SIZE + \
  339. XLARGE_MEMORY_SIZE + \
  340. XXLARGE_MEMORY_SIZE)
  341. #define BLOCK_CAT_COUNT 7 /**< Block category count is 7 (xxsmall, xsmall, small, medium, large, xlarge, xxlarge). Having one of the block count to zero has no impact on this count. */
  342. #define BLOCK_CAT_XXS 0 /**< Extra Extra Small category identifier. */
  343. #define BLOCK_CAT_XS 1 /**< Extra Small category identifier. */
  344. #define BLOCK_CAT_SMALL 2 /**< Small category identifier. */
  345. #define BLOCK_CAT_MEDIUM 3 /**< Medium category identifier. */
  346. #define BLOCK_CAT_LARGE 4 /**< Large category identifier. */
  347. #define BLOCK_CAT_XL 5 /**< Extra Large category identifier. */
  348. #define BLOCK_CAT_XXL 6 /**< Extra Extra Large category identifier. */
  349. #define BITMAP_SIZE 32 /**< Bitmap size for each word used to contain block information. */
  350. #define BLOCK_BITMAP_ARRAY_SIZE CEIL_DIV(TOTAL_BLOCK_COUNT, BITMAP_SIZE) /**< Determines number of blocks needed for book keeping availability status of all blocks. */
  351. /**@brief Lookup table for maximum memory size per block category. */
  352. static const uint32_t m_block_size[BLOCK_CAT_COUNT] =
  353. {
  354. MEMORY_MANAGER_XXSMALL_BLOCK_SIZE,
  355. MEMORY_MANAGER_XSMALL_BLOCK_SIZE,
  356. MEMORY_MANAGER_SMALL_BLOCK_SIZE,
  357. MEMORY_MANAGER_MEDIUM_BLOCK_SIZE,
  358. MEMORY_MANAGER_LARGE_BLOCK_SIZE,
  359. MEMORY_MANAGER_XLARGE_BLOCK_SIZE,
  360. MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
  361. };
  362. /**@brief Lookup table for block start index for each block category. */
  363. static const uint32_t m_block_start[BLOCK_CAT_COUNT] =
  364. {
  365. XXSMALL_BLOCK_START,
  366. XSMALL_BLOCK_START,
  367. SMALL_BLOCK_START,
  368. MEDIUM_BLOCK_START,
  369. LARGE_BLOCK_START,
  370. XLARGE_BLOCK_START,
  371. XXLARGE_BLOCK_START
  372. };
  373. /**@brief Lookup table for last block index for each block category. */
  374. static const uint32_t m_block_end[BLOCK_CAT_COUNT] =
  375. {
  376. XXSMALL_BLOCK_END,
  377. XSMALL_BLOCK_END,
  378. SMALL_BLOCK_END,
  379. MEDIUM_BLOCK_END,
  380. LARGE_BLOCK_END,
  381. XLARGE_BLOCK_END,
  382. XXLARGE_BLOCK_END
  383. };
  384. /**@brief Lookup table for memory start range for each block category. */
  385. static const uint32_t m_block_mem_start[BLOCK_CAT_COUNT] =
  386. {
  387. XXSMALL_MEMORY_START,
  388. XSMALL_MEMORY_START,
  389. SMALL_MEMORY_START,
  390. MEDIUM_MEMORY_START,
  391. LARGE_MEMORY_START,
  392. XLARGE_MEMORY_START,
  393. XXLARGE_MEMORY_START
  394. };
  395. static uint8_t m_memory[TOTAL_MEMORY_SIZE]; /**< Memory managed by the module. */
  396. static uint32_t m_mem_pool[BLOCK_BITMAP_ARRAY_SIZE]; /**< Bitmap used for book-keeping availability of all blocks managed by the module. */
  397. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  398. /**@brief Lookup table for descriptive strings for each block category. */
  399. static const char * m_block_desc_str[BLOCK_CAT_COUNT] =
  400. {
  401. "XXSmall",
  402. "XSmall",
  403. "Small",
  404. "Medium",
  405. "Large",
  406. "XLarge",
  407. "XXLarge"
  408. };
  409. /**@brief Table for book keeping smallest size allocated in each block range. */
  410. static uint32_t m_min_size[BLOCK_CAT_COUNT] =
  411. {
  412. MEMORY_MANAGER_XXSMALL_BLOCK_SIZE,
  413. MEMORY_MANAGER_XSMALL_BLOCK_SIZE,
  414. MEMORY_MANAGER_SMALL_BLOCK_SIZE,
  415. MEMORY_MANAGER_MEDIUM_BLOCK_SIZE,
  416. MEMORY_MANAGER_LARGE_BLOCK_SIZE,
  417. MEMORY_MANAGER_XLARGE_BLOCK_SIZE,
  418. MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
  419. };
  420. /**@brief Table for book keeping largest size allocated in each block range. */
  421. static uint32_t m_max_size[BLOCK_CAT_COUNT];
  422. /**@brief Global pointing to minimum size holder for block type being allocated. */
  423. static uint32_t * p_min_size;
  424. /**@brief Global pointing to maximum size holder for block type being allocated. */
  425. static uint32_t * p_max_size;
  426. /**@brief Lookup table for count of block available in each block category. */
  427. static uint32_t m_block_count[BLOCK_CAT_COUNT] =
  428. {
  429. MEMORY_MANAGER_XXSMALL_BLOCK_COUNT,
  430. MEMORY_MANAGER_XSMALL_BLOCK_COUNT,
  431. MEMORY_MANAGER_SMALL_BLOCK_COUNT,
  432. MEMORY_MANAGER_MEDIUM_BLOCK_COUNT,
  433. MEMORY_MANAGER_LARGE_BLOCK_COUNT,
  434. MEMORY_MANAGER_XLARGE_BLOCK_COUNT,
  435. MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
  436. };
  437. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  438. SDK_MUTEX_DEFINE(m_mm_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
  439. #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
  440. static bool m_module_initialized = false; /**< State indicating if module is initialized or not. */
  441. #endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK
  442. /**@brief Function to get X and Y coordinates.
  443. *
  444. * @details Function to get X and Y co-ordinates for the block identified by index.
  445. * Here, X determines relevant word for the block. Y determines the actual bit in the word.
  446. *
  447. * @param[in] index Identifies the block.
  448. * @param[out] p_x Points to the word that contains the bit representing the block.
  449. * @param[out] p_y Contains the bitnumber in the the word 'X' relevant to the block.
  450. */
  451. static __INLINE void get_block_coordinates(uint32_t block_index, uint32_t * p_x, uint32_t * p_y)
  452. {
  453. // Determine position of the block in the bitmap.
  454. // X determines relevant word for the block. Y determines the actual bit in the word.
  455. const uint32_t x = block_index / BITMAP_SIZE;
  456. const uint32_t y = (block_index - x * BITMAP_SIZE);
  457. (*p_x) = x;
  458. (*p_y) = y;
  459. }
  460. /**@brief Initializes the block by setting it to be free. */
  461. static void block_init (uint32_t block_index)
  462. {
  463. uint32_t x;
  464. uint32_t y;
  465. // Determine position of the block in the bitmap.
  466. // X determines relevant word for the block. Y determines the actual bit in the word.
  467. get_block_coordinates(block_index, &x, &y);
  468. // Set bit related to the block to indicate that the block is free.
  469. SET_BIT(m_mem_pool[x], y);
  470. }
  471. /**@brief Function to get the category of the block of size 'size' or block number 'block_index'.*/
  472. static __INLINE uint32_t get_block_cat(uint32_t size, uint32_t block_index)
  473. {
  474. for (uint32_t block_cat = 0; block_cat < BLOCK_CAT_COUNT; block_cat++)
  475. {
  476. if (((size != 0) && (size <= m_block_size[block_cat]) &&
  477. (m_block_end[block_cat] != m_block_start[block_cat])) ||
  478. (block_index < m_block_end[block_cat]))
  479. {
  480. return block_cat;
  481. }
  482. }
  483. return 0;
  484. }
  485. /**@brief Function to get the size of the block number 'block_index'. */
  486. static __INLINE uint32_t get_block_size(uint32_t block_index)
  487. {
  488. const uint32_t block_cat = get_block_cat(0, block_index);
  489. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  490. p_min_size = &m_min_size[block_cat];
  491. p_max_size = &m_max_size[block_cat];
  492. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  493. return m_block_size[block_cat];
  494. }
  495. /**@brief Function to free the block identified by block number 'block_index'. */
  496. static bool is_block_free(uint32_t block_index)
  497. {
  498. uint32_t x;
  499. uint32_t y;
  500. // Determine position of the block in the bitmap.
  501. // X determines relevant word for the block. Y determines the actual bit in the word.
  502. get_block_coordinates(block_index, &x, &y);
  503. return IS_SET(m_mem_pool[x], y);
  504. }
  505. /**@brief Function to allocate the block identified by block number 'block_index'. */
  506. static void block_allocate(uint32_t block_index)
  507. {
  508. uint32_t x;
  509. uint32_t y;
  510. // Determine position of the block in the bitmap.
  511. // X determines relevant word for the block. Y determines the actual bit in the word.
  512. get_block_coordinates(block_index, &x, &y);
  513. CLR_BIT(m_mem_pool[x], y);
  514. }
  515. uint32_t nrf_mem_init(void)
  516. {
  517. NRF_LOG_DEBUG(">> %s.", (uint32_t)__func__);
  518. SDK_MUTEX_INIT(m_mm_mutex);
  519. MM_MUTEX_LOCK();
  520. uint32_t block_index = 0;
  521. for (block_index = 0; block_index < TOTAL_BLOCK_COUNT; block_index++)
  522. {
  523. block_init(block_index);
  524. }
  525. #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
  526. m_module_initialized = true;
  527. #endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK
  528. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  529. nrf_mem_diagnose();
  530. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  531. MM_MUTEX_UNLOCK();
  532. NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__);
  533. return NRF_SUCCESS;
  534. }
  535. uint32_t nrf_mem_reserve(uint8_t ** pp_buffer, uint32_t * p_size)
  536. {
  537. VERIFY_MODULE_INITIALIZED();
  538. NULL_PARAM_CHECK(pp_buffer);
  539. NULL_PARAM_CHECK(p_size);
  540. const uint32_t requested_size = (*p_size);
  541. VERIFY_REQUESTED_SIZE(requested_size);
  542. NRF_LOG_DEBUG(">> %s, size 0x%04lX.", (uint32_t)__func__, requested_size);
  543. MM_MUTEX_LOCK();
  544. const uint32_t block_cat = get_block_cat(requested_size, TOTAL_BLOCK_COUNT);
  545. uint32_t block_index = m_block_start[block_cat];
  546. uint32_t memory_index = m_block_mem_start[block_cat];
  547. uint32_t err_code = (NRF_ERROR_NO_MEM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE);
  548. NRF_LOG_DEBUG("Start index for the pool = 0x%08lX, total block count 0x%08X",
  549. block_index,
  550. TOTAL_BLOCK_COUNT);
  551. for (; block_index < TOTAL_BLOCK_COUNT; block_index++)
  552. {
  553. uint32_t block_size = get_block_size(block_index);
  554. if (is_block_free(block_index) == true)
  555. {
  556. NRF_LOG_DEBUG("Reserving block 0x%08lX", block_index);
  557. // Search succeeded, found free block.
  558. err_code = NRF_SUCCESS;
  559. // Allocate block.
  560. block_allocate(block_index);
  561. (*pp_buffer) = &m_memory[memory_index];
  562. (*p_size) = block_size;
  563. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  564. (*p_min_size) = MIN((*p_min_size), requested_size);
  565. (*p_max_size) = MAX((*p_max_size), requested_size);
  566. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  567. break;
  568. }
  569. memory_index += block_size;
  570. }
  571. if (err_code != NRF_SUCCESS)
  572. {
  573. NRF_LOG_DEBUG("Memory reservation result %d, memory %p, size %d!",
  574. err_code,
  575. (uint32_t)(*pp_buffer),
  576. (*p_size));
  577. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  578. nrf_mem_diagnose();
  579. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  580. }
  581. MM_MUTEX_UNLOCK();
  582. NRF_LOG_DEBUG("<< %s %p, result 0x%08lX.", (uint32_t)__func__,
  583. (uint32_t)(*pp_buffer), err_code);
  584. return err_code;
  585. }
  586. void * nrf_malloc(uint32_t size)
  587. {
  588. uint8_t * buffer = NULL;
  589. uint32_t allocated_size = size;
  590. uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size);
  591. if (retval != NRF_SUCCESS)
  592. {
  593. buffer = NULL;
  594. }
  595. return buffer;
  596. }
  597. void * nrf_calloc(uint32_t count, uint32_t size)
  598. {
  599. uint8_t * buffer = NULL;
  600. uint32_t allocated_size = (size * count);
  601. NRF_LOG_DEBUG("[%s]: Requested size %d, count %d", (uint32_t)__func__, allocated_size, count);
  602. uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size);
  603. if (retval == NRF_SUCCESS)
  604. {
  605. NRF_LOG_DEBUG("[%s]: buffer %p, total size %d", (uint32_t)__func__, (uint32_t)buffer, allocated_size);
  606. memset(buffer,0, allocated_size);
  607. }
  608. else
  609. {
  610. NRF_LOG_DEBUG("[%s]: Failed to allocate memory %d", (uint32_t)__func__, allocated_size);
  611. buffer = NULL;
  612. }
  613. return buffer;
  614. }
  615. void nrf_free(void * p_mem)
  616. {
  617. VERIFY_MODULE_INITIALIZED_VOID();
  618. NULL_PARAM_CHECK_VOID(p_mem);
  619. NRF_LOG_DEBUG(">> %s %p.", (uint32_t)__func__, (uint32_t)p_mem);
  620. MM_MUTEX_LOCK();
  621. uint32_t index;
  622. uint32_t memory_index = 0;
  623. for (index = 0; index < TOTAL_BLOCK_COUNT; index++)
  624. {
  625. if (&m_memory[memory_index] == p_mem)
  626. {
  627. // Found a free block of memory, assign.
  628. NRF_LOG_DEBUG("<< Freeing block %d.", index);
  629. block_init(index);
  630. break;
  631. }
  632. memory_index += get_block_size(index);
  633. }
  634. MM_MUTEX_UNLOCK();
  635. NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__);
  636. return;
  637. }
  638. void * nrf_realloc(void * p_mem, uint32_t size)
  639. {
  640. return p_mem;
  641. }
  642. #ifdef MEM_MANAGER_ENABLE_DIAGNOSTICS
  643. /**@brief Function to format and print information with respect to each block.
  644. *
  645. * @details Internal function that formats and prints information related to the block category
  646. * identified by 'block_cat'. This function also appends the number of bytes in use to
  647. * p_mem_in_use based on current count of block in the category.
  648. *
  649. * @param[in] block_cat Identifies the category of block.
  650. * @param[out] p_mem_in_use Updates the memory in use based on count in use.
  651. */
  652. void print_block_info(uint32_t block_cat, uint32_t * p_mem_in_use)
  653. {
  654. #define PRINT_COLUMN_WIDTH 13
  655. #define PRINT_BUFFER_SIZE 80
  656. #define ASCII_VALUE_FOR_SPACE 32
  657. char print_buffer[PRINT_BUFFER_SIZE];
  658. const uint32_t total_count = (m_block_start[block_cat] + m_block_count[block_cat]);
  659. uint32_t in_use = 0;
  660. uint32_t num_of_blocks = 0;
  661. uint32_t index = m_block_start[block_cat];
  662. uint32_t column_number;
  663. // No statistic provided in case block category is not included.
  664. if (m_block_count[block_cat] != 0)
  665. {
  666. memset(print_buffer, ASCII_VALUE_FOR_SPACE, PRINT_BUFFER_SIZE);
  667. for (; index < total_count; index++)
  668. {
  669. if (is_block_free(index) == false)
  670. {
  671. num_of_blocks++;
  672. in_use += m_block_size[block_cat];
  673. }
  674. }
  675. column_number = 0;
  676. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  677. PRINT_COLUMN_WIDTH,
  678. "| %s",
  679. m_block_desc_str[block_cat]);
  680. column_number++;
  681. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  682. PRINT_COLUMN_WIDTH,
  683. "| %d",
  684. m_block_size[block_cat]);
  685. column_number++;
  686. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  687. PRINT_COLUMN_WIDTH,
  688. "| %d",
  689. m_block_count[block_cat]);
  690. column_number++;
  691. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  692. PRINT_COLUMN_WIDTH,
  693. "| %d",
  694. num_of_blocks);
  695. column_number++;
  696. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  697. PRINT_COLUMN_WIDTH,
  698. "| %d",
  699. m_min_size[block_cat]);
  700. column_number++;
  701. snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
  702. PRINT_COLUMN_WIDTH,
  703. "| %d",
  704. m_max_size[block_cat]);
  705. column_number++;
  706. const uint32_t column_end = (column_number * PRINT_COLUMN_WIDTH);
  707. for (int j = 0; j < column_end; j ++)
  708. {
  709. if (print_buffer[j] == 0)
  710. {
  711. print_buffer[j] = 0x20;
  712. }
  713. }
  714. snprintf(&print_buffer[column_end], 2, "|");
  715. NRF_LOG_BYTES_DEBUG(print_buffer, strlen(print_buffer));
  716. (*p_mem_in_use) += in_use;
  717. }
  718. }
  719. void nrf_mem_diagnose(void)
  720. {
  721. uint32_t in_use = 0;
  722. NRF_LOG_DEBUG("");
  723. NRF_LOG_DEBUG("+------------+------------+------------+------------+------------+------------+");
  724. NRF_LOG_DEBUG("| Block | Size | Total | In Use | Min Alloc | Max Alloc |");
  725. NRF_LOG_DEBUG("+------------+------------+------------+------------+------------+------------+");
  726. print_block_info(BLOCK_CAT_XXS, &in_use);
  727. print_block_info(BLOCK_CAT_XS, &in_use);
  728. print_block_info(BLOCK_CAT_SMALL, &in_use);
  729. print_block_info(BLOCK_CAT_MEDIUM, &in_use);
  730. print_block_info(BLOCK_CAT_LARGE, &in_use);
  731. print_block_info(BLOCK_CAT_XL, &in_use);
  732. print_block_info(BLOCK_CAT_XXL, &in_use);
  733. NRF_LOG_DEBUG("+------------+------------+------------+------------+------------+------------+");
  734. NRF_LOG_DEBUG("| Total | %d | %d | %d",
  735. TOTAL_MEMORY_SIZE, TOTAL_BLOCK_COUNT,in_use);
  736. NRF_LOG_DEBUG("+------------+------------+------------+------------+------------+------------+");
  737. }
  738. #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
  739. /** @} */
  740. #endif //NRF_MODULE_ENABLED(MEM_MANAGER)