mem_manager.c 36 KB

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