mem_manager.c 34 KB

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