lib_mem.c 116 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842
  1. /*
  2. *********************************************************************************************************
  3. * uC/LIB
  4. * CUSTOM LIBRARY MODULES
  5. *
  6. * (c) Copyright 2004-2014; Micrium, Inc.; Weston, FL
  7. *
  8. * All rights reserved. Protected by international copyright laws.
  9. *
  10. * uC/LIB is provided in source form to registered licensees ONLY. It is
  11. * illegal to distribute this source code to any third party unless you receive
  12. * written permission by an authorized Micrium representative. Knowledge of
  13. * the source code may NOT be used to develop a similar product.
  14. *
  15. * Please help us continue to provide the Embedded community with the finest
  16. * software available. Your honesty is greatly appreciated.
  17. *
  18. * You can find our product's user manual, API reference, release notes and
  19. * more information at: https://doc.micrium.com
  20. *
  21. * You can contact us at: http://www.micrium.com
  22. *********************************************************************************************************
  23. */
  24. /*
  25. *********************************************************************************************************
  26. *
  27. * STANDARD MEMORY OPERATIONS
  28. *
  29. * Filename : lib_mem.c
  30. * Version : V1.38.01
  31. * Programmer(s) : ITJ
  32. * FGK
  33. * JFD
  34. * FBJ
  35. * EJ
  36. *********************************************************************************************************
  37. * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
  38. *
  39. * (a) ALL standard library functions are implemented in the custom library modules :
  40. *
  41. * (1) \<Custom Library Directory>\lib_*.*
  42. *
  43. * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
  44. *
  45. * where
  46. * <Custom Library Directory> directory path for custom library software
  47. * <cpu> directory name for specific processor (CPU)
  48. * <compiler> directory name for specific compiler
  49. *
  50. * (b) Product-specific library functions are implemented in individual products.
  51. *********************************************************************************************************
  52. */
  53. /*
  54. *********************************************************************************************************
  55. * INCLUDE FILES
  56. *********************************************************************************************************
  57. */
  58. #define MICRIUM_SOURCE
  59. #define LIB_MEM_MODULE
  60. #include "lib_mem.h"
  61. #include "lib_math.h"
  62. #include "lib_str.h"
  63. /*
  64. *********************************************************************************************************
  65. * LOCAL DEFINES
  66. *********************************************************************************************************
  67. */
  68. /*
  69. *********************************************************************************************************
  70. * LOCAL CONSTANTS
  71. *********************************************************************************************************
  72. */
  73. /*
  74. *********************************************************************************************************
  75. * LOCAL DATA TYPES
  76. *********************************************************************************************************
  77. */
  78. /*
  79. *********************************************************************************************************
  80. * LOCAL TABLES
  81. *********************************************************************************************************
  82. */
  83. /*
  84. *********************************************************************************************************
  85. * LOCAL GLOBAL VARIABLES
  86. *********************************************************************************************************
  87. */
  88. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  89. #ifndef LIB_MEM_CFG_HEAP_BASE_ADDR
  90. CPU_INT08U Mem_Heap[LIB_MEM_CFG_HEAP_SIZE]; /* Mem heap. */
  91. #endif
  92. MEM_SEG Mem_SegHeap; /* Heap mem seg. */
  93. #endif
  94. MEM_SEG *Mem_SegHeadPtr; /* Ptr to head of seg list. */
  95. /*
  96. *********************************************************************************************************
  97. * LOCAL FUNCTION PROTOTYPES
  98. *********************************************************************************************************
  99. */
  100. static void Mem_SegCreateCritical (const CPU_CHAR *p_name,
  101. MEM_SEG *p_seg,
  102. CPU_ADDR seg_base_addr,
  103. CPU_SIZE_T padding_align,
  104. CPU_SIZE_T size);
  105. static MEM_SEG *Mem_SegOverlapChkCritical( CPU_ADDR seg_base_addr,
  106. CPU_SIZE_T size,
  107. LIB_ERR *p_err);
  108. static void *Mem_SegAllocInternal (const CPU_CHAR *p_name,
  109. MEM_SEG *p_seg,
  110. CPU_SIZE_T size,
  111. CPU_SIZE_T align,
  112. CPU_SIZE_T padding_align,
  113. CPU_SIZE_T *p_bytes_reqd,
  114. LIB_ERR *p_err);
  115. static void *Mem_SegAllocExtCritical ( MEM_SEG *p_seg,
  116. CPU_SIZE_T size,
  117. CPU_SIZE_T align,
  118. CPU_SIZE_T padding_align,
  119. CPU_SIZE_T *p_bytes_reqd,
  120. LIB_ERR *p_err);
  121. static void Mem_DynPoolCreateInternal(const CPU_CHAR *p_name,
  122. MEM_DYN_POOL *p_pool,
  123. MEM_SEG *p_seg,
  124. CPU_SIZE_T blk_size,
  125. CPU_SIZE_T blk_align,
  126. CPU_SIZE_T blk_padding_align,
  127. CPU_SIZE_T blk_qty_init,
  128. CPU_SIZE_T blk_qty_max,
  129. LIB_ERR *p_err);
  130. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  131. static void Mem_SegAllocTrackCritical(const CPU_CHAR *p_name,
  132. MEM_SEG *p_seg,
  133. CPU_SIZE_T size,
  134. LIB_ERR *p_err);
  135. #endif
  136. #if ((LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) && \
  137. (LIB_MEM_CFG_HEAP_SIZE > 0u))
  138. static CPU_BOOLEAN Mem_PoolBlkIsValidAddr ( MEM_POOL *p_pool,
  139. void *p_mem);
  140. #endif
  141. /*
  142. *********************************************************************************************************
  143. * LOCAL CONFIGURATION ERRORS
  144. *********************************************************************************************************
  145. */
  146. /*
  147. *********************************************************************************************************
  148. *********************************************************************************************************
  149. * GLOBAL FUNCTIONS
  150. *********************************************************************************************************
  151. *********************************************************************************************************
  152. */
  153. /*
  154. *********************************************************************************************************
  155. * Mem_Init()
  156. *
  157. * Description : (1) Initializes Memory Management Module :
  158. *
  159. * (a) Initialize heap memory pool
  160. * (b) Initialize memory pool table
  161. *
  162. *
  163. * Argument(s) : none.
  164. *
  165. * Return(s) : none.
  166. *
  167. * Caller(s) : Application.
  168. *
  169. * Note(s) : (2) Mem_Init() MUST be called ... :
  170. *
  171. * (a) ONLY ONCE from a product's application; ...
  172. * (b) BEFORE product's application calls any memory library module function(s)
  173. *********************************************************************************************************
  174. */
  175. void Mem_Init (void)
  176. {
  177. /* ------------------ INIT SEG LIST ------------------- */
  178. Mem_SegHeadPtr = DEF_NULL;
  179. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  180. {
  181. LIB_ERR err;
  182. CPU_ADDR heap_base_addr;
  183. /* ------------------ INIT HEAP SEG ------------------- */
  184. #ifdef LIB_MEM_CFG_HEAP_BASE_ADDR
  185. heap_base_addr = LIB_MEM_CFG_HEAP_BASE_ADDR;
  186. #else
  187. heap_base_addr = (CPU_ADDR)&Mem_Heap[0u];
  188. #endif
  189. Mem_SegCreate("Heap",
  190. &Mem_SegHeap, /* Create heap seg. */
  191. heap_base_addr,
  192. LIB_MEM_CFG_HEAP_SIZE,
  193. LIB_MEM_PADDING_ALIGN_NONE,
  194. &err);
  195. if (err != LIB_MEM_ERR_NONE) {
  196. CPU_SW_EXCEPTION(;);
  197. }
  198. }
  199. #endif
  200. }
  201. /*
  202. *********************************************************************************************************
  203. * Mem_Clr()
  204. *
  205. * Description : Clears data buffer (see Note #2).
  206. *
  207. * Argument(s) : pmem Pointer to memory buffer to clear.
  208. *
  209. * size Number of data buffer octets to clear (see Note #1).
  210. *
  211. * Return(s) : none.
  212. *
  213. * Caller(s) : Application.
  214. *
  215. * Note(s) : (1) Null clears allowed (i.e. zero-length clears).
  216. *
  217. * See also 'Mem_Set() Note #1'.
  218. *
  219. * (2) Clear data by setting each data octet to 0.
  220. *********************************************************************************************************
  221. */
  222. void Mem_Clr (void *pmem,
  223. CPU_SIZE_T size)
  224. {
  225. Mem_Set(pmem,
  226. 0u, /* See Note #2. */
  227. size);
  228. }
  229. /*
  230. *********************************************************************************************************
  231. * Mem_Set()
  232. *
  233. * Description : Fills data buffer with specified data octet.
  234. *
  235. * Argument(s) : pmem Pointer to memory buffer to fill with specified data octet.
  236. *
  237. * data_val Data fill octet value.
  238. *
  239. * size Number of data buffer octets to fill (see Note #1).
  240. *
  241. * Return(s) : none.
  242. *
  243. * Caller(s) : Application.
  244. *
  245. * Note(s) : (1) Null sets allowed (i.e. zero-length sets).
  246. *
  247. * (2) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data
  248. * words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
  249. * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
  250. * addresses.
  251. *
  252. * (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
  253. * address boundary.
  254. *
  255. * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus
  256. * address values MUST be cast to an appropriately-sized integer value PRIOR to any
  257. * 'mem_align_mod' arithmetic operation.
  258. *********************************************************************************************************
  259. */
  260. void Mem_Set (void *pmem,
  261. CPU_INT08U data_val,
  262. CPU_SIZE_T size)
  263. {
  264. CPU_SIZE_T size_rem;
  265. CPU_ALIGN data_align;
  266. CPU_ALIGN *pmem_align;
  267. CPU_INT08U *pmem_08;
  268. CPU_DATA mem_align_mod;
  269. CPU_DATA i;
  270. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  271. if (size < 1) { /* See Note #1. */
  272. return;
  273. }
  274. if (pmem == (void *)0) {
  275. return;
  276. }
  277. #endif
  278. data_align = 0u;
  279. for (i = 0u; i < sizeof(CPU_ALIGN); i++) { /* Fill each data_align octet with data val. */
  280. data_align <<= DEF_OCTET_NBR_BITS;
  281. data_align |= (CPU_ALIGN)data_val;
  282. }
  283. size_rem = size;
  284. mem_align_mod = (CPU_INT08U)((CPU_ADDR)pmem % sizeof(CPU_ALIGN)); /* See Note #3. */
  285. pmem_08 = (CPU_INT08U *)pmem;
  286. if (mem_align_mod != 0u) { /* If leading octets avail, ... */
  287. i = mem_align_mod;
  288. while ((size_rem > 0) && /* ... start mem buf fill with leading octets ... */
  289. (i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
  290. *pmem_08++ = data_val;
  291. size_rem -= sizeof(CPU_INT08U);
  292. i++;
  293. }
  294. }
  295. pmem_align = (CPU_ALIGN *)pmem_08; /* See Note #2. */
  296. while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem buf aligned on CPU_ALIGN word boundaries, */
  297. *pmem_align++ = data_align; /* ... fill mem buf with CPU_ALIGN-sized data. */
  298. size_rem -= sizeof(CPU_ALIGN);
  299. }
  300. pmem_08 = (CPU_INT08U *)pmem_align;
  301. while (size_rem > 0) { /* Finish mem buf fill with trailing octets. */
  302. *pmem_08++ = data_val;
  303. size_rem -= sizeof(CPU_INT08U);
  304. }
  305. }
  306. /*
  307. *********************************************************************************************************
  308. * Mem_Copy()
  309. *
  310. * Description : Copies data octets from one memory buffer to another memory buffer.
  311. *
  312. * Argument(s) : pdest Pointer to destination memory buffer.
  313. *
  314. * psrc Pointer to source memory buffer.
  315. *
  316. * size Number of octets to copy (see Note #1).
  317. *
  318. * Return(s) : none.
  319. *
  320. * Caller(s) : Application.
  321. *
  322. * Note(s) : (1) Null copies allowed (i.e. zero-length copies).
  323. *
  324. * (2) Memory buffers NOT checked for overlapping.
  325. *
  326. * (a) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that "if
  327. * copying takes place between objects that overlap, the behavior is undefined".
  328. *
  329. * (b) However, data octets from a source memory buffer at a higher address value SHOULD
  330. * successfully copy to a destination memory buffer at a lower address value even
  331. * if any octets of the memory buffers overlap as long as no individual, atomic CPU
  332. * word copy overlaps.
  333. *
  334. * Since Mem_Copy() performs the data octet copy via 'CPU_ALIGN'-sized words &/or
  335. * octets; & since 'CPU_ALIGN'-sized words MUST be accessed on word-aligned addresses
  336. * (see Note #3b), neither 'CPU_ALIGN'-sized words nor octets at unique addresses can
  337. * ever overlap.
  338. *
  339. * Therefore, Mem_Copy() SHOULD be able to successfully copy overlapping memory
  340. * buffers as long as the source memory buffer is at a higher address value than the
  341. * destination memory buffer.
  342. *
  343. * (3) For best CPU performance, optimized to copy data buffer using 'CPU_ALIGN'-sized data
  344. * words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
  345. * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
  346. * addresses.
  347. *
  348. * (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
  349. * address boundary.
  350. *
  351. * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus
  352. * address values MUST be cast to an appropriately-sized integer value PRIOR to any
  353. * 'mem_align_mod' arithmetic operation.
  354. *********************************************************************************************************
  355. */
  356. #if (LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED)
  357. void Mem_Copy ( void *pdest,
  358. const void *psrc,
  359. CPU_SIZE_T size)
  360. {
  361. CPU_SIZE_T size_rem;
  362. CPU_SIZE_T mem_gap_octets;
  363. CPU_ALIGN *pmem_align_dest;
  364. const CPU_ALIGN *pmem_align_src;
  365. CPU_INT08U *pmem_08_dest;
  366. const CPU_INT08U *pmem_08_src;
  367. CPU_DATA i;
  368. CPU_DATA mem_align_mod_dest;
  369. CPU_DATA mem_align_mod_src;
  370. CPU_BOOLEAN mem_aligned;
  371. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  372. if (size < 1) { /* See Note #1. */
  373. return;
  374. }
  375. if (pdest == (void *)0) {
  376. return;
  377. }
  378. if (psrc == (void *)0) {
  379. return;
  380. }
  381. #endif
  382. size_rem = size;
  383. pmem_08_dest = ( CPU_INT08U *)pdest;
  384. pmem_08_src = (const CPU_INT08U *)psrc;
  385. mem_gap_octets = pmem_08_src - pmem_08_dest;
  386. if (mem_gap_octets >= sizeof(CPU_ALIGN)) { /* Avoid bufs overlap. */
  387. /* See Note #4. */
  388. mem_align_mod_dest = (CPU_INT08U)((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
  389. mem_align_mod_src = (CPU_INT08U)((CPU_ADDR)pmem_08_src % sizeof(CPU_ALIGN));
  390. mem_aligned = (mem_align_mod_dest == mem_align_mod_src) ? DEF_YES : DEF_NO;
  391. if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
  392. /* ... optimize copy for mem buf alignment. */
  393. if (mem_align_mod_dest != 0u) { /* If leading octets avail, ... */
  394. i = mem_align_mod_dest;
  395. while ((size_rem > 0) && /* ... start mem buf copy with leading octets ... */
  396. (i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
  397. *pmem_08_dest++ = *pmem_08_src++;
  398. size_rem -= sizeof(CPU_INT08U);
  399. i++;
  400. }
  401. }
  402. pmem_align_dest = ( CPU_ALIGN *)pmem_08_dest; /* See Note #3. */
  403. pmem_align_src = (const CPU_ALIGN *)pmem_08_src;
  404. while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem bufs aligned on CPU_ALIGN word boundaries, */
  405. *pmem_align_dest++ = *pmem_align_src++; /* ... copy psrc to pdest with CPU_ALIGN-sized words. */
  406. size_rem -= sizeof(CPU_ALIGN);
  407. }
  408. pmem_08_dest = ( CPU_INT08U *)pmem_align_dest;
  409. pmem_08_src = (const CPU_INT08U *)pmem_align_src;
  410. }
  411. }
  412. while (size_rem > 0) { /* For unaligned mem bufs or trailing octets, ... */
  413. *pmem_08_dest++ = *pmem_08_src++; /* ... copy psrc to pdest by octets. */
  414. size_rem -= sizeof(CPU_INT08U);
  415. }
  416. }
  417. #endif
  418. /*
  419. *********************************************************************************************************
  420. * Mem_Move()
  421. *
  422. * Description : Moves data octets from one memory buffer to another memory buffer, or within the same
  423. * memory buffer. Overlapping is correctly handled for all move operations.
  424. *
  425. * Argument(s) : pdest Pointer to destination memory buffer.
  426. *
  427. * psrc Pointer to source memory buffer.
  428. *
  429. * size Number of octets to move (see Note #1).
  430. *
  431. * Return(s) : none.
  432. *
  433. * Caller(s) : Application.
  434. *
  435. * Note(s) : (1) Null move operations allowed (i.e. zero-length).
  436. *
  437. * (2) Memory buffers checked for overlapping.
  438. *
  439. * (3) For best CPU performance, optimized to copy data buffer using 'CPU_ALIGN'-sized data
  440. * words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
  441. * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
  442. * addresses.
  443. *
  444. * (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
  445. * address boundary.
  446. *
  447. * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus
  448. * address values MUST be cast to an appropriately-sized integer value PRIOR to any
  449. * 'mem_align_mod' arithmetic operation.
  450. *********************************************************************************************************
  451. */
  452. void Mem_Move ( void *pdest,
  453. const void *psrc,
  454. CPU_SIZE_T size)
  455. {
  456. CPU_SIZE_T size_rem;
  457. CPU_SIZE_T mem_gap_octets;
  458. CPU_ALIGN *pmem_align_dest;
  459. const CPU_ALIGN *pmem_align_src;
  460. CPU_INT08U *pmem_08_dest;
  461. const CPU_INT08U *pmem_08_src;
  462. CPU_INT08S i;
  463. CPU_DATA mem_align_mod_dest;
  464. CPU_DATA mem_align_mod_src;
  465. CPU_BOOLEAN mem_aligned;
  466. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  467. if (size < 1) {
  468. return;
  469. }
  470. if (pdest == (void *)0) {
  471. return;
  472. }
  473. if (psrc == (void *)0) {
  474. return;
  475. }
  476. #endif
  477. pmem_08_src = (const CPU_INT08U *)psrc;
  478. pmem_08_dest = ( CPU_INT08U *)pdest;
  479. if (pmem_08_src > pmem_08_dest) {
  480. Mem_Copy(pdest, psrc, size);
  481. return;
  482. }
  483. size_rem = size;
  484. pmem_08_dest = ( CPU_INT08U *)pdest + size - 1;
  485. pmem_08_src = (const CPU_INT08U *)psrc + size - 1;
  486. mem_gap_octets = pmem_08_dest - pmem_08_src;
  487. if (mem_gap_octets >= sizeof(CPU_ALIGN)) { /* Avoid bufs overlap. */
  488. /* See Note #4. */
  489. mem_align_mod_dest = (CPU_INT08U)((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
  490. mem_align_mod_src = (CPU_INT08U)((CPU_ADDR)pmem_08_src % sizeof(CPU_ALIGN));
  491. mem_aligned = (mem_align_mod_dest == mem_align_mod_src) ? DEF_YES : DEF_NO;
  492. if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
  493. /* ... optimize copy for mem buf alignment. */
  494. if (mem_align_mod_dest != (sizeof(CPU_ALIGN) - 1)) {/* If leading octets avail, ... */
  495. i = mem_align_mod_dest;
  496. while ((size_rem > 0) && /* ... start mem buf copy with leading octets ... */
  497. (i >= 0)) { /* ... until next CPU_ALIGN word boundary. */
  498. *pmem_08_dest-- = *pmem_08_src--;
  499. size_rem -= sizeof(CPU_INT08U);
  500. i--;
  501. }
  502. }
  503. /* See Note #3. */
  504. pmem_align_dest = ( CPU_ALIGN *)((CPU_INT08U *)pmem_08_dest - sizeof(CPU_ALIGN) + 1);
  505. pmem_align_src = (const CPU_ALIGN *)((CPU_INT08U *)pmem_08_src - sizeof(CPU_ALIGN) + 1);
  506. while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem bufs aligned on CPU_ALIGN word boundaries, */
  507. *pmem_align_dest-- = *pmem_align_src--; /* ... copy psrc to pdest with CPU_ALIGN-sized words. */
  508. size_rem -= sizeof(CPU_ALIGN);
  509. }
  510. pmem_08_dest = ( CPU_INT08U *)pmem_align_dest + sizeof(CPU_ALIGN) - 1;
  511. pmem_08_src = (const CPU_INT08U *)pmem_align_src + sizeof(CPU_ALIGN) - 1;
  512. }
  513. }
  514. while (size_rem > 0) { /* For unaligned mem bufs or trailing octets, ... */
  515. *pmem_08_dest-- = *pmem_08_src--; /* ... copy psrc to pdest by octets. */
  516. size_rem -= sizeof(CPU_INT08U);
  517. }
  518. }
  519. /*
  520. *********************************************************************************************************
  521. * Mem_Cmp()
  522. *
  523. * Description : Verifies that ALL data octets in two memory buffers are identical in sequence.
  524. *
  525. * Argument(s) : p1_mem Pointer to first memory buffer.
  526. *
  527. * p2_mem Pointer to second memory buffer.
  528. *
  529. * size Number of data buffer octets to compare (see Note #1).
  530. *
  531. * Return(s) : DEF_YES, if 'size' number of data octets are identical in both memory buffers.
  532. *
  533. * DEF_NO, otherwise.
  534. *
  535. * Caller(s) : Application.
  536. *
  537. * Note(s) : (1) Null compares allowed (i.e. zero-length compares); 'DEF_YES' returned to indicate
  538. * identical null compare.
  539. *
  540. * (2) Many memory buffer comparisons vary ONLY in the least significant octets -- e.g.
  541. * network address buffers. Consequently, memory buffer comparison is more efficient
  542. * if the comparison starts from the end of the memory buffers which will abort sooner
  543. * on dissimilar memory buffers that vary only in the least significant octets.
  544. *
  545. * (3) For best CPU performance, optimized to compare data buffers using 'CPU_ALIGN'-sized
  546. * data words. Since many word-aligned processors REQUIRE that multi-octet words be accessed on
  547. * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
  548. * addresses.
  549. *
  550. * (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
  551. * address boundary.
  552. *
  553. * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus
  554. * address values MUST be cast to an appropriately-sized integer value PRIOR to any
  555. * 'mem_align_mod' arithmetic operation.
  556. *********************************************************************************************************
  557. */
  558. CPU_BOOLEAN Mem_Cmp (const void *p1_mem,
  559. const void *p2_mem,
  560. CPU_SIZE_T size)
  561. {
  562. CPU_SIZE_T size_rem;
  563. CPU_ALIGN *p1_mem_align;
  564. CPU_ALIGN *p2_mem_align;
  565. const CPU_INT08U *p1_mem_08;
  566. const CPU_INT08U *p2_mem_08;
  567. CPU_DATA i;
  568. CPU_DATA mem_align_mod_1;
  569. CPU_DATA mem_align_mod_2;
  570. CPU_BOOLEAN mem_aligned;
  571. CPU_BOOLEAN mem_cmp;
  572. if (size < 1) { /* See Note #1. */
  573. return (DEF_YES);
  574. }
  575. if (p1_mem == (void *)0) {
  576. return (DEF_NO);
  577. }
  578. if (p2_mem == (void *)0) {
  579. return (DEF_NO);
  580. }
  581. mem_cmp = DEF_YES; /* Assume mem bufs are identical until cmp fails. */
  582. size_rem = size;
  583. /* Start @ end of mem bufs (see Note #2). */
  584. p1_mem_08 = (const CPU_INT08U *)p1_mem + size;
  585. p2_mem_08 = (const CPU_INT08U *)p2_mem + size;
  586. /* See Note #4. */
  587. mem_align_mod_1 = (CPU_INT08U)((CPU_ADDR)p1_mem_08 % sizeof(CPU_ALIGN));
  588. mem_align_mod_2 = (CPU_INT08U)((CPU_ADDR)p2_mem_08 % sizeof(CPU_ALIGN));
  589. mem_aligned = (mem_align_mod_1 == mem_align_mod_2) ? DEF_YES : DEF_NO;
  590. if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
  591. /* ... optimize cmp for mem buf alignment. */
  592. if (mem_align_mod_1 != 0u) { /* If trailing octets avail, ... */
  593. i = mem_align_mod_1;
  594. while ((mem_cmp == DEF_YES) && /* ... cmp mem bufs while identical & ... */
  595. (size_rem > 0) && /* ... start mem buf cmp with trailing octets ... */
  596. (i > 0)) { /* ... until next CPU_ALIGN word boundary. */
  597. p1_mem_08--;
  598. p2_mem_08--;
  599. if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
  600. mem_cmp = DEF_NO;
  601. }
  602. size_rem -= sizeof(CPU_INT08U);
  603. i--;
  604. }
  605. }
  606. if (mem_cmp == DEF_YES) { /* If cmp still identical, cmp aligned mem bufs. */
  607. p1_mem_align = (CPU_ALIGN *)p1_mem_08; /* See Note #3. */
  608. p2_mem_align = (CPU_ALIGN *)p2_mem_08;
  609. while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical & ... */
  610. (size_rem >= sizeof(CPU_ALIGN))) { /* ... mem bufs aligned on CPU_ALIGN word boundaries. */
  611. p1_mem_align--;
  612. p2_mem_align--;
  613. if (*p1_mem_align != *p2_mem_align) { /* If ANY data octet(s) NOT identical, cmp fails. */
  614. mem_cmp = DEF_NO;
  615. }
  616. size_rem -= sizeof(CPU_ALIGN);
  617. }
  618. p1_mem_08 = (CPU_INT08U *)p1_mem_align;
  619. p2_mem_08 = (CPU_INT08U *)p2_mem_align;
  620. }
  621. }
  622. while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical ... */
  623. (size_rem > 0)) { /* ... for unaligned mem bufs or trailing octets. */
  624. p1_mem_08--;
  625. p2_mem_08--;
  626. if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
  627. mem_cmp = DEF_NO;
  628. }
  629. size_rem -= sizeof(CPU_INT08U);
  630. }
  631. return (mem_cmp);
  632. }
  633. /*
  634. *********************************************************************************************************
  635. * Mem_HeapAlloc()
  636. *
  637. * Description : Allocates a memory block from the heap memory segment.
  638. *
  639. * Argument(s) : size Size of memory block to allocate (in bytes).
  640. *
  641. * align Alignment of memory block to specific word boundary (in bytes).
  642. *
  643. * p_bytes_reqd Optional pointer to a variable to ... :
  644. *
  645. * (a) Return the number of bytes required to successfully
  646. * allocate the memory block, if any error(s);
  647. * (b) Return 0, otherwise.
  648. *
  649. * p_err Pointer to variable that will receive the return error code from this function :
  650. *
  651. * LIB_MEM_ERR_NONE Operation was successful.
  652. * LIB_MEM_ERR_HEAP_EMPTY No more memory available on heap.
  653. *
  654. * ---------------------RETURNED BY Mem_SegAllocInternal()---------------------
  655. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  656. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  657. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  658. *
  659. * Return(s) : Pointer to memory block, if NO error(s).
  660. *
  661. * Pointer to NULL, otherwise.
  662. *
  663. * Caller(s) : Application.
  664. *
  665. * Note(s) : (1) Pointers to variables that return values MUST be initialized PRIOR to all other
  666. * validation or function handling in case of any error(s).
  667. *
  668. * (2) This function is DEPRECATED and will be removed in a future version of this product.
  669. * Mem_SegAlloc(), Mem_SegAllocExt() or Mem_SegAllocHW() should be used instead.
  670. *********************************************************************************************************
  671. */
  672. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  673. void *Mem_HeapAlloc (CPU_SIZE_T size,
  674. CPU_SIZE_T align,
  675. CPU_SIZE_T *p_bytes_reqd,
  676. LIB_ERR *p_err)
  677. {
  678. void *p_mem;
  679. p_mem = Mem_SegAllocInternal(DEF_NULL,
  680. &Mem_SegHeap,
  681. size,
  682. align,
  683. LIB_MEM_CFG_HEAP_PADDING_ALIGN,
  684. p_bytes_reqd,
  685. p_err);
  686. if (*p_err == LIB_MEM_ERR_SEG_OVF) {
  687. *p_err = LIB_MEM_ERR_HEAP_OVF;
  688. }
  689. return (p_mem);
  690. }
  691. #endif
  692. /*
  693. *********************************************************************************************************
  694. * Mem_HeapGetSizeRem()
  695. *
  696. * Description : Gets remaining heap memory size available to allocate.
  697. *
  698. * Argument(s) : align Desired word boundary alignment (in bytes) to return remaining memory size from.
  699. *
  700. * p_err Pointer to variable that will receive the return error code from this function
  701. *
  702. * LIB_MEM_ERR_NONE Operation was successful.
  703. *
  704. * --------------------RETURNED BY Mem_SegRemSizeGet()--------------------
  705. * LIB_MEM_ERR_NULL_PTR Segment data pointer NULL.
  706. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory alignment.
  707. *
  708. * Return(s) : Remaining heap memory size (in bytes), if NO error(s).
  709. *
  710. * 0, otherwise.
  711. *
  712. * Caller(s) : Application.
  713. *
  714. * Note(s) : (1) This function is DEPRECATED and will be removed in a future version of this product.
  715. * Mem_SegRemSizeGet() should be used instead.
  716. *********************************************************************************************************
  717. */
  718. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  719. CPU_SIZE_T Mem_HeapGetSizeRem (CPU_SIZE_T align,
  720. LIB_ERR *p_err)
  721. {
  722. CPU_SIZE_T rem_size;
  723. rem_size = Mem_SegRemSizeGet(&Mem_SegHeap,
  724. align,
  725. DEF_NULL,
  726. p_err);
  727. if (*p_err != LIB_MEM_ERR_NONE) {
  728. return (0u);
  729. }
  730. return (rem_size);
  731. }
  732. #endif
  733. /*
  734. *********************************************************************************************************
  735. * Mem_SegCreate()
  736. *
  737. * Description : Creates a new memory segment to be used for runtime memory allocation.
  738. *
  739. * Argument(s) : p_name Pointer to segment name.
  740. *
  741. * p_seg Pointer to segment data. Must be allocated by caller.
  742. *
  743. * seg_base_addr Address of segment's first byte.
  744. *
  745. * size Total size of segment, in bytes.
  746. *
  747. * padding_align Padding alignment, in bytes, that will be added to any allocated buffer from
  748. * this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
  749. * means no padding.
  750. *
  751. * p_err Pointer to variable that will receive the return error code from this function :
  752. *
  753. * LIB_MEM_ERR_NONE Operation was successful.
  754. * LIB_MEM_ERR_INVALID_SEG_SIZE Invalid segment size specified.
  755. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid padding alignment.
  756. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  757. *
  758. * -------------------RETURNED BY Mem_SegOverlapChkCritical()-------------------
  759. * LIB_MEM_ERR_INVALID_SEG_OVERLAP Segment overlaps another existing segment.
  760. * LIB_MEM_ERR_INVALID_SEG_EXISTS Segment already exists.
  761. *
  762. * Return(s) : None.
  763. *
  764. * Caller(s) : Application.
  765. *
  766. * Note(s) : (1) New segments are checked for overlap with existing segments. A critical section needs
  767. * to be maintained during the whole list search and add procedure to prevent a reentrant
  768. * call from creating another segment overlapping with the one being added.
  769. *********************************************************************************************************
  770. */
  771. void Mem_SegCreate (const CPU_CHAR *p_name,
  772. MEM_SEG *p_seg,
  773. CPU_ADDR seg_base_addr,
  774. CPU_SIZE_T size,
  775. CPU_SIZE_T padding_align,
  776. LIB_ERR *p_err)
  777. {
  778. CPU_SR_ALLOC();
  779. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  780. if (p_err == DEF_NULL) { /* Chk for null err ptr. */
  781. CPU_SW_EXCEPTION(;);
  782. }
  783. if (p_seg == DEF_NULL) { /* Chk for null seg ptr. */
  784. *p_err = LIB_MEM_ERR_NULL_PTR;
  785. return;
  786. }
  787. if (size < 1u) { /* Chk for invalid sized seg. */
  788. *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
  789. return;
  790. }
  791. /* Chk for addr space ovf. */
  792. if (seg_base_addr + (size - 1u) < seg_base_addr) {
  793. *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
  794. return;
  795. }
  796. if ((padding_align != LIB_MEM_PADDING_ALIGN_NONE) &&
  797. (MATH_IS_PWR2(padding_align) != DEF_YES)) {
  798. *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
  799. return;
  800. }
  801. #endif
  802. CPU_CRITICAL_ENTER();
  803. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  804. (void)Mem_SegOverlapChkCritical(seg_base_addr, /* Chk for overlap. */
  805. size,
  806. p_err);
  807. if (*p_err != LIB_MEM_ERR_NONE) {
  808. CPU_CRITICAL_EXIT();
  809. return;
  810. }
  811. #endif
  812. Mem_SegCreateCritical(p_name, /* Create seg. */
  813. p_seg,
  814. seg_base_addr,
  815. padding_align,
  816. size);
  817. CPU_CRITICAL_EXIT();
  818. *p_err = LIB_MEM_ERR_NONE;
  819. }
  820. /*
  821. *********************************************************************************************************
  822. * Mem_SegClr()
  823. *
  824. * Description : Clears a memory segment.
  825. *
  826. * Argument(s) : p_seg Pointer to segment data. Must be allocated by caller.
  827. *
  828. * p_err Pointer to variable that will receive the return error code from this function :
  829. *
  830. * LIB_MEM_ERR_NONE Operation was successful.
  831. * LIB_MEM_ERR_NULL_PTR Segment data pointer NULL.
  832. *
  833. * Return(s) : None.
  834. *
  835. * Caller(s) : Application.
  836. *
  837. * Note(s) : (1) This function must be used with extreme caution. It must only be called on memory
  838. * segments that are no longer used.
  839. *
  840. * (2) This function is disabled when debug mode is enabled to avoid heap memory leaks.
  841. *********************************************************************************************************
  842. */
  843. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_DISABLED)
  844. void Mem_SegClr (MEM_SEG *p_seg,
  845. LIB_ERR *p_err)
  846. {
  847. CPU_SR_ALLOC();
  848. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  849. if (p_err == DEF_NULL) { /* Chk for null err ptr. */
  850. CPU_SW_EXCEPTION(;);
  851. }
  852. if (p_seg == DEF_NULL) { /* Chk for null seg ptr. */
  853. *p_err = LIB_MEM_ERR_NULL_PTR;
  854. return;
  855. }
  856. #endif
  857. CPU_CRITICAL_ENTER();
  858. p_seg->AddrNext = p_seg->AddrBase;
  859. CPU_CRITICAL_EXIT();
  860. *p_err = LIB_MEM_ERR_NONE;
  861. }
  862. #endif
  863. /*
  864. *********************************************************************************************************
  865. * Mem_SegRemSizeGet()
  866. *
  867. * Description : Gets free space of memory segment.
  868. *
  869. * Argument(s) : p_seg Pointer to segment data.
  870. *
  871. * align Alignment in bytes to assume for calculation of free space.
  872. *
  873. * p_seg_info Pointer to structure that will receive further segment info data (used size,
  874. * total size, base address and next allocation address).
  875. *
  876. * p_err Pointer to variable that will receive the return error code from this function :
  877. *
  878. * LIB_MEM_ERR_NONE Operation was successful.
  879. * LIB_MEM_ERR_NULL_PTR Segment data pointer NULL.
  880. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory alignment.
  881. *
  882. * Return(s) : Memory segment remaining size in bytes, if successful.
  883. * 0, otherwise or if memory segment empty.
  884. *
  885. * Caller(s) : Application,
  886. * Mem_HeapGetSizeRem(),
  887. * Mem_OutputUsage().
  888. *
  889. * Note(s) : None.
  890. *********************************************************************************************************
  891. */
  892. CPU_SIZE_T Mem_SegRemSizeGet (MEM_SEG *p_seg,
  893. CPU_SIZE_T align,
  894. MEM_SEG_INFO *p_seg_info,
  895. LIB_ERR *p_err)
  896. {
  897. CPU_SIZE_T rem_size;
  898. CPU_SIZE_T total_size;
  899. CPU_SIZE_T used_size;
  900. CPU_ADDR next_addr_align;
  901. CPU_SR_ALLOC();
  902. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  903. if (p_err == DEF_NULL) { /* Chk for null err ptr. */
  904. CPU_SW_EXCEPTION(seg_info);
  905. }
  906. if (MATH_IS_PWR2(align) != DEF_YES) { /* Chk for invalid align val. */
  907. *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
  908. return (0u);
  909. }
  910. #endif
  911. if (p_seg == DEF_NULL) { /* Dflt to heap in case p_seg is null. */
  912. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  913. p_seg = &Mem_SegHeap;
  914. #else
  915. *p_err = LIB_MEM_ERR_NULL_PTR;
  916. return (0u);
  917. #endif
  918. }
  919. CPU_CRITICAL_ENTER(); /* Calc seg stats. */
  920. next_addr_align = MATH_ROUND_INC_UP_PWR2(p_seg->AddrNext, align);
  921. CPU_CRITICAL_EXIT();
  922. total_size = p_seg->AddrEnd - p_seg->AddrBase + 1u;
  923. used_size = next_addr_align - p_seg->AddrBase;
  924. rem_size = total_size - used_size;
  925. if (p_seg_info != DEF_NULL) {
  926. p_seg_info->TotalSize = total_size;
  927. p_seg_info->UsedSize = used_size;
  928. p_seg_info->AddrBase = p_seg->AddrBase;
  929. p_seg_info->AddrNextAlloc = next_addr_align;
  930. }
  931. *p_err = LIB_MEM_ERR_NONE;
  932. return (rem_size);
  933. }
  934. /*
  935. *********************************************************************************************************
  936. * Mem_SegAlloc()
  937. *
  938. * Description : Allocates memory from specified segment. Returned memory block will be aligned on a CPU
  939. * word boundary.
  940. *
  941. * Argument(s) : p_name Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
  942. *
  943. * p_seg Pointer to segment from which to allocate memory. Will be allocated from
  944. * general-purpose heap if null.
  945. *
  946. * size Size of memory block to allocate, in bytes.
  947. *
  948. * p_err Pointer to variable that will receive the return error code from this function :
  949. *
  950. * LIB_MEM_ERR_NONE Operation was successful.
  951. *
  952. * ------------------RETURNED BY Mem_SegAllocInternal()-------------------
  953. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  954. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  955. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  956. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  957. *
  958. * Return(s) : Pointer to allocated memory block, if successful.
  959. *
  960. * DEF_NULL, otherwise.
  961. *
  962. * Caller(s) : Application.
  963. *
  964. * Note(s) : (1) The memory block returned by this function will be aligned on a word boundary. In
  965. * order to specify a specific alignment value, use either Mem_SegAllocExt() or
  966. * Mem_SegAllocHW().
  967. *********************************************************************************************************
  968. */
  969. void *Mem_SegAlloc (const CPU_CHAR *p_name,
  970. MEM_SEG *p_seg,
  971. CPU_SIZE_T size,
  972. LIB_ERR *p_err)
  973. {
  974. void *p_blk;
  975. if (p_seg == DEF_NULL) { /* Alloc from heap if p_seg is null. */
  976. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  977. p_seg = &Mem_SegHeap;
  978. #else
  979. *p_err = LIB_MEM_ERR_NULL_PTR;
  980. return (DEF_NULL);
  981. #endif
  982. }
  983. p_blk = Mem_SegAllocInternal(p_name,
  984. p_seg,
  985. size,
  986. sizeof(CPU_ALIGN),
  987. LIB_MEM_PADDING_ALIGN_NONE,
  988. DEF_NULL,
  989. p_err);
  990. return (p_blk);
  991. }
  992. /*
  993. *********************************************************************************************************
  994. * Mem_SegAllocExt()
  995. *
  996. * Description : Allocates memory from specified memory segment.
  997. *
  998. * Argument(s) : p_name Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
  999. *
  1000. * p_seg Pointer to segment from which to allocate memory. Will be allocated from
  1001. * general-purpose heap if null.
  1002. *
  1003. * size Size of memory block to allocate, in bytes.
  1004. *
  1005. * align Required alignment of memory block, in bytes. MUST be a power of 2.
  1006. *
  1007. * p_bytes_reqd Pointer to variable that will receive the number of free bytes missing for
  1008. * the allocation to succeed. Set to DEF_NULL to skip calculation.
  1009. *
  1010. * p_err Pointer to variable that will receive the return error code from this function :
  1011. *
  1012. * LIB_MEM_ERR_NONE Operation was successful.
  1013. *
  1014. * ------------------RETURNED BY Mem_SegAllocInternal()-------------------
  1015. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1016. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1017. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1018. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1019. *
  1020. * Return(s) : Pointer to allocated memory block, if successful.
  1021. *
  1022. * DEF_NULL, otherwise.
  1023. *
  1024. * Caller(s) : Application.
  1025. *
  1026. * Note(s) : none.
  1027. *********************************************************************************************************
  1028. */
  1029. void *Mem_SegAllocExt (const CPU_CHAR *p_name,
  1030. MEM_SEG *p_seg,
  1031. CPU_SIZE_T size,
  1032. CPU_SIZE_T align,
  1033. CPU_SIZE_T *p_bytes_reqd,
  1034. LIB_ERR *p_err)
  1035. {
  1036. void *p_blk;
  1037. if (p_seg == DEF_NULL) { /* Alloc from heap if p_seg is null. */
  1038. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1039. p_seg = &Mem_SegHeap;
  1040. #else
  1041. *p_err = LIB_MEM_ERR_NULL_PTR;
  1042. return (DEF_NULL);
  1043. #endif
  1044. }
  1045. p_blk = Mem_SegAllocInternal(p_name,
  1046. p_seg,
  1047. size,
  1048. align,
  1049. LIB_MEM_PADDING_ALIGN_NONE,
  1050. p_bytes_reqd,
  1051. p_err);
  1052. return (p_blk);
  1053. }
  1054. /*
  1055. *********************************************************************************************************
  1056. * Mem_SegAllocHW()
  1057. *
  1058. * Description : Allocates memory from specified segment. The returned buffer will be padded in function
  1059. * of memory segment's properties.
  1060. *
  1061. * Argument(s) : p_name Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
  1062. *
  1063. * p_seg Pointer to segment from which to allocate memory. Will be allocated from
  1064. * general-purpose heap if null.
  1065. *
  1066. * size Size of memory block to allocate, in bytes.
  1067. *
  1068. * align Required alignment of memory block, in bytes. MUST be a power of 2.
  1069. *
  1070. * p_bytes_reqd Pointer to variable that will receive the number of free bytes missing for
  1071. * the allocation to succeed. Set to DEF_NULL to skip calculation.
  1072. *
  1073. * p_err Pointer to variable that will receive the return error code from this function :
  1074. *
  1075. * LIB_MEM_ERR_NONE Operation was successful.
  1076. *
  1077. * ------------------RETURNED BY Mem_SegAllocInternal()-------------------
  1078. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1079. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1080. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1081. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1082. *
  1083. * Return(s) : Pointer to allocated memory block, if successful.
  1084. *
  1085. * DEF_NULL, otherwise.
  1086. *
  1087. * Caller(s) : Application.
  1088. *
  1089. * Note(s) : none.
  1090. *********************************************************************************************************
  1091. */
  1092. void *Mem_SegAllocHW (const CPU_CHAR *p_name,
  1093. MEM_SEG *p_seg,
  1094. CPU_SIZE_T size,
  1095. CPU_SIZE_T align,
  1096. CPU_SIZE_T *p_bytes_reqd,
  1097. LIB_ERR *p_err)
  1098. {
  1099. void *p_blk;
  1100. if (p_seg == DEF_NULL) { /* Alloc from heap if p_seg is null. */
  1101. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1102. p_seg = &Mem_SegHeap;
  1103. #else
  1104. *p_err = LIB_MEM_ERR_NULL_PTR;
  1105. return (DEF_NULL);
  1106. #endif
  1107. }
  1108. p_blk = Mem_SegAllocInternal(p_name,
  1109. p_seg,
  1110. size,
  1111. align,
  1112. p_seg->PaddingAlign,
  1113. p_bytes_reqd,
  1114. p_err);
  1115. return (p_blk);
  1116. }
  1117. /*
  1118. *********************************************************************************************************
  1119. * Mem_PoolCreate()
  1120. *
  1121. * Description : (1) Creates a memory pool :
  1122. *
  1123. * (a) Create memory pool from heap or dedicated memory
  1124. * (b) Allocate memory pool memory blocks
  1125. * (c) Configure memory pool
  1126. *
  1127. *
  1128. * Argument(s) : p_pool Pointer to a memory pool structure to create (see Note #1).
  1129. *
  1130. * p_mem_base Memory pool segment base address :
  1131. *
  1132. * (a) Null address Memory pool allocated from general-purpose heap.
  1133. * (b) Non-null address Memory pool allocated from dedicated memory
  1134. * specified by its base address.
  1135. *
  1136. * mem_size Size of memory pool segment (in bytes).
  1137. *
  1138. * blk_nbr Number of memory pool blocks to create.
  1139. *
  1140. * blk_size Size of memory pool blocks to create (in bytes).
  1141. *
  1142. * blk_align Alignment of memory pool blocks to specific word boundary (in bytes).
  1143. *
  1144. * p_bytes_reqd Optional pointer to a variable to ... :
  1145. *
  1146. * (a) Return the number of bytes required to successfully
  1147. * allocate the memory pool, if any error(s);
  1148. * (b) Return 0, otherwise.
  1149. *
  1150. * p_err Pointer to variable that will receive the return error code from this function :
  1151. *
  1152. * LIB_MEM_ERR_NONE Operation was successful.
  1153. * LIB_MEM_ERR_NULL_PTR Pointer to memory pool is null.
  1154. * LIB_MEM_ERR_INVALID_BLK_ALIGN Invalid block alignment requested.
  1155. * LIB_MEM_ERR_INVALID_BLK_NBR Invalid number of blocks specified.
  1156. * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid block size specified.
  1157. * LIB_MEM_ERR_INVALID_SEG_SIZE Invalid segment size.
  1158. * LIB_MEM_ERR_HEAP_EMPTY No more memory available on heap.
  1159. *
  1160. * ---------------RETURNED BY Mem_SegOverlapChkCritical()----------------
  1161. * LIB_MEM_ERR_INVALID_SEG_EXISTS Segment already exists.
  1162. * LIB_MEM_ERR_INVALID_SEG_OVERLAP Segment overlaps another existing segment.
  1163. *
  1164. * -----------------RETURNED BY Mem_SegAllocExtCritical()-----------------
  1165. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1166. *
  1167. * ------------------RETURNED BY Mem_SegAllocInternal()-------------------
  1168. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1169. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1170. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1171. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1172. *
  1173. * -----------------------RETURNED BY Mem_PoolClr()-----------------------
  1174. * LIB_MEM_ERR_NULL_PTR Argument 'p_pool' passed a NULL pointer.
  1175. *
  1176. * Return(s) : none.
  1177. *
  1178. * Caller(s) : Application.
  1179. *
  1180. * Note(s) : (1) This function is DEPRECATED and will be removed in a future version of this product.
  1181. * Mem_DynPoolCreate() or Mem_DynPoolCreateHW() should be used instead.
  1182. *********************************************************************************************************
  1183. */
  1184. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1185. void Mem_PoolCreate (MEM_POOL *p_pool,
  1186. void *p_mem_base,
  1187. CPU_SIZE_T mem_size,
  1188. MEM_POOL_BLK_QTY blk_nbr,
  1189. CPU_SIZE_T blk_size,
  1190. CPU_SIZE_T blk_align,
  1191. CPU_SIZE_T *p_bytes_reqd,
  1192. LIB_ERR *p_err)
  1193. {
  1194. MEM_SEG *p_seg;
  1195. void *p_pool_mem;
  1196. CPU_SIZE_T pool_size;
  1197. CPU_SIZE_T blk_size_align;
  1198. CPU_ADDR pool_addr_end;
  1199. MEM_POOL_BLK_QTY blk_ix;
  1200. CPU_INT08U *p_blk;
  1201. CPU_SR_ALLOC();
  1202. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* --------------- VALIDATE RTN ERR PTR --------------- */
  1203. if (p_err == DEF_NULL) {
  1204. CPU_SW_EXCEPTION(;);
  1205. }
  1206. /* ------------- VALIDATE MEM POOL CREATE ------------- */
  1207. if (p_pool == DEF_NULL) {
  1208. *p_err = LIB_MEM_ERR_NULL_PTR;
  1209. return;
  1210. }
  1211. if (p_mem_base != DEF_NULL) {
  1212. if (mem_size < 1u) {
  1213. *p_err = LIB_MEM_ERR_INVALID_SEG_SIZE;
  1214. return;
  1215. }
  1216. }
  1217. if (blk_nbr < 1u) {
  1218. *p_err = LIB_MEM_ERR_INVALID_BLK_NBR;
  1219. return;
  1220. }
  1221. if (blk_size < 1u) {
  1222. *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
  1223. return;
  1224. }
  1225. if (MATH_IS_PWR2(blk_align) != DEF_YES) { /* Chk that req alignment is a pwr of 2. */
  1226. *p_err = LIB_MEM_ERR_INVALID_BLK_ALIGN;
  1227. return;
  1228. }
  1229. #endif
  1230. Mem_PoolClr(p_pool, p_err); /* Init mem pool. */
  1231. if (*p_err != LIB_MEM_ERR_NONE) {
  1232. return;
  1233. }
  1234. /* -------- DETERMINE AND/OR ALLOC SEG TO USE --------- */
  1235. if (p_mem_base == DEF_NULL) { /* Use heap seg. */
  1236. p_seg = &Mem_SegHeap;
  1237. } else { /* Use other seg. */
  1238. CPU_CRITICAL_ENTER();
  1239. p_seg = Mem_SegOverlapChkCritical((CPU_ADDR)p_mem_base,
  1240. mem_size,
  1241. p_err);
  1242. switch (*p_err) {
  1243. case LIB_MEM_ERR_INVALID_SEG_EXISTS: /* Seg already exists. */
  1244. break;
  1245. case LIB_MEM_ERR_NONE: /* Seg must be created. */
  1246. p_seg = (MEM_SEG *)Mem_SegAllocExtCritical(&Mem_SegHeap,
  1247. sizeof(MEM_SEG),
  1248. sizeof(CPU_ALIGN),
  1249. LIB_MEM_PADDING_ALIGN_NONE,
  1250. p_bytes_reqd,
  1251. p_err);
  1252. if (*p_err != LIB_MEM_ERR_NONE) {
  1253. CPU_CRITICAL_EXIT();
  1254. return;
  1255. }
  1256. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED) /* Track alloc if req'd. */
  1257. Mem_SegAllocTrackCritical("Unknown segment data",
  1258. &Mem_SegHeap,
  1259. sizeof(MEM_SEG),
  1260. p_err);
  1261. if (*p_err != LIB_MEM_ERR_NONE) {
  1262. CPU_CRITICAL_EXIT();
  1263. return;
  1264. }
  1265. #endif
  1266. Mem_SegCreateCritical( DEF_NULL,
  1267. p_seg,
  1268. (CPU_ADDR)p_mem_base,
  1269. LIB_MEM_PADDING_ALIGN_NONE,
  1270. mem_size);
  1271. break;
  1272. case LIB_MEM_ERR_INVALID_SEG_OVERLAP:
  1273. default:
  1274. CPU_CRITICAL_EXIT();
  1275. return; /* Prevent 'break NOT reachable' compiler warning. */
  1276. }
  1277. CPU_CRITICAL_EXIT();
  1278. }
  1279. /* ---------------- ALLOC MEM FOR POOL ---------------- */
  1280. /* Calc blk size with align. */
  1281. blk_size_align = MATH_ROUND_INC_UP_PWR2(blk_size, blk_align);
  1282. pool_size = blk_size_align * blk_nbr; /* Calc required size for pool. */
  1283. /* Alloc mem for pool. */
  1284. p_pool_mem = (void *)Mem_SegAllocInternal("Unnamed static pool",
  1285. p_seg,
  1286. pool_size,
  1287. blk_align,
  1288. LIB_MEM_PADDING_ALIGN_NONE,
  1289. p_bytes_reqd,
  1290. p_err);
  1291. if (*p_err != LIB_MEM_ERR_NONE) {
  1292. return;
  1293. }
  1294. /* ------------ ALLOC MEM FOR FREE BLK TBL ------------ */
  1295. p_pool->BlkFreeTbl = (void *)Mem_SegAllocInternal("Unnamed static pool free blk tbl",
  1296. &Mem_SegHeap,
  1297. blk_nbr * sizeof(void *),
  1298. sizeof(CPU_ALIGN),
  1299. LIB_MEM_PADDING_ALIGN_NONE,
  1300. p_bytes_reqd,
  1301. p_err);
  1302. if (*p_err != LIB_MEM_ERR_NONE) {
  1303. return;
  1304. }
  1305. /* ------------------ INIT BLK LIST ------------------- */
  1306. p_blk = (CPU_INT08U *)p_pool_mem;
  1307. for (blk_ix = 0; blk_ix < blk_nbr; blk_ix++) {
  1308. p_pool->BlkFreeTbl[blk_ix] = p_blk;
  1309. p_blk += blk_size_align;
  1310. }
  1311. /* ------------------ INIT POOL DATA ------------------ */
  1312. pool_addr_end = (CPU_ADDR)p_pool_mem + (pool_size - 1u);
  1313. p_pool->PoolAddrStart = p_pool_mem;
  1314. p_pool->PoolAddrEnd = (void *)pool_addr_end;
  1315. p_pool->BlkNbr = blk_nbr;
  1316. p_pool->BlkSize = blk_size_align;
  1317. p_pool->BlkFreeTblIx = blk_nbr;
  1318. }
  1319. #endif
  1320. /*
  1321. *********************************************************************************************************
  1322. * Mem_PoolClr()
  1323. *
  1324. * Description : Clears a memory pool (see Note #1).
  1325. *
  1326. * Argument(s) : p_pool Pointer to a memory pool structure to clear (see Note #2).
  1327. *
  1328. * p_err Pointer to variable that will receive the return error code from this function :
  1329. *
  1330. * LIB_MEM_ERR_NONE Operation was successful.
  1331. * LIB_MEM_ERR_NULL_PTR Argument 'p_pool' passed a NULL pointer.
  1332. *
  1333. * Return(s) : none.
  1334. *
  1335. * Caller(s) : Application,
  1336. * Mem_PoolCreate().
  1337. *
  1338. * Note(s) : (1) (a) Mem_PoolClr() ONLY clears a memory pool structure's variables & should ONLY be
  1339. * called to initialize a memory pool structure prior to calling Mem_PoolCreate().
  1340. *
  1341. * (b) Mem_PoolClr() does NOT deallocate memory from the memory pool or deallocate the
  1342. * memory pool itself & MUST NOT be called after calling Mem_PoolCreate() since
  1343. * this will likely corrupt the memory pool management.
  1344. *
  1345. * (2) Assumes 'p_pool' points to a valid memory pool (if non-NULL).
  1346. *
  1347. * (3) This function is DEPRECATED and will be removed in a future version of this product.
  1348. *********************************************************************************************************
  1349. */
  1350. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1351. void Mem_PoolClr (MEM_POOL *p_pool,
  1352. LIB_ERR *p_err)
  1353. {
  1354. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* -------------- VALIDATE RTN ERR PTR --------------- */
  1355. if (p_err == DEF_NULL) {
  1356. CPU_SW_EXCEPTION(;);
  1357. }
  1358. /* -------------- VALIDATE MEM POOL PTR --------------- */
  1359. if (p_pool == DEF_NULL) {
  1360. *p_err = LIB_MEM_ERR_NULL_PTR;
  1361. return;
  1362. }
  1363. #endif
  1364. p_pool->PoolAddrStart = DEF_NULL;
  1365. p_pool->PoolAddrEnd = DEF_NULL;
  1366. p_pool->BlkSize = 0u;
  1367. p_pool->BlkNbr = 0u;
  1368. p_pool->BlkFreeTbl = DEF_NULL;
  1369. p_pool->BlkFreeTblIx = 0u;
  1370. *p_err = LIB_MEM_ERR_NONE;
  1371. }
  1372. #endif
  1373. /*
  1374. *********************************************************************************************************
  1375. * Mem_PoolBlkGet()
  1376. *
  1377. * Description : Gets a memory block from memory pool.
  1378. *
  1379. * Argument(s) : p_pool Pointer to memory pool to get memory block from.
  1380. *
  1381. * size Size of requested memory (in bytes).
  1382. *
  1383. * p_err Pointer to variable that will receive the return error code from this function :
  1384. *
  1385. * LIB_MEM_ERR_NONE Operation was successful.
  1386. * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid memory pool block size requested.
  1387. * LIB_MEM_ERR_NULL_PTR Argument 'p_pool' passed a NULL pointer.
  1388. * LIB_MEM_ERR_POOL_EMPTY NO memory blocks available in memory pool.
  1389. *
  1390. * Return(s) : Pointer to memory block, if NO error(s).
  1391. *
  1392. * Pointer to NULL, otherwise.
  1393. *
  1394. * Caller(s) : Application.
  1395. *
  1396. * Note(s) : (1) This function is DEPRECATED and will be removed in a future version of this product.
  1397. * Mem_DynPoolBlkGet() should be used instead.
  1398. *********************************************************************************************************
  1399. */
  1400. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1401. void *Mem_PoolBlkGet (MEM_POOL *p_pool,
  1402. CPU_SIZE_T size,
  1403. LIB_ERR *p_err)
  1404. {
  1405. CPU_INT08U *p_blk;
  1406. CPU_SR_ALLOC();
  1407. (void)&size; /* Prevent possible 'variable unused' warning. */
  1408. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* -------------- VALIDATE MEM POOL GET --------------- */
  1409. if (p_err == DEF_NULL) { /* Validate err ptr. */
  1410. CPU_SW_EXCEPTION(DEF_NULL);
  1411. }
  1412. if (p_pool == DEF_NULL) { /* Validate pool ptr. */
  1413. *p_err = LIB_MEM_ERR_NULL_PTR;
  1414. return (DEF_NULL);
  1415. }
  1416. if (size < 1u) { /* Validate req'd size as non-NULL. */
  1417. *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
  1418. return (DEF_NULL);
  1419. }
  1420. if (size > p_pool->BlkSize) { /* Validate req'd size <= mem pool blk size. */
  1421. *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
  1422. return (DEF_NULL);
  1423. }
  1424. #endif
  1425. /* -------------- GET MEM BLK FROM POOL --------------- */
  1426. p_blk = DEF_NULL;
  1427. CPU_CRITICAL_ENTER();
  1428. if (p_pool->BlkFreeTblIx > 0u) {
  1429. p_pool->BlkFreeTblIx -= 1u;
  1430. p_blk = p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx];
  1431. p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx] = DEF_NULL;
  1432. }
  1433. CPU_CRITICAL_EXIT();
  1434. if (p_blk == DEF_NULL) {
  1435. *p_err = LIB_MEM_ERR_POOL_EMPTY;
  1436. } else {
  1437. *p_err = LIB_MEM_ERR_NONE;
  1438. }
  1439. return (p_blk);
  1440. }
  1441. #endif
  1442. /*
  1443. *********************************************************************************************************
  1444. * Mem_PoolBlkFree()
  1445. *
  1446. * Description : Free a memory block to memory pool.
  1447. *
  1448. * Argument(s) : p_pool Pointer to memory pool to free memory block.
  1449. *
  1450. * p_blk Pointer to memory block address to free.
  1451. *
  1452. * p_err Pointer to variable that will receive the return error code from this function :
  1453. *
  1454. * LIB_MEM_ERR_NONE Operation was successful.
  1455. * LIB_MEM_ERR_NULL_PTR Argument 'p_pool'/'p_blk' passed
  1456. * a NULL pointer.
  1457. * LIB_MEM_ERR_INVALID_BLK_ADDR Invalid memory block address.
  1458. * LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL Memory block address already
  1459. * in memory pool.
  1460. * LIB_MEM_ERR_POOL_FULL Pool is full.
  1461. *
  1462. * Return(s) : none.
  1463. *
  1464. * Caller(s) : Application.
  1465. *
  1466. * Note(s) : (1) This function is DEPRECATED and will be removed in a future version of this product.
  1467. * Mem_DynPoolBlkFree() should be used instead.
  1468. *********************************************************************************************************
  1469. */
  1470. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1471. void Mem_PoolBlkFree (MEM_POOL *p_pool,
  1472. void *p_blk,
  1473. LIB_ERR *p_err)
  1474. {
  1475. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1476. CPU_SIZE_T tbl_ix;
  1477. CPU_BOOLEAN addr_valid;
  1478. #endif
  1479. CPU_SR_ALLOC();
  1480. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* -------------- VALIDATE MEM POOL FREE -------------- */
  1481. if (p_err == DEF_NULL) {
  1482. CPU_SW_EXCEPTION(;);
  1483. }
  1484. if (p_pool == DEF_NULL) { /* Validate mem ptrs. */
  1485. *p_err = LIB_MEM_ERR_NULL_PTR;
  1486. return;
  1487. }
  1488. if (p_blk == DEF_NULL) {
  1489. *p_err = LIB_MEM_ERR_NULL_PTR;
  1490. return;
  1491. }
  1492. addr_valid = Mem_PoolBlkIsValidAddr(p_pool, p_blk); /* Validate mem blk as valid pool blk addr. */
  1493. if (addr_valid != DEF_OK) {
  1494. *p_err = LIB_MEM_ERR_INVALID_BLK_ADDR;
  1495. return;
  1496. }
  1497. CPU_CRITICAL_ENTER(); /* Make sure blk isn't already in free list. */
  1498. for (tbl_ix = 0u; tbl_ix < p_pool->BlkNbr; tbl_ix++) {
  1499. if (p_pool->BlkFreeTbl[tbl_ix] == p_blk) {
  1500. CPU_CRITICAL_EXIT();
  1501. *p_err = LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL;
  1502. return;
  1503. }
  1504. }
  1505. #else /* Double-free possibility if not in critical section. */
  1506. CPU_CRITICAL_ENTER();
  1507. #endif
  1508. /* --------------- FREE MEM BLK TO POOL --------------- */
  1509. if (p_pool->BlkFreeTblIx >= p_pool->BlkNbr) {
  1510. CPU_CRITICAL_EXIT();
  1511. *p_err = LIB_MEM_ERR_POOL_FULL;
  1512. return;
  1513. }
  1514. p_pool->BlkFreeTbl[p_pool->BlkFreeTblIx] = p_blk;
  1515. p_pool->BlkFreeTblIx += 1u;
  1516. CPU_CRITICAL_EXIT();
  1517. *p_err = LIB_MEM_ERR_NONE;
  1518. }
  1519. #endif
  1520. /*
  1521. *********************************************************************************************************
  1522. * Mem_PoolBlkGetNbrAvail()
  1523. *
  1524. * Description : Get memory pool's remaining number of blocks available to allocate.
  1525. *
  1526. * Argument(s) : p_pool Pointer to a memory pool structure.
  1527. *
  1528. * p_err Pointer to variable that will receive the return error code from this function :
  1529. *
  1530. * LIB_MEM_ERR_NONE Operation was successful.
  1531. * LIB_MEM_ERR_NULL_PTR Argument 'p_pool' passed a NULL pointer.
  1532. *
  1533. * Return(s) : Remaining memory pool blocks, if NO error(s).
  1534. *
  1535. * 0, otherwise.
  1536. *
  1537. * Caller(s) : Application.
  1538. *
  1539. * Note(s) : (1) This function is DEPRECATED and will be removed in a future version of this product.
  1540. * Mem_DynPoolBlkNbrAvailGet() should be used instead.
  1541. *********************************************************************************************************
  1542. */
  1543. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1544. MEM_POOL_BLK_QTY Mem_PoolBlkGetNbrAvail (MEM_POOL *p_pool,
  1545. LIB_ERR *p_err)
  1546. {
  1547. CPU_SIZE_T nbr_avail;
  1548. CPU_SR_ALLOC();
  1549. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1550. /* --------------- VALIDATE RTN ERR PTR --------------- */
  1551. if (p_err == DEF_NULL) {
  1552. CPU_SW_EXCEPTION(0u);
  1553. }
  1554. /* ---------------- VALIDATE MEM POOL ----------------- */
  1555. if (p_pool == DEF_NULL) { /* Validate mem ptr. */
  1556. *p_err = LIB_MEM_ERR_NULL_PTR;
  1557. return (0u);
  1558. }
  1559. #endif
  1560. CPU_CRITICAL_ENTER();
  1561. nbr_avail = p_pool->BlkFreeTblIx;
  1562. CPU_CRITICAL_EXIT();
  1563. *p_err = LIB_MEM_ERR_NONE;
  1564. return (nbr_avail);
  1565. }
  1566. #endif
  1567. /*
  1568. *********************************************************************************************************
  1569. * Mem_DynPoolCreate()
  1570. *
  1571. * Description : Creates a dynamic memory pool.
  1572. *
  1573. * Argument(s) : p_name Pointer to pool name.
  1574. *
  1575. * p_pool Pointer to pool data.
  1576. *
  1577. * p_seg Pointer to segment from which to allocate memory. Will be allocated from
  1578. * general-purpose heap if null.
  1579. *
  1580. * blk_size Size of memory block to allocate from pool, in bytes. See Note #1.
  1581. *
  1582. * blk_align Required alignment of memory block, in bytes. MUST be a power of 2.
  1583. *
  1584. * blk_qty_init Initial number of elements to be allocated in pool.
  1585. *
  1586. * blk_qty_max Maximum number of elements that can be allocated from this pool. Set to
  1587. * LIB_MEM_BLK_QTY_UNLIMITED if no limit.
  1588. *
  1589. * p_err Pointer to variable that will receive the return error code from this function :
  1590. *
  1591. * LIB_MEM_ERR_NONE Operation was successful.
  1592. *
  1593. * --------------------RETURNED BY Mem_DynPoolCreateInternal()-------------------
  1594. * LIB_MEM_ERR_INVALID_BLK_ALIGN Invalid requested block alignment.
  1595. * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid requested block size.
  1596. * LIB_MEM_ERR_INVALID_BLK_NBR Invalid requested block quantity max.
  1597. * LIB_MEM_ERR_NULL_PTR Pool data pointer NULL.
  1598. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1599. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1600. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1601. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1602. *
  1603. * Return(s) : None.
  1604. *
  1605. * Caller(s) : Application.
  1606. *
  1607. * Note(s) : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
  1608. * block is stored in the block itself (only when free/unused).
  1609. *********************************************************************************************************
  1610. */
  1611. void Mem_DynPoolCreate (const CPU_CHAR *p_name,
  1612. MEM_DYN_POOL *p_pool,
  1613. MEM_SEG *p_seg,
  1614. CPU_SIZE_T blk_size,
  1615. CPU_SIZE_T blk_align,
  1616. CPU_SIZE_T blk_qty_init,
  1617. CPU_SIZE_T blk_qty_max,
  1618. LIB_ERR *p_err)
  1619. {
  1620. if (p_seg == DEF_NULL) { /* Alloc from heap if p_seg is null. */
  1621. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1622. p_seg = &Mem_SegHeap;
  1623. #else
  1624. *p_err = LIB_MEM_ERR_NULL_PTR;
  1625. return (DEF_NULL);
  1626. #endif
  1627. }
  1628. Mem_DynPoolCreateInternal(p_name,
  1629. p_pool,
  1630. p_seg,
  1631. blk_size,
  1632. blk_align,
  1633. LIB_MEM_PADDING_ALIGN_NONE,
  1634. blk_qty_init,
  1635. blk_qty_max,
  1636. p_err);
  1637. }
  1638. /*
  1639. *********************************************************************************************************
  1640. * Mem_DynPoolCreateHW()
  1641. *
  1642. * Description : Creates a dynamic memory pool. Memory blocks will be padded according to memory segment's
  1643. * properties.
  1644. *
  1645. * Argument(s) : p_name Pointer to pool name.
  1646. *
  1647. * p_pool Pointer to pool data.
  1648. *
  1649. * p_seg Pointer to segment from which to allocate memory. Will allocate from
  1650. * general-purpose heap if null.
  1651. *
  1652. * blk_size Size of memory block to allocate from pool, in bytes. See Note #1.
  1653. *
  1654. * blk_align Required alignment of memory block, in bytes. MUST be a power of 2.
  1655. *
  1656. * blk_qty_init Initial number of elements to be allocated in pool.
  1657. *
  1658. * blk_qty_max Maximum number of elements that can be allocated from this pool. Set to
  1659. * LIB_MEM_BLK_QTY_UNLIMITED if no limit.
  1660. *
  1661. * p_err Pointer to variable that will receive the return error code from this function :
  1662. *
  1663. * LIB_MEM_ERR_NONE Operation was successful.
  1664. *
  1665. * -------------------RETURNED BY Mem_DynPoolCreateInternal()-------------------
  1666. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1667. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1668. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1669. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1670. *
  1671. * Return(s) : None.
  1672. *
  1673. * Caller(s) : Application.
  1674. *
  1675. * Note(s) : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
  1676. * block is stored in the block itself (only when free/unused).
  1677. *********************************************************************************************************
  1678. */
  1679. void Mem_DynPoolCreateHW (const CPU_CHAR *p_name,
  1680. MEM_DYN_POOL *p_pool,
  1681. MEM_SEG *p_seg,
  1682. CPU_SIZE_T blk_size,
  1683. CPU_SIZE_T blk_align,
  1684. CPU_SIZE_T blk_qty_init,
  1685. CPU_SIZE_T blk_qty_max,
  1686. LIB_ERR *p_err)
  1687. {
  1688. if (p_seg == DEF_NULL) { /* Alloc from heap if p_seg is null. */
  1689. #if (LIB_MEM_CFG_HEAP_SIZE > 0u)
  1690. p_seg = &Mem_SegHeap;
  1691. #else
  1692. *p_err = LIB_MEM_ERR_NULL_PTR;
  1693. return (DEF_NULL);
  1694. #endif
  1695. }
  1696. Mem_DynPoolCreateInternal(p_name,
  1697. p_pool,
  1698. p_seg,
  1699. blk_size,
  1700. blk_align,
  1701. p_seg->PaddingAlign,
  1702. blk_qty_init,
  1703. blk_qty_max,
  1704. p_err);
  1705. }
  1706. /*
  1707. *********************************************************************************************************
  1708. * Mem_DynPoolBlkGet()
  1709. *
  1710. * Description : Gets a memory block from specified pool, growing it if needed.
  1711. *
  1712. * Argument(s) : p_pool Pointer to pool data.
  1713. *
  1714. * p_err Pointer to variable that will receive the return error code from this function :
  1715. *
  1716. * LIB_MEM_ERR_NONE Operation was successful.
  1717. * LIB_MEM_ERR_NULL_PTR Pool data pointer NULL.
  1718. * LIB_MEM_ERR_POOL_EMPTY Pools is empty.
  1719. *
  1720. * ----------------------RETURNED BY Mem_SegAllocInternal()-----------------------
  1721. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  1722. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  1723. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  1724. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  1725. *
  1726. * Return(s) : Pointer to memory block, if successful.
  1727. *
  1728. * DEF_NULL, otherwise.
  1729. *
  1730. * Caller(s) : Application.
  1731. *
  1732. * Note(s) : none.
  1733. *********************************************************************************************************
  1734. */
  1735. void *Mem_DynPoolBlkGet (MEM_DYN_POOL *p_pool,
  1736. LIB_ERR *p_err)
  1737. {
  1738. void *p_blk;
  1739. const CPU_CHAR *p_pool_name;
  1740. CPU_SR_ALLOC();
  1741. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1742. if (p_err == DEF_NULL) { /* Chk for NULL err ptr. */
  1743. CPU_SW_EXCEPTION(DEF_NULL);
  1744. }
  1745. if (p_pool == DEF_NULL) { /* Chk for NULL pool data ptr. */
  1746. *p_err = LIB_MEM_ERR_NULL_PTR;
  1747. return (DEF_NULL);
  1748. }
  1749. #endif
  1750. /* Ensure pool is not empty if qty is limited. */
  1751. if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) {
  1752. CPU_CRITICAL_ENTER();
  1753. if (p_pool->BlkAllocCnt >= p_pool->BlkQtyMax) {
  1754. CPU_CRITICAL_EXIT();
  1755. *p_err = LIB_MEM_ERR_POOL_EMPTY;
  1756. return (DEF_NULL);
  1757. }
  1758. p_pool->BlkAllocCnt++;
  1759. CPU_CRITICAL_EXIT();
  1760. }
  1761. /* --------------- ALLOC FROM FREE LIST --------------- */
  1762. CPU_CRITICAL_ENTER();
  1763. if (p_pool->BlkFreePtr != DEF_NULL) {
  1764. p_blk = p_pool->BlkFreePtr;
  1765. p_pool->BlkFreePtr = *((void **)p_blk);
  1766. CPU_CRITICAL_EXIT();
  1767. *p_err = LIB_MEM_ERR_NONE;
  1768. return (p_blk);
  1769. }
  1770. CPU_CRITICAL_EXIT();
  1771. /* ------------------ ALLOC NEW BLK ------------------- */
  1772. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  1773. p_pool_name = p_pool->NamePtr;
  1774. #else
  1775. p_pool_name = DEF_NULL;
  1776. #endif
  1777. p_blk = Mem_SegAllocInternal(p_pool_name,
  1778. p_pool->PoolSegPtr,
  1779. p_pool->BlkSize,
  1780. p_pool->BlkAlign,
  1781. p_pool->BlkPaddingAlign,
  1782. DEF_NULL,
  1783. p_err);
  1784. if (*p_err != LIB_MEM_ERR_NONE) {
  1785. return (DEF_NULL);
  1786. }
  1787. return (p_blk);
  1788. }
  1789. /*
  1790. *********************************************************************************************************
  1791. * Mem_DynPoolBlkFree()
  1792. *
  1793. * Description : Frees memory block, making it available for future use.
  1794. *
  1795. * Argument(s) : p_pool Pointer to pool data.
  1796. *
  1797. * p_blk Pointer to first byte of memory block.
  1798. *
  1799. * p_err Pointer to variable that will receive the return error code from this function :
  1800. *
  1801. * LIB_MEM_ERR_NONE Operation was successful.
  1802. * LIB_MEM_ERR_NULL_PTR 'p_pool' or 'p_blk' pointer passed is NULL.
  1803. * LIB_MEM_ERR_POOL_FULL Pool is full.
  1804. *
  1805. * Return(s) : none.
  1806. *
  1807. * Caller(s) : Application.
  1808. *
  1809. * Note(s) : none.
  1810. *********************************************************************************************************
  1811. */
  1812. void Mem_DynPoolBlkFree (MEM_DYN_POOL *p_pool,
  1813. void *p_blk,
  1814. LIB_ERR *p_err)
  1815. {
  1816. CPU_SR_ALLOC();
  1817. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1818. if (p_err == DEF_NULL) { /* Chk for NULL err ptr. */
  1819. CPU_SW_EXCEPTION(;);
  1820. }
  1821. if (p_pool == DEF_NULL) { /* Chk for NULL pool data ptr. */
  1822. *p_err = LIB_MEM_ERR_NULL_PTR;
  1823. return;
  1824. }
  1825. if (p_blk == DEF_NULL) {
  1826. *p_err = LIB_MEM_ERR_NULL_PTR;
  1827. return;
  1828. }
  1829. #endif
  1830. if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) { /* Ensure pool is not full. */
  1831. CPU_CRITICAL_ENTER();
  1832. if (p_pool->BlkAllocCnt == 0u) {
  1833. CPU_CRITICAL_EXIT();
  1834. *p_err = LIB_MEM_ERR_POOL_FULL;
  1835. return;
  1836. }
  1837. p_pool->BlkAllocCnt--;
  1838. CPU_CRITICAL_EXIT();
  1839. }
  1840. CPU_CRITICAL_ENTER();
  1841. *((void **)p_blk) = p_pool->BlkFreePtr;
  1842. p_pool->BlkFreePtr = p_blk;
  1843. CPU_CRITICAL_EXIT();
  1844. *p_err = LIB_MEM_ERR_NONE;
  1845. }
  1846. /*
  1847. *********************************************************************************************************
  1848. * Mem_DynPoolBlkNbrAvailGet()
  1849. *
  1850. * Description : Gets number of available blocks in dynamic memory pool. This call will fail with a
  1851. * dynamic memory pool for which no limit was set at creation.
  1852. *
  1853. * Argument(s) : p_pool Pointer to pool data.
  1854. *
  1855. * p_err Pointer to variable that will receive the return error code from this function :
  1856. *
  1857. * LIB_MEM_ERR_NONE Operation was successful.
  1858. * LIB_MEM_ERR_NULL_PTR 'p_pool' pointer passed is NULL.
  1859. * LIB_MEM_ERR_POOL_UNLIMITED Pool has no specified limit.
  1860. *
  1861. * Return(s) : Number of blocks available in dynamic memory pool, if successful.
  1862. *
  1863. * 0, if pool is empty or if an error occurred.
  1864. *
  1865. * Caller(s) : Application.
  1866. *
  1867. * Note(s) : None.
  1868. *********************************************************************************************************
  1869. */
  1870. CPU_SIZE_T Mem_DynPoolBlkNbrAvailGet (MEM_DYN_POOL *p_pool,
  1871. LIB_ERR *p_err)
  1872. {
  1873. CPU_SIZE_T blk_nbr_avail;
  1874. CPU_SR_ALLOC();
  1875. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1876. if (p_err == DEF_NULL) { /* Chk for NULL err ptr. */
  1877. CPU_SW_EXCEPTION(;);
  1878. }
  1879. if (p_pool == DEF_NULL) { /* Chk for NULL pool data ptr. */
  1880. *p_err = LIB_MEM_ERR_NULL_PTR;
  1881. return (0u);
  1882. }
  1883. #endif
  1884. if (p_pool->BlkQtyMax != LIB_MEM_BLK_QTY_UNLIMITED) {
  1885. CPU_CRITICAL_ENTER();
  1886. blk_nbr_avail = p_pool->BlkQtyMax - p_pool->BlkAllocCnt;
  1887. CPU_CRITICAL_EXIT();
  1888. *p_err = LIB_MEM_ERR_NONE;
  1889. } else {
  1890. blk_nbr_avail = 0u;
  1891. *p_err = LIB_MEM_ERR_POOL_UNLIMITED;
  1892. }
  1893. return (blk_nbr_avail);
  1894. }
  1895. /*
  1896. *********************************************************************************************************
  1897. * Mem_OutputUsage()
  1898. *
  1899. * Description : Outputs memory usage report through 'out_fnct'.
  1900. *
  1901. * Argument(s) : out_fnct Pointer to output function.
  1902. *
  1903. * print_details DEF_YES, if the size of each allocation should be printed.
  1904. * DEF_NO, otherwise.
  1905. *
  1906. * p_err Pointer to variable that will receive the return error code from this function :
  1907. *
  1908. * LIB_MEM_ERR_NONE Operation was successful.
  1909. * LIB_MEM_ERR_NULL_PTR 'out_fnct' pointer passed is NULL.
  1910. *
  1911. * ---------------------RETURNED BY Mem_SegRemSizeGet()--------------------
  1912. * LIB_MEM_ERR_NULL_PTR Segment data pointer NULL.
  1913. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory alignment.
  1914. *
  1915. * Return(s) : None.
  1916. *
  1917. * Caller(s) : Application.
  1918. *
  1919. * Note(s) : none.
  1920. *********************************************************************************************************
  1921. */
  1922. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  1923. void Mem_OutputUsage(void (*out_fnct) (CPU_CHAR *),
  1924. LIB_ERR *p_err)
  1925. {
  1926. CPU_CHAR str[DEF_INT_32U_NBR_DIG_MAX];
  1927. MEM_SEG *p_seg;
  1928. CPU_SR_ALLOC();
  1929. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  1930. if (p_err == DEF_NULL) { /* Chk for NULL err ptr. */
  1931. CPU_SW_EXCEPTION(;);
  1932. }
  1933. if (out_fnct == DEF_NULL) { /* Chk for NULL out fnct ptr. */
  1934. *p_err = LIB_MEM_ERR_NULL_PTR;
  1935. return;
  1936. }
  1937. #endif
  1938. out_fnct("---------------- Memory allocation info ----------------\r\n");
  1939. out_fnct("| Type | Size | Free size | Name\r\n");
  1940. out_fnct("|---------|------------|------------|-------------------\r\n");
  1941. CPU_CRITICAL_ENTER();
  1942. p_seg = Mem_SegHeadPtr;
  1943. while (p_seg != DEF_NULL) {
  1944. CPU_SIZE_T rem_size;
  1945. MEM_SEG_INFO seg_info;
  1946. MEM_ALLOC_INFO *p_alloc;
  1947. rem_size = Mem_SegRemSizeGet(p_seg, 1u, &seg_info, p_err);
  1948. if (*p_err != LIB_MEM_ERR_NONE) {
  1949. return;
  1950. }
  1951. out_fnct("| Section | ");
  1952. (void)Str_FmtNbr_Int32U(seg_info.TotalSize,
  1953. 10u,
  1954. DEF_NBR_BASE_DEC,
  1955. ' ',
  1956. DEF_NO,
  1957. DEF_YES,
  1958. &str[0u]);
  1959. out_fnct(str);
  1960. out_fnct(" | ");
  1961. (void)Str_FmtNbr_Int32U(rem_size,
  1962. 10u,
  1963. DEF_NBR_BASE_DEC,
  1964. ' ',
  1965. DEF_NO,
  1966. DEF_YES,
  1967. &str[0u]);
  1968. out_fnct(str);
  1969. out_fnct(" | ");
  1970. out_fnct((p_seg->NamePtr != DEF_NULL) ? (CPU_CHAR *)p_seg->NamePtr : (CPU_CHAR *)"Unknown");
  1971. out_fnct("\r\n");
  1972. p_alloc = p_seg->AllocInfoHeadPtr;
  1973. while (p_alloc != DEF_NULL) {
  1974. out_fnct("| -> Obj | ");
  1975. (void)Str_FmtNbr_Int32U(p_alloc->Size,
  1976. 10u,
  1977. DEF_NBR_BASE_DEC,
  1978. ' ',
  1979. DEF_NO,
  1980. DEF_YES,
  1981. &str[0u]);
  1982. out_fnct(str);
  1983. out_fnct(" | | ");
  1984. out_fnct((p_alloc->NamePtr != DEF_NULL) ? (CPU_CHAR *)p_alloc->NamePtr : (CPU_CHAR *)"Unknown");
  1985. out_fnct("\r\n");
  1986. p_alloc = p_alloc->NextPtr;
  1987. }
  1988. p_seg = p_seg->NextPtr;
  1989. }
  1990. CPU_CRITICAL_EXIT();
  1991. *p_err = LIB_MEM_ERR_NONE;
  1992. }
  1993. #endif
  1994. /*
  1995. *********************************************************************************************************
  1996. *********************************************************************************************************
  1997. * LOCAL FUNCTIONS
  1998. *********************************************************************************************************
  1999. *********************************************************************************************************
  2000. */
  2001. /*
  2002. *********************************************************************************************************
  2003. * Mem_SegCreateCritical()
  2004. *
  2005. * Description : Creates a new memory segment to be used for runtime memory allocation or dynamic pools.
  2006. *
  2007. * Argument(s) : p_name Pointer to segment name.
  2008. *
  2009. * p_seg Pointer to segment data. Must be allocated by caller.
  2010. * ----- Argument validated by caller.
  2011. *
  2012. * seg_base_addr Segment's first byte address.
  2013. *
  2014. * padding_align Padding alignment, in bytes, that will be added to any allocated buffer
  2015. * from this memory segment. MUST be a power of 2.
  2016. * LIB_MEM_PADDING_ALIGN_NONE means no padding.
  2017. * ------------- Argument validated by caller.
  2018. *
  2019. * size Total size of segment, in bytes.
  2020. * ---- Argument validated by caller.
  2021. *
  2022. * Return(s) : Pointer to segment data, if successful.
  2023. *
  2024. * DEF_NULL, otherwise.
  2025. *
  2026. * Caller(s) : Mem_PoolCreate(),
  2027. * Mem_SegCreate().
  2028. *
  2029. * Note(s) : (1) This function MUST be called within a CRITICAL_SECTION.
  2030. *********************************************************************************************************
  2031. */
  2032. static void Mem_SegCreateCritical(const CPU_CHAR *p_name,
  2033. MEM_SEG *p_seg,
  2034. CPU_ADDR seg_base_addr,
  2035. CPU_SIZE_T padding_align,
  2036. CPU_SIZE_T size)
  2037. {
  2038. p_seg->AddrBase = seg_base_addr;
  2039. p_seg->AddrEnd = (seg_base_addr + (size - 1u));
  2040. p_seg->AddrNext = seg_base_addr;
  2041. p_seg->NextPtr = Mem_SegHeadPtr;
  2042. p_seg->PaddingAlign = padding_align;
  2043. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  2044. p_seg->NamePtr = p_name;
  2045. p_seg->AllocInfoHeadPtr = DEF_NULL;
  2046. #else
  2047. (void)&p_name;
  2048. #endif
  2049. Mem_SegHeadPtr = p_seg;
  2050. }
  2051. /*
  2052. *********************************************************************************************************
  2053. * Mem_SegOverlapChkCritical()
  2054. *
  2055. * Description : Checks if existing memory segment exists or overlaps with specified memory area.
  2056. *
  2057. * Argument(s) : seg_base_addr Address of first byte of memory area.
  2058. *
  2059. * size Size of memory area, in bytes.
  2060. *
  2061. * p_err Pointer to variable that will receive the return error code from this function :
  2062. *
  2063. * LIB_MEM_ERR_INVALID_SEG_OVERLAP Segment overlaps another existing segment.
  2064. * LIB_MEM_ERR_INVALID_SEG_EXISTS Segment already exists.
  2065. *
  2066. * Return(s) : Pointer to memory segment that overlaps.
  2067. *
  2068. * DEF_NULL, otherwise.
  2069. *
  2070. * Caller(s) : Mem_PoolCreate(),
  2071. * Mem_SegCreate().
  2072. *
  2073. * Note(s) : (1) This function MUST be called within a CRITICAL_SECTION.
  2074. *********************************************************************************************************
  2075. */
  2076. static MEM_SEG *Mem_SegOverlapChkCritical (CPU_ADDR seg_base_addr,
  2077. CPU_SIZE_T size,
  2078. LIB_ERR *p_err)
  2079. {
  2080. MEM_SEG *p_seg_chk;
  2081. CPU_ADDR seg_new_end;
  2082. CPU_ADDR seg_chk_start;
  2083. CPU_ADDR seg_chk_end;
  2084. seg_new_end = seg_base_addr + (size - 1u);
  2085. p_seg_chk = Mem_SegHeadPtr;
  2086. while (p_seg_chk != DEF_NULL) {
  2087. seg_chk_start = (CPU_ADDR)p_seg_chk->AddrBase;
  2088. seg_chk_end = (CPU_ADDR)p_seg_chk->AddrEnd;
  2089. if ((seg_base_addr == seg_chk_start) && (seg_new_end == seg_chk_end)) {
  2090. *p_err = LIB_MEM_ERR_INVALID_SEG_EXISTS;
  2091. return (p_seg_chk);
  2092. } else if (((seg_base_addr >= seg_chk_start) && (seg_base_addr <= seg_chk_end)) ||
  2093. ((seg_base_addr <= seg_chk_start) && (seg_new_end >= seg_chk_start))) {
  2094. *p_err = LIB_MEM_ERR_INVALID_SEG_OVERLAP;
  2095. return (p_seg_chk);
  2096. }
  2097. p_seg_chk = p_seg_chk->NextPtr;
  2098. }
  2099. *p_err = LIB_MEM_ERR_NONE;
  2100. return (DEF_NULL);
  2101. }
  2102. /*
  2103. *********************************************************************************************************
  2104. * Mem_SegAllocInternal()
  2105. *
  2106. * Description : Allocates memory from specified segment.
  2107. *
  2108. * Argument(s) : p_name Pointer to allocated object name. Used for allocations tracking. May be DEF_NULL.
  2109. *
  2110. * p_seg Pointer to segment from which to allocate memory.
  2111. * ----- Argument validated by caller.
  2112. *
  2113. * size Size of memory block to allocate, in bytes.
  2114. *
  2115. * align Required alignment of memory block, in bytes. MUST be a power of 2.
  2116. *
  2117. * padding_align Padding alignment, in bytes, that will be added to any allocated buffer from
  2118. * this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
  2119. * means no padding.
  2120. *
  2121. * p_bytes_reqd Pointer to variable that will receive the number of free bytes missing for
  2122. * the allocation to succeed. Set to DEF_NULL to skip calculation.
  2123. *
  2124. * p_err Pointer to variable that will receive the return error code from this function :
  2125. *
  2126. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  2127. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  2128. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  2129. *
  2130. * ------------------RETURNED BY Mem_SegAllocExtCritical()------------------
  2131. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  2132. *
  2133. * Return(s) : Pointer to allocated memory block, if successful.
  2134. *
  2135. * DEF_NULL, otherwise.
  2136. *
  2137. * Caller(s) : Mem_DynPoolBlkGet(),
  2138. * Mem_DynPoolCreateInternal(),
  2139. * Mem_HeapAlloc(),
  2140. * Mem_PoolCreate(),
  2141. * Mem_SegAlloc(),
  2142. * Mem_SegAllocExt(),
  2143. * Mem_SegAllocHW().
  2144. *
  2145. * Note(s) : none.
  2146. *********************************************************************************************************
  2147. */
  2148. static void *Mem_SegAllocInternal (const CPU_CHAR *p_name,
  2149. MEM_SEG *p_seg,
  2150. CPU_SIZE_T size,
  2151. CPU_SIZE_T align,
  2152. CPU_SIZE_T padding_align,
  2153. CPU_SIZE_T *p_bytes_reqd,
  2154. LIB_ERR *p_err)
  2155. {
  2156. void *p_blk;
  2157. CPU_SR_ALLOC();
  2158. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  2159. if (p_err == DEF_NULL) { /* Chk for null err ptr. */
  2160. CPU_SW_EXCEPTION(DEF_NULL);
  2161. }
  2162. if (size < 1u) { /* Chk for invalid sized mem req. */
  2163. *p_err = LIB_MEM_ERR_INVALID_MEM_SIZE;
  2164. return (DEF_NULL);
  2165. }
  2166. if (MATH_IS_PWR2(align) != DEF_YES) { /* Chk that align is a pwr of 2. */
  2167. *p_err = LIB_MEM_ERR_INVALID_MEM_ALIGN;
  2168. return (DEF_NULL);
  2169. }
  2170. #endif
  2171. CPU_CRITICAL_ENTER();
  2172. p_blk = Mem_SegAllocExtCritical(p_seg,
  2173. size,
  2174. align,
  2175. padding_align,
  2176. p_bytes_reqd,
  2177. p_err);
  2178. if (*p_err != LIB_MEM_ERR_NONE) {
  2179. CPU_CRITICAL_EXIT();
  2180. return (DEF_NULL);
  2181. }
  2182. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED) /* Track alloc if req'd. */
  2183. Mem_SegAllocTrackCritical(p_name,
  2184. p_seg,
  2185. size,
  2186. p_err);
  2187. if (*p_err != LIB_MEM_ERR_NONE) {
  2188. CPU_CRITICAL_EXIT();
  2189. return (DEF_NULL);
  2190. }
  2191. #else
  2192. (void)&p_name;
  2193. #endif
  2194. CPU_CRITICAL_EXIT();
  2195. return (p_blk);
  2196. }
  2197. /*
  2198. *********************************************************************************************************
  2199. * Mem_SegAllocExtCritical()
  2200. *
  2201. * Description : Allocates memory from specified segment.
  2202. *
  2203. * Argument(s) : p_seg Pointer to segment from which to allocate memory.
  2204. *
  2205. * size Size of memory block to allocate, in bytes.
  2206. *
  2207. * align Required alignment of memory block, in bytes. MUST be a power of 2.
  2208. *
  2209. * padding_align Padding alignment, in bytes, that will be added to any allocated buffer from
  2210. * this memory segment. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
  2211. * means no padding.
  2212. *
  2213. * p_bytes_reqd Pointer to variable that will receive the number of free bytes missing for
  2214. * the allocation to succeed. Set to DEF_NULL to skip calculation.
  2215. *
  2216. * p_err Pointer to variable that will receive the return error code from this function :
  2217. *
  2218. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  2219. *
  2220. * Return(s) : Pointer to allocated memory block, if successful.
  2221. *
  2222. * DEF_NULL, otherwise.
  2223. *
  2224. * Caller(s) : Mem_PoolCreate(),
  2225. * Mem_SegAllocInternal(),
  2226. * Mem_SegAllocTrackCritical().
  2227. *
  2228. * Note(s) : (1) This function MUST be called within a CRITICAL_SECTION.
  2229. *********************************************************************************************************
  2230. */
  2231. static void *Mem_SegAllocExtCritical (MEM_SEG *p_seg,
  2232. CPU_SIZE_T size,
  2233. CPU_SIZE_T align,
  2234. CPU_SIZE_T padding_align,
  2235. CPU_SIZE_T *p_bytes_reqd,
  2236. LIB_ERR *p_err)
  2237. {
  2238. CPU_ADDR blk_addr;
  2239. CPU_ADDR addr_next;
  2240. CPU_SIZE_T size_rem_seg;
  2241. CPU_SIZE_T size_tot_blk;
  2242. CPU_SIZE_T blk_align = DEF_MAX(align, padding_align);
  2243. blk_addr = MATH_ROUND_INC_UP_PWR2(p_seg->AddrNext, /* Compute align'ed blk addr. */
  2244. blk_align);
  2245. addr_next = MATH_ROUND_INC_UP_PWR2(blk_addr + size, /* Compute addr of next alloc. */
  2246. padding_align);
  2247. size_rem_seg = p_seg->AddrEnd - p_seg->AddrNext + 1u;
  2248. size_tot_blk = addr_next - p_seg->AddrNext; /* Compute tot blk size including align and padding. */
  2249. if (size_rem_seg < size_tot_blk) { /* If seg doesn't have enough space ... */
  2250. if (p_bytes_reqd != DEF_NULL) { /* ... calc nbr of req'd bytes. */
  2251. *p_bytes_reqd = size_tot_blk - size_rem_seg;
  2252. }
  2253. *p_err = LIB_MEM_ERR_SEG_OVF;
  2254. return (DEF_NULL);
  2255. }
  2256. p_seg->AddrNext = addr_next;
  2257. *p_err = LIB_MEM_ERR_NONE;
  2258. return ((void *)blk_addr);
  2259. }
  2260. /*
  2261. *********************************************************************************************************
  2262. * Mem_SegAllocTrackCritical()
  2263. *
  2264. * Description : Tracks segment allocation, adding the 'size' of the allocation under the 'p_name' entry.
  2265. *
  2266. * Argument(s) : p_name Pointer to the name of the object. This string is not copied and its memory should
  2267. * remain accessible at all times.
  2268. *
  2269. * p_seg Pointer to segment data.
  2270. *
  2271. * size Allocation size, in bytes.
  2272. *
  2273. * p_err Pointer to variable that will receive the return error code from this function :
  2274. *
  2275. * LIB_MEM_ERR_HEAP_EMPTY No more memory available on heap
  2276. *
  2277. * --------------RETURNED BY Mem_SegAllocExtCritical()---------------
  2278. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  2279. *
  2280. * Return(s) : none.
  2281. *
  2282. * Caller(s) : Mem_PoolCreate(),
  2283. * Mem_SegAllocInternal().
  2284. *
  2285. * Note(s) : none.
  2286. *********************************************************************************************************
  2287. */
  2288. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  2289. static void Mem_SegAllocTrackCritical (const CPU_CHAR *p_name,
  2290. MEM_SEG *p_seg,
  2291. CPU_SIZE_T size,
  2292. LIB_ERR *p_err)
  2293. {
  2294. MEM_ALLOC_INFO *p_alloc;
  2295. /* ------- UPDATE ALLOC INFO LIST, IF POSSIBLE -------- */
  2296. p_alloc = p_seg->AllocInfoHeadPtr;
  2297. while (p_alloc != DEF_NULL) {
  2298. if (p_alloc->NamePtr == p_name) {
  2299. p_alloc->Size += size;
  2300. *p_err = LIB_MEM_ERR_NONE;
  2301. return;
  2302. }
  2303. p_alloc = p_alloc->NextPtr;
  2304. }
  2305. /* --------- ADD NEW ALLOC INFO ENTRY IN LIST --------- */
  2306. p_alloc = Mem_SegAllocExtCritical(&Mem_SegHeap, /* Alloc new alloc info struct on heap. */
  2307. sizeof(MEM_ALLOC_INFO),
  2308. sizeof(CPU_ALIGN),
  2309. LIB_MEM_PADDING_ALIGN_NONE,
  2310. DEF_NULL,
  2311. p_err);
  2312. if (*p_err != LIB_MEM_ERR_NONE) {
  2313. return;
  2314. }
  2315. p_alloc->NamePtr = p_name; /* Populate alloc info. */
  2316. p_alloc->Size = size;
  2317. p_alloc->NextPtr = p_seg->AllocInfoHeadPtr; /* Prepend new item in list. */
  2318. p_seg->AllocInfoHeadPtr = p_alloc;
  2319. }
  2320. #endif
  2321. /*
  2322. *********************************************************************************************************
  2323. * Mem_DynPoolCreateInternal()
  2324. *
  2325. * Description : Creates a dynamic memory pool.
  2326. *
  2327. * Argument(s) : p_name Pointer to pool name.
  2328. *
  2329. * p_pool Pointer to pool data.
  2330. *
  2331. * p_seg Pointer to segment from which to allocate memory.
  2332. *
  2333. * blk_size Size of memory block to allocate from pool, in bytes. See Note #1.
  2334. *
  2335. * blk_align Required alignment of memory block, in bytes. MUST be a power of 2.
  2336. *
  2337. * blk_padding_align Block's padding alignment, in bytes, that will be added at the end
  2338. * of block's buffer. MUST be a power of 2. LIB_MEM_PADDING_ALIGN_NONE
  2339. * means no padding.
  2340. *
  2341. * blk_qty_init Initial number of elements to be allocated in pool.
  2342. *
  2343. * blk_qty_max Maximum number of elements that can be allocated from this pool. Set to
  2344. * LIB_MEM_BLK_QTY_UNLIMITED if no limit.
  2345. *
  2346. * p_err Pointer to variable that will receive the return error code from this function :
  2347. *
  2348. * LIB_MEM_ERR_INVALID_BLK_ALIGN Invalid requested block alignment.
  2349. * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid requested block size.
  2350. * LIB_MEM_ERR_INVALID_BLK_NBR Invalid requested block quantity max.
  2351. * LIB_MEM_ERR_NULL_PTR Pool data pointer NULL.
  2352. *
  2353. * ------------------RETURNED BY Mem_SegAllocInternal()-------------------
  2354. * LIB_MEM_ERR_INVALID_MEM_ALIGN Invalid memory block alignment requested.
  2355. * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory block size specified.
  2356. * LIB_MEM_ERR_NULL_PTR Error or segment data pointer NULL.
  2357. * LIB_MEM_ERR_SEG_OVF Allocation would overflow memory segment.
  2358. *
  2359. * Return(s) : None.
  2360. *
  2361. * Caller(s) : Mem_DynPoolCreate(),
  2362. * Mem_DynPoolCreateHW().
  2363. *
  2364. * Note(s) : (1) 'blk_size' must be big enough to fit a pointer since the pointer to the next free
  2365. * block is stored in the block itself (only when free/unused).
  2366. *********************************************************************************************************
  2367. */
  2368. static void Mem_DynPoolCreateInternal (const CPU_CHAR *p_name,
  2369. MEM_DYN_POOL *p_pool,
  2370. MEM_SEG *p_seg,
  2371. CPU_SIZE_T blk_size,
  2372. CPU_SIZE_T blk_align,
  2373. CPU_SIZE_T blk_padding_align,
  2374. CPU_SIZE_T blk_qty_init,
  2375. CPU_SIZE_T blk_qty_max,
  2376. LIB_ERR *p_err)
  2377. {
  2378. CPU_INT08U *p_blks;
  2379. CPU_SIZE_T blk_size_align;
  2380. CPU_SIZE_T blk_align_worst = DEF_MAX(blk_align, blk_padding_align);
  2381. #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
  2382. if (p_err == DEF_NULL) { /* Chk for NULL err ptr. */
  2383. CPU_SW_EXCEPTION(DEF_NULL);
  2384. }
  2385. if (p_pool == DEF_NULL) { /* Chk for NULL pool data ptr. */
  2386. *p_err = LIB_MEM_ERR_NULL_PTR;
  2387. return;
  2388. }
  2389. if (blk_size < 1u) { /* Chk for inv blk size. */
  2390. *p_err = LIB_MEM_ERR_INVALID_BLK_SIZE;
  2391. return;
  2392. }
  2393. if ((blk_qty_max != LIB_MEM_BLK_QTY_UNLIMITED) && /* Chk for invalid blk qty. */
  2394. (blk_qty_init > blk_qty_max)) {
  2395. *p_err = LIB_MEM_ERR_INVALID_BLK_NBR;
  2396. return;
  2397. }
  2398. if (MATH_IS_PWR2(blk_align) != DEF_YES) { /* Chk for illegal align spec. */
  2399. *p_err = LIB_MEM_ERR_INVALID_BLK_ALIGN;
  2400. return;
  2401. }
  2402. #endif
  2403. /* Calc blk size with align. */
  2404. if (blk_size < sizeof(void *)) { /* If size if smaller than ptr ... */
  2405. /* ... inc size to ptr size. */
  2406. blk_size_align = MATH_ROUND_INC_UP_PWR2(sizeof(void *), blk_align_worst);
  2407. } else {
  2408. blk_size_align = MATH_ROUND_INC_UP_PWR2(blk_size, blk_align_worst);
  2409. }
  2410. if (blk_qty_init != 0u) { /* Alloc init blks. */
  2411. p_blks = (CPU_INT08U *)Mem_SegAllocInternal(p_name,
  2412. p_seg,
  2413. blk_size_align * blk_qty_init,
  2414. blk_align_worst,
  2415. LIB_MEM_PADDING_ALIGN_NONE,
  2416. DEF_NULL,
  2417. p_err);
  2418. if (*p_err != LIB_MEM_ERR_NONE) {
  2419. return;
  2420. }
  2421. }
  2422. /* ----------------- CREATE POOL DATA ----------------- */
  2423. p_pool->PoolSegPtr = p_seg;
  2424. p_pool->BlkSize = blk_size;
  2425. p_pool->BlkAlign = blk_align_worst;
  2426. p_pool->BlkPaddingAlign = blk_padding_align;
  2427. p_pool->BlkQtyMax = blk_qty_max;
  2428. p_pool->BlkAllocCnt = 0u;
  2429. if (blk_qty_init != 0u) { /* Init free list. */
  2430. CPU_SIZE_T i;
  2431. p_pool->BlkFreePtr = (void *)p_blks;
  2432. for (i = 0u; i < blk_qty_init - 1u; i++) {
  2433. *((void **)p_blks) = p_blks + blk_size_align;
  2434. p_blks += blk_size_align;
  2435. }
  2436. *((void **)p_blks) = DEF_NULL;
  2437. } else {
  2438. p_pool->BlkFreePtr = DEF_NULL;
  2439. }
  2440. #if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
  2441. p_pool->NamePtr = p_name;
  2442. #endif
  2443. *p_err = LIB_MEM_ERR_NONE;
  2444. }
  2445. /*
  2446. *********************************************************************************************************
  2447. * Mem_PoolBlkIsValidAddr()
  2448. *
  2449. * Description : Calculates if a given memory block address is valid for the memory pool.
  2450. *
  2451. * Argument(s) : p_pool Pointer to memory pool structure to validate memory block address.
  2452. * ------ Argument validated by caller.
  2453. *
  2454. * p_mem Pointer to memory block address to validate.
  2455. * ----- Argument validated by caller.
  2456. *
  2457. * Return(s) : DEF_YES, if valid memory pool block address.
  2458. *
  2459. * DEF_NO, otherwise.
  2460. *
  2461. * Caller(s) : Mem_PoolBlkFree().
  2462. *
  2463. * Note(s) : none.
  2464. *********************************************************************************************************
  2465. */
  2466. #if ((LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) && \
  2467. (LIB_MEM_CFG_HEAP_SIZE > 0u))
  2468. static CPU_BOOLEAN Mem_PoolBlkIsValidAddr (MEM_POOL *p_pool,
  2469. void *p_mem)
  2470. {
  2471. CPU_ADDR pool_offset;
  2472. if ((p_mem < p_pool->PoolAddrStart) ||
  2473. (p_mem > p_pool->PoolAddrEnd)) {
  2474. return (DEF_FALSE);
  2475. }
  2476. pool_offset = (CPU_ADDR)p_mem - (CPU_ADDR)p_pool->PoolAddrStart;
  2477. if (pool_offset % p_pool->BlkSize != 0u) {
  2478. return (DEF_FALSE);
  2479. } else {
  2480. return (DEF_TRUE);
  2481. }
  2482. }
  2483. #endif