cmsis_os2.c 145 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335
  1. /**
  2. ******************************************************************************
  3. * @file cmsis_os2.c
  4. * @author MCD Application Team
  5. * @brief CMSIS RTOS2 wrapper for AzureRTOS ThreadX
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2020 STMicroelectronics.
  10. * Copyright (c) 2023 HPMicro
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /**
  20. * Important note
  21. * --------------
  22. * This file is the implementation of functions to wrap CMSIS RTOS2 onto
  23. * AzureRTOS ThreadX based on API published by Arm Limited in cmsis_os2.h.
  24. * The implementation of these functions is inspired from an original work from
  25. * Arm Limited to wrap CMSIS RTOS2 onto FreeRTOS (see copyright and license
  26. * information below).
  27. * The whole contents of this file is a creation by STMicroelectronics licensed
  28. * to you under the License as specified above. However, some functions
  29. * originally created by Arm Limited have not been strongly reworked by
  30. * STMicroelectronics and are still available under their Apache License,
  31. * Version 2.0 original terms; these original functions are:
  32. * - osKernelGetInfo
  33. * - osKernelStart
  34. * - osKernelGetTickCount
  35. * - osKernelGetTickFreq
  36. * - osKernelGetSysTimerFreq
  37. * - osDelay
  38. * - osDelayUntil
  39. * - osThreadGetId
  40. * - osTimerIsRunning
  41. */
  42. /* --------------------------------------------------------------------------
  43. * Copyright (c) 2013-2019 Arm Limited. All rights reserved.
  44. *
  45. * SPDX-License-Identifier: Apache-2.0
  46. *
  47. * Licensed under the Apache License, Version 2.0 (the License); you may
  48. * not use this file except in compliance with the License.
  49. * You may obtain a copy of the License at
  50. *
  51. * www.apache.org/licenses/LICENSE-2.0
  52. *
  53. * Unless required by applicable law or agreed to in writing, software
  54. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  55. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  56. * See the License for the specific language governing permissions and
  57. * limitations under the License.
  58. *
  59. * Name: cmsis_os2.c
  60. * Purpose: CMSIS RTOS2 wrapper for AzureRTOS ThreadX
  61. *
  62. *---------------------------------------------------------------------------*/
  63. #include <string.h>
  64. /* ::CMSIS:RTOS2 */
  65. #include "cmsis_os2.h"
  66. #include "tx_api.h"
  67. #include "tx_initialize.h"
  68. #include "tx_thread.h"
  69. #include "tx_timer.h"
  70. #include "tx_byte_pool.h"
  71. #include "tx_event_flags.h"
  72. #include "tx_mutex.h"
  73. #include "tx_semaphore.h"
  74. #include "tx_queue.h"
  75. #include "tx_block_pool.h"
  76. #include "hpm_soc.h"
  77. #include "hpm_mchtmr_drv.h"
  78. #include "hpm_clock_drv.h"
  79. /*---------------------------------------------------------------------------*/
  80. /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
  81. #define KERNEL_VERSION (((uint32_t)THREADX_MAJOR_VERSION * 10000000UL) + \
  82. ((uint32_t)THREADX_MINOR_VERSION * 10000UL) + \
  83. ((uint32_t)THREADX_PATCH_VERSION * 1UL))
  84. #define KERNEL_ID ("Azure RTOS ThreadX")
  85. #define IS_IRQ_MODE() (read_csr(CSR_MSCRATCH) != 0U)
  86. /* Default thread stack size */
  87. #ifndef RTOS2_DEFAULT_THREAD_STACK_SIZE
  88. #define RTOS2_DEFAULT_THREAD_STACK_SIZE 1024
  89. #endif
  90. /* Default thread stack size */
  91. #define RTOS2_INTERNAL_BYTE_POOL_SIZE 256
  92. /* Default use memory pool allocation */
  93. #define USE_MEMORY_POOL_ALLOCATION 1
  94. #ifndef USE_DYNAMIC_MEMORY_ALLOCATION
  95. #ifndef USE_MEMORY_POOL_ALLOCATION
  96. #error "CMSIS RTOS ThreadX Wrapper cmsis_os2.c: USE_DYNAMIC_MEMORY_ALLOCATION or USE_MEMORY_POOL_ALLOCATION must be defined"
  97. #endif
  98. #endif
  99. /* Default stack byte pool memory size */
  100. #ifndef RTOS2_BYTE_POOL_STACK_SIZE
  101. #define RTOS2_BYTE_POOL_STACK_SIZE 32 * 1024
  102. #endif
  103. /* Default stack byte pool memory size */
  104. #ifndef RTOS2_BYTE_POOL_HEAP_SIZE
  105. #define RTOS2_BYTE_POOL_HEAP_SIZE 4 * 1024
  106. #endif
  107. /* Default time slice for the created threads */
  108. #ifndef RTOS2_DEFAULT_TIME_SLICE
  109. #define RTOS2_DEFAULT_TIME_SLICE 4
  110. #endif
  111. /* Default stack byte pool memory type */
  112. #define RTOS2_BYTE_POOL_STACK_TYPE 1
  113. /* Default stack byte pool memory type */
  114. #define RTOS2_BYTE_POOL_HEAP_TYPE 2
  115. #ifndef TX_THREAD_USER_EXTENSION
  116. #error "CMSIS RTOS ThreadX Wrapper: TX_THREAD_USER_EXTENSION must be defined as tx_thread_detached_joinable (ULONG) in tx_user.h file"
  117. #endif
  118. #ifdef TX_DISABLE_ERROR_CHECKING
  119. #error "CMSIS RTOS ThreadX Wrapper : TX_DISABLE_ERROR_CHECKING must be undefined"
  120. #endif
  121. /* Ensure the maximum number of priorities is modified by the user to 64. */
  122. #if(TX_MAX_PRIORITIES != 64)
  123. #error "CMSIS RTOS ThreadX Wrapper: TX_MAX_PRIORITIES must be fixed to 64 in tx_user.h file"
  124. #endif
  125. /*---------------------------------------------------------------------------*/
  126. static osKernelState_t KernelState = osKernelInactive;
  127. extern uint32_t SystemCoreClock;
  128. TX_BYTE_POOL HeapBytePool;
  129. TX_BYTE_POOL StackBytePool;
  130. TX_BLOCK_POOL BlockPool;
  131. /*---------------------------------------------------------------------------*/
  132. /*-------------------CMSIS RTOS2 Internal Functions--------------------------*/
  133. /*---------------------------------------------------------------------------*/
  134. /**
  135. * @brief The function MemAlloc allocates thread, timer, mutex, semaphore,
  136. * event flags and message queue block object memory.
  137. * Or it allocates the thread or message queue stack memory.
  138. * @param [in] memory size to be allocated from BytePool
  139. * [in] to be allocated memory type (Heap or Stack)
  140. * @retval pointer to the allocated memory or NULL in case of error.
  141. */
  142. static uint8_t *MemAlloc(uint32_t mem_size, uint8_t pool_type)
  143. {
  144. /* The output pointer to the allocated memory or NULL in case of error */
  145. uint8_t *mem_ptr;
  146. /* Allocated memory size */
  147. uint32_t allocated_mem_size = mem_size;
  148. /* Pointer to the BytePool to be used for memory allocation */
  149. TX_BYTE_POOL *byte_pool;
  150. /* Check if the memory size is invalid or the BytePool type is wrong */
  151. if ((mem_size == 0) || (pool_type > RTOS2_BYTE_POOL_HEAP_TYPE))
  152. {
  153. /* Return NULL in case of error */
  154. mem_ptr = NULL;
  155. }
  156. else
  157. {
  158. /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */
  159. if (allocated_mem_size < TX_BYTE_POOL_MIN)
  160. {
  161. /* We should at least allocate TX_BYTE_POOL_MIN */
  162. allocated_mem_size = TX_BYTE_POOL_MIN;
  163. }
  164. /* Assign the BytePool to be used (StackBytePool or HeapBytePool) */
  165. if (pool_type == RTOS2_BYTE_POOL_STACK_TYPE)
  166. {
  167. /* Point to the Stack BytePool */
  168. byte_pool = &StackBytePool;
  169. }
  170. else
  171. {
  172. /* Point to the Heap BytePool */
  173. byte_pool = &HeapBytePool;
  174. }
  175. /* Allocate the mem_ptr */
  176. if (tx_byte_allocate(byte_pool, (void **) &mem_ptr, allocated_mem_size, TX_NO_WAIT) != TX_SUCCESS)
  177. {
  178. /* Return NULL in case of error */
  179. mem_ptr = NULL;
  180. }
  181. }
  182. return (mem_ptr);
  183. }
  184. /**
  185. * @brief The function MemFree allocates thread, timer, mutex, semaphore,
  186. * event flags and message queue block object memory.
  187. * Or it allocates the thread or message queue stack memory.
  188. * @param [in] memory size to be allocated from BytePool
  189. * [in] to be allocated memory type (Heap or Stack)
  190. * @retval pointer to the allocated memory or NULL in case of error.
  191. */
  192. static osStatus_t MemFree(VOID *memory_ptr)
  193. {
  194. /* The output status code that indicates the execution status */
  195. osStatus_t status = osOK;
  196. /* Check if the memory_ptr is invalid */
  197. if (memory_ptr == NULL)
  198. {
  199. /* Return osError in case of error */
  200. status = osError;
  201. }
  202. else
  203. {
  204. /* Free the allocated memory_ptr */
  205. if (tx_byte_release(memory_ptr) != TX_SUCCESS)
  206. {
  207. /* Return osError in case of error */
  208. status = osError;
  209. }
  210. }
  211. return (status);
  212. }
  213. /**
  214. * @brief The function MemInit creates memory pools for stack and heap.
  215. * The stack pool is used for threads and queues stacks allocations.
  216. * The heap pool is used for threads, timers, mutex, semaphores,
  217. * message queues and events flags control block object memory allocations.
  218. * The size of stack and heap pools are user configured using the
  219. * RTOS2_BYTE_POOL_STACK_SIZE and RTOS2_BYTE_POOL_HEAP_SIZE flags.
  220. * @param none.
  221. * @retval status code that indicates the execution status of the function.
  222. */
  223. static osStatus_t MemInit(void)
  224. {
  225. /* Allocated memory size */
  226. uint32_t bytepool_size = RTOS2_BYTE_POOL_STACK_SIZE;
  227. #ifdef USE_DYNAMIC_MEMORY_ALLOCATION
  228. /* Unused memory address */
  229. CHAR *unused_memory = NULL;
  230. #else
  231. #ifdef USE_MEMORY_POOL_ALLOCATION
  232. CHAR *unused_memory_Stack = NULL;
  233. CHAR *unused_memory_Heap = NULL;
  234. #endif
  235. #endif
  236. /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */
  237. if (bytepool_size < TX_BYTE_POOL_MIN)
  238. {
  239. /* We should at least allocate TX_BYTE_POOL_MIN */
  240. bytepool_size = TX_BYTE_POOL_MIN;
  241. }
  242. /* Initialize the Heap BytePool address */
  243. #ifdef USE_DYNAMIC_MEMORY_ALLOCATION
  244. unused_memory = (CHAR *)_tx_initialize_unused_memory;
  245. #elif USE_MEMORY_POOL_ALLOCATION
  246. static CHAR freememStack[RTOS2_BYTE_POOL_STACK_SIZE + RTOS2_INTERNAL_BYTE_POOL_SIZE];
  247. static CHAR freememHeap[RTOS2_BYTE_POOL_HEAP_SIZE + RTOS2_INTERNAL_BYTE_POOL_SIZE];
  248. unused_memory_Stack = (CHAR *)freememStack;
  249. unused_memory_Heap = (CHAR *)freememHeap;
  250. #endif
  251. #ifdef USE_DYNAMIC_MEMORY_ALLOCATION
  252. /* Create a byte memory pool from which to allocate the timer control
  253. block */
  254. if (tx_byte_pool_create(&StackBytePool, "Byte Pool Stack", unused_memory,
  255. RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS)
  256. {
  257. /* Return osError in case of error */
  258. return (osError);
  259. }
  260. else
  261. {
  262. /* Set the tx_initialize_unused_memory address */
  263. unused_memory += RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size;
  264. }
  265. /* Set bytepool_size to the user configured Heap size */
  266. bytepool_size = RTOS2_BYTE_POOL_HEAP_SIZE;
  267. /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */
  268. if (bytepool_size < TX_BYTE_POOL_MIN)
  269. {
  270. /* We should at least allocate TX_BYTE_POOL_MIN */
  271. bytepool_size = TX_BYTE_POOL_MIN;
  272. }
  273. /* Create a byte memory pool from which to allocate the timer control
  274. block */
  275. if (tx_byte_pool_create(&HeapBytePool, "Byte Pool Heap", unused_memory,
  276. RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS)
  277. {
  278. /* Return osError in case of error */
  279. return (osError);
  280. }
  281. else
  282. {
  283. /* Set the tx_initialize_unused_memory address */
  284. unused_memory += RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size;
  285. }
  286. /* Update the _tx_initialize_unused_memory */
  287. _tx_initialize_unused_memory = unused_memory;
  288. #else
  289. #ifdef USE_MEMORY_POOL_ALLOCATION
  290. /* Create a byte memory pool from which to allocate the timer control
  291. block */
  292. if (tx_byte_pool_create(&StackBytePool, "Byte Pool Stack", unused_memory_Stack,
  293. RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS)
  294. {
  295. /* Return osError in case of error */
  296. return (osError);
  297. }
  298. /* Set bytepool_size to the user configured Heap size */
  299. bytepool_size = RTOS2_BYTE_POOL_HEAP_SIZE;
  300. /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */
  301. if (bytepool_size < TX_BYTE_POOL_MIN)
  302. {
  303. /* We should at least allocate TX_BYTE_POOL_MIN */
  304. bytepool_size = TX_BYTE_POOL_MIN;
  305. }
  306. /* Create a byte memory pool from which to allocate the timer control
  307. block */
  308. if (tx_byte_pool_create(&HeapBytePool, "Byte Pool Heap", unused_memory_Heap,
  309. RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS)
  310. {
  311. /* Return osError in case of error */
  312. return (osError);
  313. }
  314. #endif
  315. #endif
  316. return (osOK);
  317. }
  318. /*---------------------------------------------------------------------------*/
  319. /*---------------------------Kenel Management APIs---------------------------*/
  320. /*---------------------------------------------------------------------------*/
  321. /**
  322. * @brief The function osKernelInitialize initializes the RTOS Kernel. Before
  323. * it is successfully executed, only the functions osKernelGetInfo and
  324. * osKernelGetState may be called.
  325. * Note : This function cannot be called from Interrupt Service
  326. * Routines.
  327. * @param none
  328. * @retval status code that indicates the execution status of the function.
  329. */
  330. osStatus_t osKernelInitialize(void)
  331. {
  332. /* The output status code that indicates the execution status */
  333. osStatus_t status;
  334. /* Check if this API is called from Interrupt Service Routines */
  335. if (IS_IRQ_MODE())
  336. {
  337. /* Return osErrorISR in case of error */
  338. status = osErrorISR;
  339. }
  340. else
  341. {
  342. /* Check if the kernel state is osKernelInactive */
  343. if (KernelState == osKernelInactive)
  344. {
  345. /* Initialize the kernel */
  346. _tx_initialize_kernel_setup();
  347. /* Initialize the Heap and stack memory BytePools */
  348. if (MemInit() == osOK)
  349. {
  350. /* Set the kernel state to osKernelReady */
  351. KernelState = osKernelReady;
  352. /* Return osOK in case of success */
  353. status = osOK;
  354. }
  355. else
  356. {
  357. /* Return osError in case of error */
  358. status = osError;
  359. }
  360. }
  361. else
  362. {
  363. /* Return osError in case of error */
  364. status = osError;
  365. }
  366. }
  367. return (status);
  368. }
  369. /**
  370. * @brief The function osKernelGetInfo retrieves the API and kernel version
  371. * of the underlying RTOS kernel and a human readable identifier string
  372. * for the kernel. It can be safely called before the RTOS is
  373. * initialized or started (call to osKernelInitialize or osKernelStart)
  374. * Note : This function may be called from Interrupt Service
  375. * Routines.
  376. * @param [out] version pointer to buffer for retrieving version information.
  377. * [out] id_buf pointer to buffer for retrieving kernel identification
  378. * string.
  379. * [in] id_size size of buffer for kernel identification string.
  380. * @retval status code that indicates the execution status of the function.
  381. */
  382. osStatus_t osKernelGetInfo(osVersion_t *version, char *id_buf, uint32_t id_size)
  383. {
  384. /* The output status code that indicates the execution status */
  385. osStatus_t status = osOK;
  386. /* Check if input version pointer is not NULL */
  387. if (version != NULL)
  388. {
  389. /* Version encoding is major.minor.rev: mmnnnrrrr dec */
  390. version->api = KERNEL_VERSION;
  391. version->kernel = KERNEL_VERSION;
  392. }
  393. else
  394. {
  395. /* Return osError in case of error */
  396. status = osError;
  397. }
  398. /* Check if input id_buf pointer is not NULL and id_size != 0 */
  399. if ((id_buf != NULL) && (id_size != 0U))
  400. {
  401. if (id_size > sizeof(KERNEL_ID))
  402. {
  403. id_size = sizeof(KERNEL_ID);
  404. }
  405. memcpy(id_buf, KERNEL_ID, id_size);
  406. }
  407. else
  408. {
  409. /* Return osError in case of error */
  410. status = osError;
  411. }
  412. return (status);
  413. }
  414. /**
  415. * @brief The function osKernelGetState returns the current state of the
  416. * kernel and can be safely called before the RTOS is initialized or
  417. * started (call to osKernelInitialize or osKernelStart). In case it
  418. * fails it will return osKernelError, otherwise it returns the kernel
  419. * state (refer to osKernelState_t for the list of kernel states).
  420. * Note : This function may be called from Interrupt Service
  421. * Routines.
  422. * @param none
  423. * @retval current RTOS Kernel state.
  424. */
  425. osKernelState_t osKernelGetState(void)
  426. {
  427. return (KernelState);
  428. }
  429. /**
  430. * @brief The function osKernelStart starts the RTOS kernel and begins thread
  431. * switching. It will not return to its calling function in case of
  432. * success. Before it is successfully executed, only the functions
  433. * osKernelGetInfo, osKernelGetState, and object creation functions
  434. * (osXxxNew) may be called.
  435. * Note : This function cannot be called from Interrupt Service
  436. * Routines.
  437. * @param none
  438. * @retval status code that indicates the execution status of the function.
  439. */
  440. osStatus_t osKernelStart(void)
  441. {
  442. /* The output status code that indicates the execution status */
  443. osStatus_t status;
  444. /* Check if this API is called from Interrupt Service Routines */
  445. if (IS_IRQ_MODE())
  446. {
  447. /* Return osErrorISR in case of error */
  448. status = osErrorISR;
  449. }
  450. else
  451. {
  452. /* Check if the kernel state is osKernelReady */
  453. if (KernelState == osKernelReady)
  454. {
  455. /* Set the kernel state to osKernelRunning */
  456. KernelState = osKernelRunning;
  457. /* Return osOK in case of success */
  458. status = osOK;
  459. /* Start the Kernel */
  460. tx_kernel_enter();
  461. }
  462. else
  463. {
  464. /* Return osError in case of error */
  465. status = osError;
  466. }
  467. }
  468. return (status);
  469. }
  470. /**
  471. * @brief The function osKernelGetTickCount returns the current RTOS kernel
  472. * tick count.
  473. * Note : This function may be called from Interrupt Service
  474. * Routines.
  475. * @param none
  476. * @retval RTOS kernel current tick count.
  477. */
  478. uint32_t osKernelGetTickCount(void)
  479. {
  480. /* The output RTOS kernel current tick count */
  481. uint32_t ticks;
  482. /* Get the RTOS kernel current tick count */
  483. ticks = (uint32_t)tx_time_get();
  484. return (ticks);
  485. }
  486. /**
  487. * @brief The function osKernelGetTickFreq returns the frequency of the
  488. * current RTOS kernel tick.
  489. * Note : This function may be called from Interrupt Service
  490. * Routines.
  491. * @param none
  492. * @retval frequency of the kernel tick in hertz, i.e. kernel ticks per second.
  493. */
  494. uint32_t osKernelGetTickFreq(void)
  495. {
  496. return (TX_TIMER_TICKS_PER_SECOND);
  497. }
  498. /**
  499. * @brief The function osKernelGetSysTimerCount returns the current RTOS
  500. * kernel system timer as a 32-bit value. The value is a rolling 32-bit
  501. * counter that is composed of the kernel system interrupt timer value
  502. * and the counter that counts these interrupts (RTOS kernel ticks).
  503. * This function allows the implementation of very short timeout checks
  504. * below the RTOS tick granularity. Such checks might be required when
  505. * checking for a busy status in a device or peripheral initialization
  506. * routine, see code example below.
  507. * Note : This function may be called from Interrupt Service
  508. * Routines.
  509. * @param none
  510. * @retval RTOS kernel current system timer count as 32-bit value.
  511. */
  512. uint32_t osKernelGetSysTimerCount(void)
  513. {
  514. return (uint32_t)(mchtmr_get_count(HPM_MCHTMR));
  515. }
  516. /**
  517. * @brief The function osKernelGetSysTimerFreq returns the frequency of the
  518. * current RTOS kernel system timer.
  519. * Note : This function may be called from Interrupt Service
  520. * Routines.
  521. * @param none
  522. * @retval frequency of the system timer in hertz, i.e. timer ticks per second.
  523. */
  524. uint32_t osKernelGetSysTimerFreq(void)
  525. {
  526. return (clock_get_frequency(clock_mchtmr0));
  527. }
  528. /*---------------------------------------------------------------------------*/
  529. /*-----------------------------Generic Wait APIs-----------------------------*/
  530. /*---------------------------------------------------------------------------*/
  531. /**
  532. * @brief The function osDelay waits for a time period specified in kernel
  533. * ticks. For a value of 1 the system waits until the next timer tick
  534. * occurs. The actual time delay may be up to one timer tick less than
  535. * specified, i.e. calling osDelay(1) right before the next system tick
  536. * occurs the thread is rescheduled immediately.
  537. * The delayed thread is put into the BLOCKED state and a context
  538. * switch occurs immediately. The thread is automatically put back to
  539. * the READY state after the given amount of ticks has elapsed. If the
  540. * thread will have the highest priority in READY state it will being
  541. * scheduled immediately.
  542. * Note : This function cannot be called from Interrupt Service
  543. * Routines.
  544. * @param [in] ticks time ticks value
  545. * @retval status code that indicates the execution status of the function.
  546. */
  547. osStatus_t osDelay(uint32_t ticks)
  548. {
  549. /* The output status code that indicates the execution status */
  550. osStatus_t status;
  551. /* Check if this API is called from Interrupt Service Routines */
  552. if (IS_IRQ_MODE())
  553. {
  554. /* Return osErrorISR in case of error */
  555. status = osErrorISR;
  556. }
  557. else
  558. {
  559. /* Return osOK in case of success */
  560. status = osOK;
  561. /* Check that the input ticks != 0 */
  562. if (ticks != 0U)
  563. {
  564. /* Sleep the thread */
  565. tx_thread_sleep(ticks);
  566. }
  567. }
  568. return (status);
  569. }
  570. /**
  571. * @brief The function osDelayUntil waits until an absolute time (specified
  572. * in kernel ticks) is reached.
  573. * The corner case when the kernel tick counter overflows is handled by
  574. * osDelayUntil. Thus it is absolutely legal to provide a value which
  575. * is lower than the current tick value, i.e. returned by
  576. * osKernelGetTickCount. Typically as a user you do not have to take
  577. * care about the overflow. The only limitation you have to have in
  578. * mind is that the maximum delay is limited to (231)-1 ticks.
  579. * The delayed thread is put into the BLOCKED state and a context
  580. * switch occurs immediately. The thread is automatically put back to
  581. * the READY state when the given time is reached. If the thread will
  582. * have the highest priority in READY state it will being scheduled
  583. * immediately.
  584. * @param [in] ticks absolute time in ticks
  585. * @retval status code that indicates the execution status of the function.
  586. */
  587. osStatus_t osDelayUntil(uint32_t ticks)
  588. {
  589. uint32_t tcnt, delay;
  590. /* The output status code that indicates the execution status */
  591. osStatus_t status;
  592. /* Check if this API is called from Interrupt Service Routines */
  593. if (IS_IRQ_MODE())
  594. {
  595. /* Return osErrorISR in case of error */
  596. status = osErrorISR;
  597. }
  598. else
  599. {
  600. /* Return osOK in case of success */
  601. status = osOK;
  602. /* Return osOK in case of success */
  603. tcnt = (uint32_t)tx_time_get();
  604. /* Determine remaining number of ticks to delay */
  605. delay = ticks - tcnt;
  606. /* Check if target tick has not expired */
  607. if ((delay != 0U) && (0 == (delay >> (8 * sizeof(uint32_t) - 1))))
  608. {
  609. /* Sleep the thread */
  610. tx_thread_sleep(delay);
  611. }
  612. else
  613. {
  614. /* No delay or already expired */
  615. status = osErrorParameter;
  616. }
  617. }
  618. return (status);
  619. }
  620. /*---------------------------------------------------------------------------*/
  621. /*--------------------------Thread Management APIs---------------------------*/
  622. /*---------------------------------------------------------------------------*/
  623. /**
  624. * @brief The function osThreadNew starts a thread function by adding it to
  625. * the list of active threads and sets it to state READY. Arguments for
  626. * the thread function are passed using the parameter pointer
  627. * *argument. When the priority of the created thread function is
  628. * higher than the current RUNNING thread, the created thread function
  629. * starts instantly and becomes the new RUNNING thread. Thread
  630. * attributes are defined with the parameter pointer attr. Attributes
  631. * include settings for thread priority, stack size, or memory
  632. * allocation.
  633. * The function can be safely called before the RTOS is started
  634. * (call to osKernelStart), but not before it is initialized (call to
  635. * osKernelInitialize).
  636. * The function osThreadNew returns the pointer to the thread object
  637. * identifier or NULL in case of an error.
  638. * Note : This function Cannot be called from Interrupt Service
  639. * Routines.
  640. * @param [in] func thread function.
  641. * [in] argument pointer that is passed to the thread function as
  642. * start argument.
  643. * [in] attr thread attributes; NULL: default values.
  644. * @retval thread ID for reference by other functions or NULL in case of error.
  645. */
  646. osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
  647. {
  648. /* For ThreadX the control block pointer is the thread identifier */
  649. TX_THREAD *thread_ptr = NULL;
  650. /* Pointer to the thread name */
  651. CHAR *name_ptr = NULL;
  652. /* Pointer to start address of the thread stack */
  653. VOID *stack_start;
  654. /* The thread stack size */
  655. ULONG stack_size;
  656. /* The thread control block size */
  657. ULONG cb_size;
  658. /* The thread priority */
  659. UINT priority;
  660. /* The thread entry input */
  661. ULONG entry_input = 0;
  662. /* Check if this API is called from Interrupt Service Routines
  663. or the thread_id is NULL */
  664. if (!IS_IRQ_MODE() && (func != NULL))
  665. {
  666. /* Initialize the name_ptr to NULL */
  667. name_ptr = NULL;
  668. /* Check if the attr is not NULL */
  669. if (attr != NULL)
  670. {
  671. /* Check if the name_ptr is not NULL */
  672. if (attr->name != NULL)
  673. {
  674. /* Set the thread name_ptr */
  675. name_ptr = (CHAR *)attr->name;
  676. }
  677. /* Check the input priority value and attribute bits for osThreadJoinable
  678. parameter */
  679. if ((attr->priority < osPriorityIdle) || (attr->priority > osPriorityISR))
  680. {
  681. /* Return NULL pointer in case of error */
  682. return (NULL);
  683. }
  684. else
  685. {
  686. /* Set the thread priority */
  687. priority = osPriorityISR - attr->priority;
  688. }
  689. /* Check if the argument is not NULL */
  690. if (argument != NULL)
  691. {
  692. /* Set the entry_input */
  693. entry_input = (ULONG) argument;
  694. }
  695. /* Check if the stack size is equal to 0 */
  696. if (attr->stack_size == 0U)
  697. {
  698. /* Set stack size to DEFAULT_THREAD_STACK_SIZE */
  699. stack_size = RTOS2_DEFAULT_THREAD_STACK_SIZE;
  700. }
  701. else if (attr->stack_size < TX_MINIMUM_STACK)
  702. {
  703. /* Set stack size to TX_MINIMUM_STACK */
  704. stack_size = TX_MINIMUM_STACK;
  705. }
  706. else
  707. {
  708. /* Set stack size to attr->stack_size */
  709. stack_size = (ULONG)attr->stack_size;
  710. }
  711. /* Check if the input stack pointer is NULL */
  712. if (attr->stack_mem == NULL)
  713. {
  714. /* Allocate the stack for the thread to be created */
  715. stack_start = MemAlloc(stack_size, RTOS2_BYTE_POOL_STACK_TYPE);
  716. if (stack_start == NULL)
  717. {
  718. /* Return NULL pointer in case of error */
  719. return (NULL);
  720. }
  721. }
  722. else
  723. {
  724. if (attr->stack_size == 0U)
  725. {
  726. /* Return NULL pointer in case of error */
  727. return (NULL);
  728. }
  729. else
  730. {
  731. /* Set stack size to the input attr->stack_size */
  732. stack_size = (ULONG)attr->stack_size;
  733. }
  734. /* The stack shall point to the input stack memory address */
  735. stack_start = attr->stack_mem;
  736. }
  737. /* Check if the control block size is equal to 0 */
  738. if (attr->cb_size == 0U)
  739. {
  740. /* Set control block size to sizeof(TX_THREAD) */
  741. cb_size = sizeof(TX_THREAD);
  742. }
  743. else if (attr->cb_size < sizeof(TX_THREAD))
  744. {
  745. /* Return NULL pointer in case of error */
  746. return (NULL);
  747. }
  748. else
  749. {
  750. /* Set stack size to attr->cb_size */
  751. cb_size = (ULONG)attr->cb_size;
  752. }
  753. /* Check if the input control block pointer is NULL */
  754. if (attr->cb_mem == NULL)
  755. {
  756. /* Allocate the thread_ptr structure for the thread to be created */
  757. thread_ptr = (TX_THREAD *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  758. if (thread_ptr == NULL)
  759. {
  760. /* Check if the memory for thread stack has been internally
  761. allocated */
  762. if (attr->stack_mem == NULL)
  763. {
  764. /* Free the already allocated memory for thread stack */
  765. MemFree(stack_start);
  766. }
  767. /* Return NULL pointer in case of error */
  768. return (NULL);
  769. }
  770. }
  771. else
  772. {
  773. /* The control block shall point to the input cb_mem memory address */
  774. thread_ptr = attr->cb_mem;
  775. }
  776. }
  777. else
  778. {
  779. /* Set the thread priority to default osPriorityNormal*/
  780. priority = osPriorityISR - osPriorityNormal;
  781. /* Initialize the name_ptr to NULL */
  782. name_ptr = NULL;
  783. /* Initialize the stack_size to RTOS2_DEFAULT_THREAD_STACK_SIZE */
  784. stack_size = RTOS2_DEFAULT_THREAD_STACK_SIZE;
  785. /* Check if the argument is not NULL */
  786. if (argument != NULL)
  787. {
  788. /* Set the entry_input */
  789. entry_input = (ULONG) argument;
  790. }
  791. /* Allocate the stack for the thread to be created */
  792. stack_start = MemAlloc(stack_size, RTOS2_BYTE_POOL_STACK_TYPE);
  793. if (stack_start == NULL)
  794. {
  795. /* Return NULL pointer in case of error */
  796. return (NULL);
  797. }
  798. /* Allocate the thread_ptr structure for the thread to be created */
  799. thread_ptr = (TX_THREAD *)MemAlloc(sizeof(TX_THREAD), RTOS2_BYTE_POOL_HEAP_TYPE);
  800. if (thread_ptr == NULL)
  801. {
  802. /* Free the already allocated memory for thread stack */
  803. MemFree(stack_start);
  804. /* Return NULL pointer in case of error */
  805. return (NULL);
  806. }
  807. }
  808. /* Call the tx_thread_create function to create the new thread.
  809. Note: By default the preempt_threshold shall be deactivated by setting
  810. its value to the priority or deactivated using
  811. TX_DISABLE_PREEMPTION_THRESHOLD */
  812. if (tx_thread_create(thread_ptr, name_ptr, (void(*)(ULONG))func, entry_input, stack_start, stack_size, priority,
  813. priority, RTOS2_DEFAULT_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS)
  814. {
  815. /* Check if the memory for thread control block has been internally
  816. allocated */
  817. if ((attr->cb_mem == NULL) || (attr == NULL))
  818. {
  819. /* Free the already allocated memory for thread control block */
  820. MemFree(thread_ptr);
  821. }
  822. /* Check if the memory for thread stack has been internally allocated */
  823. if ((attr->stack_mem == NULL) || (attr == NULL))
  824. {
  825. /* Free the already allocated memory for thread stack */
  826. MemFree(stack_start);
  827. }
  828. /* Return NULL pointer in case of error */
  829. thread_ptr = NULL;
  830. }
  831. else
  832. {
  833. /* Check if the thread shall be created joinable */
  834. if ((attr != NULL) && (attr->attr_bits == osThreadJoinable))
  835. {
  836. /* Set the thread to Joinable state */
  837. thread_ptr->tx_thread_detached_joinable = osThreadJoinable;
  838. }
  839. else
  840. {
  841. /* Set the thread to Detached state */
  842. thread_ptr->tx_thread_detached_joinable = osThreadDetached;
  843. }
  844. }
  845. }
  846. return ((osThreadId_t)thread_ptr);
  847. }
  848. /**
  849. * @brief The function osThreadGetName returns the pointer to the name_ptr
  850. * string of the thread identified by parameter thread_id or NULL in
  851. * case of an error.
  852. * Note : This function cannot be called from Interrupt Service
  853. * Routines.
  854. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId
  855. * @retval name_ptr as null-terminated string.
  856. */
  857. const char *osThreadGetName(osThreadId_t thread_id)
  858. {
  859. /* For ThreadX the control block pointer is the thread identifier */
  860. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  861. /* The output name_ptr as null-terminated string */
  862. CHAR *name_ptr = NULL;
  863. /* Check if this API is called from Interrupt Service Routines, the thread_id
  864. is NULL or thread_id->tx_thread_id != TX_THREAD_ID */
  865. if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  866. {
  867. /* Return NULL in case of an error */
  868. name_ptr = NULL;
  869. }
  870. else
  871. {
  872. /* Call the tx_thread_info_get to get the thread name_ptr */
  873. if (tx_thread_info_get(thread_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  874. {
  875. /* Return NULL in case of an error */
  876. name_ptr = NULL;
  877. }
  878. }
  879. return (name_ptr);
  880. }
  881. /**
  882. * @brief The function osThreadGetId returns the thread object ID of the
  883. * currently running thread or NULL in case of an error.
  884. * Note : This function may be called from Interrupt Service Routines.
  885. * @param none
  886. * @retval thread ID for reference by other functions or NULL in case of error.
  887. */
  888. osThreadId_t osThreadGetId(void)
  889. {
  890. /* For ThreadX the control block pointer is the thread identifier */
  891. osThreadId_t thread_id;
  892. /* Call the tx_thread_identify to get the control block pointer of the
  893. currently executing thread. */
  894. thread_id = (osThreadId_t)tx_thread_identify();
  895. return (thread_id);
  896. }
  897. /**
  898. * @brief The function osThreadGetState returns the state of the thread
  899. * identified by parameter thread_id. In case it fails or if it is
  900. * called from an ISR, it will return osThreadError, otherwise it
  901. * returns the thread state (refer to osThreadState_t for the list of
  902. * thread states).
  903. * Note : This function cannot be called from Interrupt Service
  904. * Routines.
  905. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId
  906. * @retval state current thread state of the specified thread.
  907. */
  908. osThreadState_t osThreadGetState(osThreadId_t thread_id)
  909. {
  910. /* For ThreadX the control block pointer is the thread identifier */
  911. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  912. /* The control block pointer of the current running thread */
  913. TX_THREAD *current_thread = NULL;
  914. /* The current thread state of the specified thread. */
  915. osThreadState_t state;
  916. /* The current thread state of the specified thread as specified by threadx */
  917. UINT threadx_state;
  918. /* Check if this API is called from Interrupt Service Routines, the thread_id
  919. is NULL or thread_id->tx_thread_id != TX_THREAD_ID */
  920. if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  921. /* Return osThreadError in case of an error */
  922. {
  923. state = osThreadError;
  924. }
  925. else
  926. {
  927. /* Get the current running thread */
  928. TX_THREAD_GET_CURRENT(current_thread);
  929. if (current_thread == thread_id)
  930. {
  931. /* The state is running */
  932. state = osThreadRunning;
  933. }
  934. else
  935. {
  936. /* Call the tx_thread_info_get to get the thread threadx_state */
  937. if (tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  938. {
  939. /* Return osThreadError in case of an error */
  940. state = osThreadError;
  941. }
  942. else
  943. {
  944. /* Link the ThreadX thread states to CMSIS RTOS2 states */
  945. switch (threadx_state)
  946. {
  947. /* The thread is in READY state */
  948. case TX_READY:
  949. {
  950. state = osThreadReady;
  951. break;
  952. }
  953. /* The thread is in COMPLETED state */
  954. case TX_COMPLETED:
  955. {
  956. state = osThreadTerminated;
  957. break;
  958. }
  959. /* The thread is in TERMINATED state */
  960. case TX_TERMINATED:
  961. {
  962. state = osThreadTerminated;
  963. break;
  964. }
  965. /* The thread is in SUSPENDED state */
  966. case TX_SUSPENDED:
  967. case TX_QUEUE_SUSP:
  968. case TX_SEMAPHORE_SUSP:
  969. case TX_EVENT_FLAG:
  970. case TX_BLOCK_MEMORY:
  971. case TX_BYTE_MEMORY:
  972. case TX_IO_DRIVER:
  973. case TX_FILE:
  974. case TX_TCP_IP:
  975. case TX_MUTEX_SUSP:
  976. case TX_PRIORITY_CHANGE:
  977. {
  978. state = osThreadBlocked;
  979. break;
  980. }
  981. /* The thread is in SLEEP state */
  982. case TX_SLEEP:
  983. {
  984. state = osThreadBlocked;
  985. break;
  986. }
  987. /* The thread is in unknown state */
  988. default:
  989. {
  990. state = osThreadError;
  991. break;
  992. }
  993. }
  994. }
  995. }
  996. }
  997. return (state);
  998. }
  999. /**
  1000. * @brief The function osThreadGetStackSize returns the stack size of the
  1001. * thread specified by parameter thread_id. In case of an error, it
  1002. * returns 0.
  1003. * Note : This function cannot be called from Interrupt Service
  1004. * Routines.
  1005. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1006. * @retval remaining_stack_space remaining stack space in bytes.
  1007. */
  1008. uint32_t osThreadGetStackSize(osThreadId_t thread_id)
  1009. {
  1010. /* For ThreadX the control block pointer is the thread identifier */
  1011. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1012. /* The specific thread stack size in bytes */
  1013. unsigned int stack_size;
  1014. /* Check if this API is called from Interrupt Service Routines, the thread_id
  1015. is NULL or thread_id->tx_thread_id != TX_THREAD_ID */
  1016. if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1017. {
  1018. /* Return 0 in case of error */
  1019. stack_size = 0U;
  1020. }
  1021. else
  1022. {
  1023. /* The stack_size get the allocated thread stack size in the thread creation step */
  1024. stack_size = thread_ptr->tx_thread_stack_size;
  1025. }
  1026. return (stack_size);
  1027. }
  1028. /**
  1029. * @brief The function osThreadGetStackSpace returns the size of unused stack
  1030. * space for the thread specified by parameter thread_id. Stack
  1031. * watermark recording during execution needs to be enabled (refer to
  1032. * Thread Configuration). In case of an error, it returns 0.
  1033. * Note : This function cannot be called from Interrupt Service
  1034. * Routines.
  1035. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1036. * @retval remaining_stack_space remaining stack space in bytes.
  1037. */
  1038. uint32_t osThreadGetStackSpace(osThreadId_t thread_id)
  1039. {
  1040. /* For ThreadX the control block pointer is the thread identifier */
  1041. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1042. /* Remaining stack space in bytes */
  1043. uint32_t remaining_stack_space;
  1044. /* Check if this API is called from Interrupt Service Routines, the thread_id
  1045. is NULL or thread_id->tx_thread_id != TX_THREAD_ID */
  1046. if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1047. {
  1048. /* Return 0 in case of error */
  1049. remaining_stack_space = 0U;
  1050. }
  1051. else
  1052. {
  1053. /* Compute the remaining free stack size for the given thread */
  1054. remaining_stack_space = (unsigned int)((CHAR *)thread_ptr->tx_thread_stack_ptr -
  1055. (CHAR *)thread_ptr->tx_thread_stack_start);
  1056. }
  1057. return (remaining_stack_space);
  1058. }
  1059. /**
  1060. * @brief The function osThreadSetPriority changes the priority of an active
  1061. * thread specified by the parameter thread_id to the priority
  1062. * specified by the parameter priority.
  1063. * Note : This function cannot be called from Interrupt Service
  1064. * Routines.
  1065. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1066. * [in] priority new priority value for the thread function.
  1067. * @retval status code that indicates the execution status of the function.
  1068. */
  1069. osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority)
  1070. {
  1071. /* For ThreadX the control block pointer is the thread identifier */
  1072. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1073. /* Old priority */
  1074. UINT old_priority;
  1075. /* The returned status or error */
  1076. osStatus_t status;
  1077. /* Check if this API is called from Interrupt Service Routines */
  1078. if (IS_IRQ_MODE())
  1079. {
  1080. /* Return osErrorISR error */
  1081. status = osErrorISR;
  1082. }
  1083. /* Check if thread_ptr is NULL or thread_id->tx_thread_id != TX_THREAD_ID or
  1084. the input priority is out of range */
  1085. else if ((thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID) || (priority < osPriorityIdle)
  1086. || (priority > osPriorityISR))
  1087. {
  1088. /* Return osErrorParameter error */
  1089. status = osErrorParameter;
  1090. }
  1091. else
  1092. {
  1093. /* Convert input CMSIS osPriority_t to threadX priority */
  1094. priority = (osPriority_t)(osPriorityISR - priority);
  1095. /* Call the tx_thread_priority_change to change the thread priority */
  1096. if (tx_thread_priority_change(thread_ptr, priority, &old_priority) == TX_SUCCESS)
  1097. {
  1098. /* Return osOK in case of success */
  1099. status = osOK;
  1100. }
  1101. else
  1102. {
  1103. /* Return osErrorResource in case of error */
  1104. status = osErrorResource;
  1105. }
  1106. }
  1107. return (status);
  1108. }
  1109. /**
  1110. * @brief The function osThreadGetPriority returns the priority of an active
  1111. * thread specified by the parameter thread_id.
  1112. * Note : This function cannot be called from Interrupt Service
  1113. * Routines.
  1114. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1115. * @retval priority current priority value of the specified thread.
  1116. */
  1117. osPriority_t osThreadGetPriority(osThreadId_t thread_id)
  1118. {
  1119. /* For ThreadX the control block pointer is the thread identifier */
  1120. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1121. /* The returned thread priority or error */
  1122. osPriority_t priority;
  1123. /* Check if this API is called from Interrupt Service Routines
  1124. or the thread_id is NULL */
  1125. if (IS_IRQ_MODE() || (thread_ptr == NULL))
  1126. {
  1127. /* Return osPriorityError in case of an error */
  1128. priority = osPriorityError;
  1129. }
  1130. else
  1131. {
  1132. /* Call the tx_thread_info_get to get the thread priority */
  1133. if (tx_thread_info_get(thread_ptr, NULL, NULL, NULL, (UINT *)&priority, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  1134. {
  1135. /* Return osPriorityError in case of an error */
  1136. priority = osPriorityError;
  1137. }
  1138. else
  1139. {
  1140. /* Convert the threadX priority to CMSIS osPriority_t */
  1141. priority = (osPriority_t)(osPriorityISR - priority);
  1142. }
  1143. }
  1144. return (priority);
  1145. }
  1146. /**
  1147. * @brief The function osThreadYield passes control to the next thread with
  1148. * the same priority that is in the READY state. If there is no other
  1149. * thread with the same priority in state READY, then the current
  1150. * thread continues execution and no thread switch occurs.
  1151. * osThreadYield does not set the thread to state BLOCKED. Thus no
  1152. * thread with a lower priority will be scheduled even if threads in
  1153. * state READY are available.
  1154. * Note : This function cannot be called from Interrupt Service
  1155. * Routines.
  1156. * @param none.
  1157. * @retval status code that indicates the execution status of the function.
  1158. */
  1159. osStatus_t osThreadYield(void)
  1160. {
  1161. /* The returned status or error */
  1162. osStatus_t status;
  1163. /* Check if this API is called from Interrupt Service Routines */
  1164. if (IS_IRQ_MODE())
  1165. {
  1166. /* Return osErrorISR error */
  1167. status = osErrorISR;
  1168. }
  1169. else
  1170. {
  1171. /* Call the tx_thread_relinquish to relinquishes processor control to
  1172. other ready-to-run threads at the same or higher priority. */
  1173. tx_thread_relinquish();
  1174. /* Return osOK for success */
  1175. status = osOK;
  1176. }
  1177. return (status);
  1178. }
  1179. /**
  1180. * @brief The function osThreadSuspend suspends the execution of the thread
  1181. * identified by parameter thread_id. The thread is put into the
  1182. * BLOCKED state (osThreadBlocked). Suspending the running thread will
  1183. * cause a context switch to another thread in READY state immediately.
  1184. * The suspended thread is not executed until explicitly resumed with
  1185. * the function osThreadResume.
  1186. * Threads that are already BLOCKED are removed from any wait list and
  1187. * become ready when they are resumed. Thus it is not recommended to
  1188. * suspend an already blocked thread.
  1189. * Note : This function cannot be called from Interrupt Service
  1190. * Routines.
  1191. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1192. * @retval status code that indicates the execution status of the function.
  1193. */
  1194. osStatus_t osThreadSuspend(osThreadId_t thread_id)
  1195. {
  1196. /* For ThreadX the control block pointer is the thread identifier */
  1197. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1198. /* The returned status or error */
  1199. osStatus_t status;
  1200. /* Check if this API is called from Interrupt Service Routines */
  1201. if (IS_IRQ_MODE())
  1202. {
  1203. /* Return osErrorISR error */
  1204. status = osErrorISR;
  1205. }
  1206. /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */
  1207. else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1208. {
  1209. /* Return osErrorParameter error */
  1210. status = osErrorParameter;
  1211. }
  1212. else
  1213. {
  1214. /* Call the tx_thread_suspend to suspends the specified application
  1215. thread. A thread may call this service to suspend itself. */
  1216. if (tx_thread_suspend(thread_ptr) == TX_SUCCESS)
  1217. {
  1218. /* Return osOK for success */
  1219. status = osOK;
  1220. }
  1221. else
  1222. {
  1223. /* Return osErrorResource in case of error */
  1224. status = osErrorResource;
  1225. }
  1226. }
  1227. return (status);
  1228. }
  1229. /**
  1230. * @brief The function osThreadResume puts the thread identified by parameter
  1231. * thread_id (which has to be in BLOCKED state) back to the READY
  1232. * state. If the resumed thread has a higher priority than the running
  1233. * thread a context switch occurs immediately.
  1234. * The thread becomes ready regardless of the reason why the thread was
  1235. * blocked. Thus it is not recommended to resume a thread not suspended
  1236. * by osThreadSuspend.
  1237. * Functions that will put a thread into BLOCKED state are:
  1238. * osEventFlagsWait and osThreadFlagsWait, osDelay and osDelayUntil,
  1239. * osMutexAcquire and osSemaphoreAcquire, osMessageQueueGet,
  1240. * osMemoryPoolAlloc, osThreadJoin, osThreadSuspend..
  1241. * Note : This function cannot be called from Interrupt Service
  1242. * Routines.
  1243. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1244. * @retval status code that indicates the execution status of the function.
  1245. */
  1246. osStatus_t osThreadResume(osThreadId_t thread_id)
  1247. {
  1248. /* For ThreadX the control block pointer is the thread identifier */
  1249. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1250. /* The returned status or error */
  1251. osStatus_t status;
  1252. /* Check if this API is called from Interrupt Service Routines */
  1253. if (IS_IRQ_MODE())
  1254. {
  1255. /* Return osErrorISR error */
  1256. status = osErrorISR;
  1257. }
  1258. /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */
  1259. else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1260. {
  1261. /* Return osErrorParameter error */
  1262. status = osErrorParameter;
  1263. }
  1264. else
  1265. {
  1266. /* Call the tx_thread_resume to resumes or prepares for execution a thread
  1267. that was previously suspended by a tx_thread_suspend call. In addition,
  1268. this service resumes threads that were created without an automatic
  1269. start. */
  1270. if (tx_thread_resume(thread_ptr) == TX_SUCCESS)
  1271. {
  1272. /* Return osOK for success */
  1273. status = osOK;
  1274. }
  1275. else
  1276. {
  1277. /* Return osErrorResource in case of error */
  1278. status = osErrorResource;
  1279. }
  1280. }
  1281. return (status);
  1282. }
  1283. /**
  1284. * @brief The function osThreadExit terminates the calling thread. This allows
  1285. * the thread to be synchronized with osThreadJoin.
  1286. * Note : This function cannot be called from Interrupt Service
  1287. * Routines.
  1288. * @param none.
  1289. * @retval none.
  1290. */
  1291. __NO_RETURN void osThreadExit(void)
  1292. {
  1293. /* For ThreadX the control block pointer is the thread identifier */
  1294. TX_THREAD *thread_ptr = NULL;
  1295. /* Check if this API is called from Interrupt Service Routines */
  1296. if (!IS_IRQ_MODE())
  1297. {
  1298. /* Call the tx_thread_identify to get the control block pointer of the
  1299. currently executing thread. */
  1300. thread_ptr = tx_thread_identify();
  1301. /* Check if the current running thread pointer is not NULL */
  1302. if (thread_ptr != NULL)
  1303. {
  1304. /* Call the tx_thread_terminate to terminates the specified application
  1305. thread regardless of whether the thread is suspended or not. A thread
  1306. may call this service to terminate itself. */
  1307. tx_thread_terminate(thread_ptr);
  1308. }
  1309. }
  1310. /* Infinite loop */
  1311. for (;;);
  1312. }
  1313. /**
  1314. * @brief The function osThreadTerminate removes the thread specified by
  1315. * parameter thread_id from the list of active threads. If the
  1316. * thread is currently RUNNING, the thread terminates and the
  1317. * execution continues with the next READY thread. If no such thread
  1318. * exists, the function will not terminate the running thread, but
  1319. * return osErrorResource.
  1320. * Note : This function cannot be called from Interrupt Service
  1321. * Routines.
  1322. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1323. * @retval status code that indicates the execution status of the function.
  1324. */
  1325. osStatus_t osThreadTerminate(osThreadId_t thread_id)
  1326. {
  1327. /* For ThreadX the control block pointer is the thread identifier */
  1328. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1329. /* The returned status or error */
  1330. osStatus_t status;
  1331. /* Check if this API is called from Interrupt Service Routines */
  1332. if (IS_IRQ_MODE())
  1333. {
  1334. /* Return osErrorISR error */
  1335. status = osErrorISR;
  1336. }
  1337. /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */
  1338. else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1339. {
  1340. /* Return osErrorParameter error */
  1341. status = osErrorParameter;
  1342. }
  1343. else
  1344. {
  1345. /* Call the tx_thread_terminate to terminates the specified application
  1346. thread regardless of whether the thread is suspended or not. A thread
  1347. may call this service to terminate itself. */
  1348. if (tx_thread_terminate(thread_ptr) == TX_SUCCESS)
  1349. {
  1350. /* Free the thread resources if it is Detached */
  1351. if (thread_ptr->tx_thread_detached_joinable == osThreadDetached)
  1352. {
  1353. /* Free the already allocated memory for thread stack */
  1354. MemFree(thread_ptr->tx_thread_stack_start);
  1355. /* Free the already allocated memory for thread control block */
  1356. MemFree(thread_ptr);
  1357. }
  1358. /* Return osOK for success */
  1359. status = osOK;
  1360. }
  1361. else
  1362. {
  1363. /* Return osErrorResource in case of error */
  1364. status = osErrorResource;
  1365. }
  1366. }
  1367. return (status);
  1368. }
  1369. /**
  1370. * @brief The function osThreadDetach changes the attribute of a thread
  1371. * (specified by thread_id) to osThreadDetached. Detached threads are
  1372. * not joinable with osThreadJoin. When a detached thread is
  1373. * terminated, all resources are returned to the system. The behavior
  1374. * of osThreadDetach on an already detached thread is undefined.
  1375. * Note : This function cannot be called from Interrupt Service
  1376. * Routines.
  1377. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1378. * @retval status code that indicates the execution status of the function.
  1379. */
  1380. osStatus_t osThreadDetach(osThreadId_t thread_id)
  1381. {
  1382. /* For ThreadX the control block pointer is the thread identifier */
  1383. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1384. /* The returned status or error */
  1385. osStatus_t status;
  1386. /* Check if this API is called from Interrupt Service Routines */
  1387. if (IS_IRQ_MODE())
  1388. {
  1389. /* Return osErrorISR error */
  1390. status = osErrorISR;
  1391. }
  1392. /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */
  1393. else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1394. {
  1395. /* Return osErrorParameter error */
  1396. status = osErrorParameter;
  1397. }
  1398. else
  1399. {
  1400. /* Change the status of the specific thread to Detached */
  1401. thread_ptr->tx_thread_detached_joinable = osThreadDetached;
  1402. /* Return osOK for success */
  1403. status = osOK;
  1404. }
  1405. return (status);
  1406. }
  1407. /**
  1408. * @brief The function osThreadJoin waits for the thread specified by
  1409. * thread_id to terminate. If that thread has already terminated, then
  1410. * osThreadJoin returns immediately. The thread must be joinable.
  1411. * By default threads are created with the attribute osThreadDetached.
  1412. * Note : This function cannot be called from Interrupt Service
  1413. * Routines.
  1414. * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId.
  1415. * @retval status code that indicates the execution status of the function.
  1416. */
  1417. osStatus_t osThreadJoin(osThreadId_t thread_id)
  1418. {
  1419. /* For ThreadX the control block pointer is the thread identifier */
  1420. TX_THREAD *thread_ptr = (TX_THREAD *)thread_id;
  1421. /* The control block pointer of the current running thread */
  1422. TX_THREAD *current_thread = NULL;
  1423. /* The current thread state of the specified thread as specified by threadx */
  1424. UINT threadx_state;
  1425. /* The returned status or error */
  1426. osStatus_t status;
  1427. /* Check if this API is called from Interrupt Service Routines */
  1428. if (IS_IRQ_MODE())
  1429. {
  1430. /* Return osErrorISR error */
  1431. status = osErrorISR;
  1432. }
  1433. /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */
  1434. else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID))
  1435. {
  1436. /* Return osErrorParameter error */
  1437. status = osErrorParameter;
  1438. }
  1439. else
  1440. {
  1441. /* Get the current running thread */
  1442. TX_THREAD_GET_CURRENT(current_thread);
  1443. if (current_thread == thread_id)
  1444. {
  1445. /* Return osErrorParameter error */
  1446. status = osErrorParameter;
  1447. }
  1448. else
  1449. {
  1450. /* Call the tx_thread_info_get to get the thread threadx_state */
  1451. if (tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL) == TX_SUCCESS)
  1452. {
  1453. /* Check if the thread is joinable */
  1454. if (thread_ptr->tx_thread_detached_joinable == osThreadJoinable)
  1455. {
  1456. /* Only one thread can Join a thread in the same time so we will
  1457. detach it momentally until it will be terminated */
  1458. thread_ptr->tx_thread_detached_joinable = osThreadDetached;
  1459. /* Wait until the state of the specific thread turn to terminated */
  1460. while ((threadx_state != TX_TERMINATED) && (threadx_state != TX_COMPLETED))
  1461. {
  1462. /* Call the tx_thread_info_get to get the thread threadx_state */
  1463. tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL);
  1464. }
  1465. /* Once the thread is terminated it can be again Joinable */
  1466. thread_ptr->tx_thread_detached_joinable = osThreadJoinable;
  1467. /* Return osOK for success */
  1468. status = osOK;
  1469. }
  1470. else
  1471. {
  1472. /* Return osErrorResource error */
  1473. status = osErrorResource;
  1474. }
  1475. }
  1476. else
  1477. {
  1478. /* Return osErrorResource error */
  1479. status = osErrorResource;
  1480. }
  1481. }
  1482. }
  1483. return (status);
  1484. }
  1485. /**
  1486. * @brief The function osThreadGetCount returns the number of active threads
  1487. * or 0 in case of an error.
  1488. * Note : This function cannot be called from Interrupt Service
  1489. * Routines.
  1490. * @param none.
  1491. * @retval count number of active threads.
  1492. */
  1493. uint32_t osThreadGetCount(void)
  1494. {
  1495. /* For ThreadX the control block pointer is the thread identifier */
  1496. TX_THREAD *thread_ptr = NULL;
  1497. /* Returned number of active threads */
  1498. unsigned int count = 0U;
  1499. /* Check if this API is called from Interrupt Service Routines */
  1500. if (IS_IRQ_MODE())
  1501. {
  1502. /* Return 0 in case of error */
  1503. count = 0;
  1504. }
  1505. else
  1506. {
  1507. /* thread_ptr = the head pointer of the created thread list */
  1508. thread_ptr = _tx_thread_created_ptr;
  1509. /* Compute the number of active threads */
  1510. while (thread_ptr != NULL)
  1511. {
  1512. /* Check the next thread validity */
  1513. if (thread_ptr->tx_thread_id == TX_THREAD_ID)
  1514. {
  1515. /* Increment the number of active threads */
  1516. count++;
  1517. /* Check the state of next created thread */
  1518. if ((thread_ptr->tx_thread_created_next != thread_ptr)
  1519. && (thread_ptr->tx_thread_created_next != _tx_thread_created_ptr))
  1520. {
  1521. thread_ptr = thread_ptr->tx_thread_created_next;
  1522. }
  1523. else
  1524. {
  1525. break;
  1526. }
  1527. }
  1528. else
  1529. {
  1530. /* Return 0 in case of error */
  1531. count = 0;
  1532. break;
  1533. }
  1534. }
  1535. }
  1536. return (count);
  1537. }
  1538. /**
  1539. * @brief The function osThreadEnumerate returns the number of enumerated
  1540. * threads or 0 in case of an error.
  1541. * Note : This function cannot be called from Interrupt Service
  1542. * Routines.
  1543. * @param [out] thread_array pointer to array for retrieving thread IDs.
  1544. * [in] array_items maximum number of items in array for retrieving
  1545. * thread IDs.
  1546. * @retval count number of enumerated threads.
  1547. */
  1548. uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items)
  1549. {
  1550. /* For ThreadX the control block pointer is the thread identifier */
  1551. TX_THREAD *thread_ptr = NULL;
  1552. /* The number of enumerated threads */
  1553. uint32_t count = 0U;
  1554. /* Check if this API is called from Interrupt Service Routines or
  1555. if the thread_array is NULL or the array_items is equal to 0 */
  1556. if (IS_IRQ_MODE() || (thread_array == NULL) || (array_items == 0U))
  1557. {
  1558. /* Return 0 in case of error */
  1559. count = 0U;
  1560. }
  1561. else
  1562. {
  1563. /* thread_ptr point to the head pointer of the created thread list */
  1564. thread_ptr = _tx_thread_created_ptr;
  1565. /* Compute the number of active threads */
  1566. while ((thread_ptr != NULL) && (count < array_items))
  1567. {
  1568. /* Check the next thread validity */
  1569. if (thread_ptr->tx_thread_id == TX_THREAD_ID)
  1570. {
  1571. /* Retrieve the thread IDs and increment the number of active
  1572. threads */
  1573. thread_array[count++] = thread_ptr;
  1574. /* Check the state of next created thread */
  1575. if ((thread_ptr->tx_thread_created_next != thread_ptr)
  1576. && (thread_ptr->tx_thread_created_next != _tx_thread_created_ptr))
  1577. {
  1578. thread_ptr = thread_ptr->tx_thread_created_next;
  1579. }
  1580. else
  1581. {
  1582. break;
  1583. }
  1584. }
  1585. else
  1586. {
  1587. /* Return 0 in case of error */
  1588. count = 0;
  1589. break;
  1590. }
  1591. }
  1592. }
  1593. return (count);
  1594. }
  1595. /*---------------------------------------------------------------------------*/
  1596. /*---------------------------Timer Management APIs---------------------------*/
  1597. /*---------------------------------------------------------------------------*/
  1598. /**
  1599. * @brief The function osTimerNew creates an one-shot or periodic timer and
  1600. * associates it with a callback function with argument. The timer is
  1601. * in stopped state until it is started with osTimerStart.
  1602. * The function can be safely called before the RTOS is started (call
  1603. * to osKernelStart), but not before it is initialized (call to
  1604. * osKernelInitialize).
  1605. * The function osTimerNew returns the pointer to the timer object
  1606. * identifier or NULL in case of an error.
  1607. * Note : This function cannot be called from Interrupt Service
  1608. * Routines.
  1609. * @param [in] func function pointer to callback function.
  1610. * [in] type osTimerOnce for one-shot or osTimerPeriodic for periodic
  1611. * behavior.
  1612. * [in] argument argument to the timer callback function.
  1613. * [in] attr timer attributes; NULL: default values.
  1614. * @retval timer ID for reference by other functions or NULL in case of error.
  1615. */
  1616. osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)
  1617. {
  1618. /* For TX_TIMER the control block pointer is the timer identifier */
  1619. TX_TIMER *timer_ptr = NULL;
  1620. /* The name_ptr as null-terminated string */
  1621. CHAR *name_ptr = NULL;
  1622. /* The timer expiration input */
  1623. ULONG expiration_input = 0U;
  1624. /* The timer reschedule ticks */
  1625. ULONG reschedule_ticks = 0U;
  1626. /* The size of control block */
  1627. ULONG cb_size = sizeof(TX_TIMER);
  1628. /* Check if this API is called from Interrupt Service Routines,
  1629. the timer callback function handler is NULL or the type is not valid */
  1630. if (!IS_IRQ_MODE() && (func != NULL) && (type <= osTimerPeriodic))
  1631. {
  1632. /* Initialize the name_ptr to NULL */
  1633. name_ptr = NULL;
  1634. /* Check if the attr is not NULL */
  1635. if (attr != NULL)
  1636. {
  1637. /* Check if the name_ptr is not NULL */
  1638. if (attr->name != NULL)
  1639. {
  1640. /* Set the timer name_ptr */
  1641. name_ptr = (CHAR *)attr->name;
  1642. }
  1643. /* Check if the control block size is equal to 0 */
  1644. if (attr->cb_size == 0U)
  1645. {
  1646. /* Set control block size to sizeof(TX_TIMER) */
  1647. cb_size = sizeof(TX_TIMER);
  1648. }
  1649. else if (attr->cb_size < sizeof(TX_TIMER))
  1650. {
  1651. /* Return NULL pointer in case of error */
  1652. return (NULL);
  1653. }
  1654. else
  1655. {
  1656. /* Set control block size to attr->cb_size */
  1657. cb_size = (ULONG) attr->cb_size;
  1658. }
  1659. /* Check if the input control block pointer is NULL */
  1660. if (attr->cb_mem == NULL)
  1661. {
  1662. /* Allocate the timer_ptr structure for the timer to be created */
  1663. timer_ptr = (TX_TIMER *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  1664. if (timer_ptr == NULL)
  1665. {
  1666. /* Return NULL pointer in case of error */
  1667. return (NULL);
  1668. }
  1669. }
  1670. else
  1671. {
  1672. /* The control block shall point to the input cb_mem memory address */
  1673. timer_ptr = attr->cb_mem;
  1674. }
  1675. }
  1676. else
  1677. {
  1678. /* Allocate the timer_ptr structure for the timer to be created */
  1679. timer_ptr = (TX_TIMER *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  1680. }
  1681. /* Check the timer type to set timer periodicity */
  1682. if (type == osTimerPeriodic)
  1683. {
  1684. /* Specifies the number of ticks for all timer expirations after the
  1685. first. A zero for this parameter makes the timer a one-shot timer.
  1686. Otherwise, for periodic timers, legal values range from 1 through
  1687. 0xFFFFFFFF.
  1688. For periodic timer the reschedule_ticks is initiated to 1 then set to ticks
  1689. given as input in osTimerStart APIs */
  1690. reschedule_ticks = 1;
  1691. }
  1692. /* Check if the argument is not NULL */
  1693. if (argument != NULL)
  1694. {
  1695. /* Set the expiration_input */
  1696. expiration_input = (ULONG)argument;
  1697. }
  1698. /* Call the tx_timer_create function to create the new timer */
  1699. if (tx_timer_create(timer_ptr, name_ptr, (void(*)(ULONG))func, expiration_input, 1, reschedule_ticks,
  1700. TX_NO_ACTIVATE) != TX_SUCCESS)
  1701. {
  1702. /* Check if the memory for timer control block has been internally
  1703. allocated */
  1704. if ((attr->cb_mem == NULL) || (attr == NULL))
  1705. {
  1706. /* Free the already allocated memory for timer control block */
  1707. MemFree(timer_ptr);
  1708. }
  1709. /* Return NULL pointer in case of error */
  1710. timer_ptr = NULL;
  1711. }
  1712. }
  1713. return ((osThreadId_t)timer_ptr);
  1714. }
  1715. /**
  1716. * @brief The function osTimerGetName returns the pointer to the name string
  1717. * of the timer identified by parameter timer_id or NULL in case of an
  1718. * error.
  1719. * Note : This function cannot be called from Interrupt Service
  1720. * Routines.
  1721. * @param [in] timer_id timer ID obtained by osTimerNew.
  1722. * @retval name as null-terminated string.
  1723. */
  1724. const char *osTimerGetName(osTimerId_t timer_id)
  1725. {
  1726. /* For TX_TIMER the control block pointer is the timer identifier */
  1727. TX_TIMER *timer_ptr = (TX_TIMER *)timer_id;
  1728. /* The output name_ptr as null-terminated string */
  1729. CHAR *name_ptr;
  1730. /* Check if this API is called from Interrupt Service Routines
  1731. or the timer_id is NULL */
  1732. if (IS_IRQ_MODE() || (timer_ptr == NULL))
  1733. {
  1734. /* Return NULL in case of an error */
  1735. name_ptr = NULL;
  1736. }
  1737. else
  1738. {
  1739. /* Call the tx_timer_info_get to get the timer name_ptr */
  1740. if (tx_timer_info_get(timer_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  1741. {
  1742. /* Return NULL in case of an error */
  1743. name_ptr = NULL;
  1744. }
  1745. }
  1746. return ((const char *)name_ptr);
  1747. }
  1748. /**
  1749. * @brief The function osTimerIsRunning checks whether a timer specified by
  1750. * parameter timer_id is running. It returns 1 if the timer is running
  1751. * and 0 if the timer is stopped or an error occurred.
  1752. * Note : This function cannot be called from Interrupt Service
  1753. * Routines.
  1754. * @param [in] timer_id timer ID obtained by osTimerNew.
  1755. * @retval 0 not running, 1 running.
  1756. */
  1757. uint32_t osTimerIsRunning(osTimerId_t timer_id)
  1758. {
  1759. /* For TX_TIMER the control block pointer is the timer identifier */
  1760. TX_TIMER *timer_ptr = (TX_TIMER *)timer_id;
  1761. /* The active state of the timer */
  1762. UINT active;
  1763. /* Check if this API is called from Interrupt Service Routines or the input
  1764. timer_id in NULL */
  1765. if (IS_IRQ_MODE() || (timer_id == NULL))
  1766. {
  1767. /* Return 0 in case of error */
  1768. active = 0U;
  1769. }
  1770. else
  1771. {
  1772. /* Check if the timer is valid by calling the tx_timer_info_get to get
  1773. the timer active state */
  1774. if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, NULL, NULL) != TX_SUCCESS)
  1775. {
  1776. /* Return 0 in case of error */
  1777. active = 0U;
  1778. }
  1779. }
  1780. return ((uint32_t)active);
  1781. }
  1782. /**
  1783. * @brief The function osTimerStop stops a timer specified by the parameter
  1784. * timer_id.
  1785. * Note : This function cannot be called from Interrupt Service
  1786. * Routines.
  1787. * @param [in] timer_id timer ID obtained by osTimerNew.
  1788. * @retval status code that indicates the execution status of the function.
  1789. */
  1790. osStatus_t osTimerStop(osTimerId_t timer_id)
  1791. {
  1792. /* For TX_TIMER the control block pointer is the timer identifier */
  1793. TX_TIMER *timer_ptr = (TX_TIMER *)timer_id;
  1794. /* The returned status or error */
  1795. osStatus_t status;
  1796. /* The active state of the timer */
  1797. UINT active;
  1798. /* Check if this API is called from Interrupt Service Routines */
  1799. if (IS_IRQ_MODE())
  1800. {
  1801. /* Return osErrorISR error */
  1802. status = osErrorISR;
  1803. }
  1804. /* Check if the timer control block is valid */
  1805. else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID))
  1806. {
  1807. /* Return osErrorParameter error */
  1808. status = osErrorParameter;
  1809. }
  1810. else
  1811. {
  1812. /* Get the timer running state */
  1813. if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, NULL, NULL) == TX_SUCCESS)
  1814. {
  1815. /* Check if the timer is running (active) */
  1816. if (active == TX_TRUE)
  1817. {
  1818. /* Call the tx_timer_deactivate to deactivates the specified application
  1819. timer. If the timer is already deactivated, this service has no
  1820. effect. */
  1821. if (tx_timer_deactivate(timer_ptr) == TX_SUCCESS)
  1822. {
  1823. /* Return osOK for success */
  1824. status = osOK;
  1825. }
  1826. else
  1827. {
  1828. /* Return osErrorResource in case of error */
  1829. status = osErrorResource;
  1830. }
  1831. }
  1832. else
  1833. {
  1834. /* Return osErrorResource in case of error */
  1835. status = osErrorResource;
  1836. }
  1837. }
  1838. else
  1839. {
  1840. /* Return osErrorResource error */
  1841. status = osErrorResource;
  1842. }
  1843. }
  1844. return (status);
  1845. }
  1846. /**
  1847. * @brief The function osTimerStart starts or restarts a timer specified by
  1848. * the parameter timer_id. The parameter ticks specifies the value of
  1849. * the timer in time ticks.
  1850. * Note : This function cannot be called from Interrupt Service
  1851. * Routines.
  1852. * @param [in] timer_id timer ID obtained by osTimerNew.
  1853. * [in] ticks time ticks value of the timer.
  1854. * @retval status code that indicates the execution status of the function.
  1855. */
  1856. osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)
  1857. {
  1858. /* For TX_TIMER the control block pointer is the timer identifier */
  1859. TX_TIMER *timer_ptr = (TX_TIMER *)timer_id;
  1860. /* The returned status or error */
  1861. osStatus_t status = osOK;
  1862. /* The active state of the timer */
  1863. UINT active;
  1864. /* The reschedule ticks of the timer */
  1865. ULONG reschedule_ticks;
  1866. /* Check if this API is called from Interrupt Service Routines */
  1867. if (IS_IRQ_MODE())
  1868. {
  1869. /* Return osErrorISR error */
  1870. status = osErrorISR;
  1871. }
  1872. /* Check if the timer control block is valid */
  1873. else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID))
  1874. {
  1875. /* Return osErrorParameter error */
  1876. status = osErrorParameter;
  1877. }
  1878. else
  1879. {
  1880. /* Get the timer running state and reschedule ticks parameters */
  1881. if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, &reschedule_ticks, NULL) == TX_SUCCESS)
  1882. {
  1883. /* Check if the timer is active. If so, it shall be stopped before being
  1884. activated again */
  1885. if (active == TX_TRUE)
  1886. {
  1887. /* Call the tx_timer_deactivate to deactivates the specified application
  1888. timer. If the timer is already deactivated, this service has no
  1889. effect. */
  1890. if (tx_timer_deactivate(timer_ptr) == TX_SUCCESS)
  1891. {
  1892. /* Set status osOK for success */
  1893. status = osOK;
  1894. }
  1895. else
  1896. {
  1897. /* Return osErrorResource in case of error */
  1898. status = osErrorResource;
  1899. }
  1900. }
  1901. if (status == osOK)
  1902. {
  1903. /* Check the timer reschedule_ticks parameter for periodicity */
  1904. if (reschedule_ticks > 0)
  1905. {
  1906. /* Set the reschedule_ticks to the input ticks */
  1907. reschedule_ticks = ticks;
  1908. }
  1909. /* An expired one-shot timer must be reset via tx_timer_change before
  1910. it can be activated again. */
  1911. if (tx_timer_change(timer_ptr, ticks, reschedule_ticks) == TX_SUCCESS)
  1912. {
  1913. /* Call the tx_timer_activate to activates the specified application
  1914. timer. The expiration routines of timers that expire at the same
  1915. time are executed in the order they were activated. */
  1916. if (tx_timer_activate(timer_ptr) == TX_SUCCESS)
  1917. {
  1918. /* Return osOK for success */
  1919. status = osOK;
  1920. }
  1921. else
  1922. {
  1923. /* Return osErrorResource in case of error */
  1924. status = osErrorResource;
  1925. }
  1926. }
  1927. else
  1928. {
  1929. /* Return osErrorResource in case of error */
  1930. status = osErrorResource;
  1931. }
  1932. }
  1933. }
  1934. else
  1935. {
  1936. /* Return osErrorResource error */
  1937. status = osErrorResource;
  1938. }
  1939. }
  1940. return (status);
  1941. }
  1942. /**
  1943. * @brief The function osTimerDelete deletes the timer specified by parameter
  1944. * timer_id.
  1945. * Note : This function cannot be called from Interrupt Service
  1946. * Routines.
  1947. * @param [in] timer_id timer ID obtained by osTimerNew.
  1948. * @retval status code that indicates the execution status of the function.
  1949. */
  1950. osStatus_t osTimerDelete(osTimerId_t timer_id)
  1951. {
  1952. /* For TX_TIMER the control block pointer is the timer identifier */
  1953. TX_TIMER *timer_ptr = (TX_TIMER *)timer_id;
  1954. /* The returned status or error */
  1955. osStatus_t status;
  1956. /* Check if this API is called from Interrupt Service Routines */
  1957. if (IS_IRQ_MODE())
  1958. {
  1959. /* Return osErrorISR error */
  1960. status = osErrorISR;
  1961. }
  1962. /* Check if the timer control block is valid */
  1963. else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID))
  1964. {
  1965. /* Return osErrorParameter error */
  1966. status = osErrorParameter;
  1967. }
  1968. else
  1969. {
  1970. /* Call the tx_timer_delete to delete the specified application timer. */
  1971. if (tx_timer_delete(timer_ptr) == TX_SUCCESS)
  1972. {
  1973. /* Free the already allocated memory for timer control block */
  1974. MemFree(timer_ptr);
  1975. /* Return osOK for success */
  1976. status = osOK;
  1977. }
  1978. else
  1979. {
  1980. /* Return osErrorResource in case of error */
  1981. status = osErrorResource;
  1982. }
  1983. }
  1984. return (status);
  1985. }
  1986. /*---------------------------------------------------------------------------*/
  1987. /*-----------------------------Event flags APIs------------------------------*/
  1988. /*---------------------------------------------------------------------------*/
  1989. /**
  1990. * @brief The function osEventFlagsNew creates a new event flags object that
  1991. * is used to send events across threads and returns the pointer to the
  1992. * event flags object identifier or NULL in case of an error. It can be
  1993. * safely called before the RTOS is started (call to osKernelStart), but
  1994. * not before it is initialized (call to osKernelInitialize).
  1995. * Note : This function cannot be called from Interrupt Service
  1996. * Routines.
  1997. * @param [in] attr event flags attributes; NULL: default values.
  1998. * @retval event flags ID for reference by other functions or NULL in
  1999. * case of error.
  2000. */
  2001. osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
  2002. {
  2003. /* For ThreadX the control block pointer is the event flags identifier */
  2004. TX_EVENT_FLAGS_GROUP *eventflags_ptr = NULL;
  2005. /* Pointer to the event flags name */
  2006. CHAR *name_ptr = NULL;
  2007. /* The size of control block */
  2008. ULONG cb_size = sizeof(TX_EVENT_FLAGS_GROUP);
  2009. /* Check if this API is called from Interrupt Service Routines */
  2010. if (!IS_IRQ_MODE())
  2011. {
  2012. /* Check if the attr is not NULL */
  2013. if (attr != NULL)
  2014. {
  2015. /* Check if the name_ptr is not NULL */
  2016. if (attr->name != NULL)
  2017. {
  2018. /* Set the event flags name_ptr */
  2019. name_ptr = (CHAR *)attr->name;
  2020. }
  2021. /* Check if the control block size is equal to 0 */
  2022. if (attr->cb_size == 0U)
  2023. {
  2024. /* Set control block size to sizeof(TX_EVENT_FLAGS_GROUP) */
  2025. cb_size = sizeof(TX_EVENT_FLAGS_GROUP);
  2026. }
  2027. else if (attr->cb_size < sizeof(TX_EVENT_FLAGS_GROUP))
  2028. {
  2029. /* Return NULL pointer in case of error */
  2030. return (NULL);
  2031. }
  2032. else
  2033. {
  2034. /* Set control block size to attr->cb_size */
  2035. cb_size = (ULONG) attr->cb_size;
  2036. }
  2037. /* Check if the input control block pointer is NULL */
  2038. if (attr->cb_mem == NULL)
  2039. {
  2040. /* Allocate the eventflags_ptr structure for the event flags to be created */
  2041. eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2042. if (eventflags_ptr == NULL)
  2043. {
  2044. /* Return NULL pointer in case of error */
  2045. return (NULL);
  2046. }
  2047. }
  2048. else
  2049. {
  2050. /* The control block shall point to the input cb_mem memory address */
  2051. eventflags_ptr = attr->cb_mem;
  2052. }
  2053. }
  2054. else
  2055. {
  2056. /* Allocate the eventflags_ptr structure for the event flags to be created */
  2057. eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2058. }
  2059. /* Call the tx_event_flags_create function to create the new event flags */
  2060. if (tx_event_flags_create(eventflags_ptr, name_ptr) != TX_SUCCESS)
  2061. {
  2062. if ((attr->cb_mem == NULL) || (attr == NULL))
  2063. {
  2064. /* Free the already allocated memory for event flags control block */
  2065. MemFree(eventflags_ptr);
  2066. }
  2067. }
  2068. }
  2069. return ((osEventFlagsId_t)eventflags_ptr);
  2070. }
  2071. /**
  2072. * @brief The function osEventFlagsGetName returns the pointer to the name
  2073. * string of the event flags object identified by parameter ef_id or NULL
  2074. * in case of an error.
  2075. * Note : This function cannot be called from Interrupt Service
  2076. * Routines.
  2077. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2078. * @retval name as null-terminated string.
  2079. */
  2080. const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
  2081. {
  2082. /* For ThreadX the control block pointer is the event flags identifier */
  2083. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2084. /* The output name_ptr as null-terminated string */
  2085. CHAR *name_ptr;
  2086. /* Check if this API is called from Interrupt Service Routines
  2087. or the ef_id is NULL */
  2088. if (IS_IRQ_MODE() || (eventflags_ptr == NULL))
  2089. {
  2090. /* Return NULL in case of an error */
  2091. name_ptr = NULL;
  2092. }
  2093. else
  2094. {
  2095. /* Call the tx_event_flags_info_get to get the event flags name_ptr */
  2096. if (tx_event_flags_info_get(eventflags_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  2097. {
  2098. /* Return NULL in case of an error */
  2099. name_ptr = NULL;
  2100. }
  2101. }
  2102. return (name_ptr);
  2103. }
  2104. /**
  2105. * @brief The function osEventFlagsSet sets the event flags specified by the
  2106. * parameter flags in an event flags object specified by parameter ef_id.
  2107. * All threads waiting for the flag set will be notified to resume from
  2108. * BLOCKED state. The function returns the event flags stored in the event
  2109. * control block or an error code (highest bit is set, refer to Flags
  2110. * Functions Error Codes).
  2111. * Note : This function cannot be called from Interrupt Service
  2112. * Routines.
  2113. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2114. * [in] flags specifies the flags that shall be set.
  2115. * @retval event flags after setting or error code if highest bit set.
  2116. */
  2117. uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
  2118. {
  2119. /* For ThreadX the control block pointer is the semaphore identifier */
  2120. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2121. /* The returned flags_status or error */
  2122. uint32_t flags_status;
  2123. /* Flags to set */
  2124. ULONG flags_to_set = (ULONG) flags;
  2125. /* Check if the event flags ID is NULL or the event flags is invalid */
  2126. if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID))
  2127. {
  2128. /* Return osFlagsErrorParameter error */
  2129. flags_status = osFlagsErrorParameter;
  2130. }
  2131. else
  2132. {
  2133. /* Call the tx_event_flags_set to set flags */
  2134. if (tx_event_flags_set(eventflags_ptr, flags_to_set, TX_OR) == TX_SUCCESS)
  2135. {
  2136. /* Call the tx_event_flags_info_get to get the current flags */
  2137. if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) &flags_status, NULL, NULL, NULL) != TX_SUCCESS)
  2138. {
  2139. /* Return osFlagsErrorUnknown in case of an error */
  2140. flags_status = osFlagsErrorUnknown;
  2141. }
  2142. }
  2143. else
  2144. {
  2145. /* Return osFlagsErrorResource in case of error */
  2146. flags_status = osFlagsErrorResource;
  2147. }
  2148. }
  2149. return (flags_status);
  2150. }
  2151. /**
  2152. * @brief The function osEventFlagsClear clears the event flags specified by
  2153. * the parameter flags in an event flags object specified by parameter
  2154. * ef_id. The function returns the event flags before clearing or an error
  2155. * code (highest bit is set, refer to Flags Functions Error Codes).
  2156. * Note : This function cannot be called from Interrupt Service
  2157. * Routines.
  2158. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2159. * [in] flags specifies the flags that shall be cleared.
  2160. * @retval event flags before clearing or error code if highest bit set.
  2161. */
  2162. uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
  2163. {
  2164. /* For ThreadX the control block pointer is the semaphore identifier */
  2165. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2166. /* The returned flags_status or error */
  2167. uint32_t flags_status;
  2168. /* Flags to clear */
  2169. ULONG flags_to_clear = (ULONG) ~flags;
  2170. /* Check if the event flags ID is NULL or the event flags is invalid */
  2171. if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID))
  2172. {
  2173. /* Return osFlagsErrorParameter error */
  2174. flags_status = osFlagsErrorParameter;
  2175. }
  2176. else
  2177. {
  2178. /* Call the tx_event_flags_info_get to get the current flags */
  2179. if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) &flags_status, NULL, NULL, NULL) != TX_SUCCESS)
  2180. {
  2181. /* Return osFlagsErrorUnknown in case of an error */
  2182. flags_status = osFlagsErrorUnknown;
  2183. }
  2184. else
  2185. {
  2186. /* Call the tx_event_flags_set to set flags */
  2187. if (tx_event_flags_set(eventflags_ptr, flags_to_clear, TX_AND) != TX_SUCCESS)
  2188. {
  2189. /* Return osFlagsErrorResource in case of error */
  2190. flags_status = osFlagsErrorResource;
  2191. }
  2192. }
  2193. }
  2194. return (flags_status);
  2195. }
  2196. /**
  2197. * @brief The function osEventFlagsGet returns the event flags currently set
  2198. * in an event flags object specified by parameter ef_id or 0 in case of
  2199. * an error.
  2200. * Note : This function cannot be called from Interrupt Service
  2201. * Routines.
  2202. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2203. * @retval current event flags.
  2204. */
  2205. uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
  2206. {
  2207. /* For ThreadX the control block pointer is the event flags identifier */
  2208. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2209. /* The current flags */
  2210. uint32_t current_flags = 0;
  2211. /* Check if the event flags ID is NULL or the event flags is invalid */
  2212. if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID))
  2213. {
  2214. /* Return 0 in case of an error */
  2215. current_flags = 0;
  2216. }
  2217. else
  2218. {
  2219. /* Call the tx_event_flags_info_get to get the current flags */
  2220. if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) &current_flags, NULL, NULL, NULL) != TX_SUCCESS)
  2221. {
  2222. /* Return 0 in case of an error */
  2223. current_flags = 0;
  2224. }
  2225. }
  2226. return (current_flags);
  2227. }
  2228. /**
  2229. * @brief The function osEventFlagsWait suspends the execution of the
  2230. * currently RUNNING thread until any or all event flags specified by the
  2231. * parameter flags in the event object specified by parameter ef_id are
  2232. * set. When these event flags are already set, the function returns
  2233. * instantly. Otherwise, the thread is put into the state BLOCKED.
  2234. * Note : This function cannot be called from Interrupt Service
  2235. * Routines.
  2236. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2237. * [in] flags specifies the flags to wait for.
  2238. * [in] options specifies flags options (osFlagsXxxx).
  2239. * [in] timeout Timeout Value or 0 in case of no time-out.
  2240. * @retval event flags before clearing or error code if highest bit set.
  2241. */
  2242. uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags,
  2243. uint32_t options, uint32_t timeout)
  2244. {
  2245. /* For ThreadX the control block pointer is the semaphore identifier */
  2246. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2247. /* Flags to get */
  2248. ULONG requested_flags = (ULONG) flags;
  2249. /* The ThreadX wait option */
  2250. ULONG wait_option = (ULONG) timeout;
  2251. /* The ThreadX get options */
  2252. UINT get_option = 0;
  2253. /* The actual flags */
  2254. ULONG actual_flags;
  2255. /* ThreadX APIs status */
  2256. UINT status;
  2257. /* Check if the event flags ID is NULL or the event flags is invalid or non-zero timeout specified in an ISR */
  2258. if ((IS_IRQ_MODE() && (timeout != 0)) || (ef_id == NULL) ||
  2259. (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID))
  2260. {
  2261. /* Return osFlagsErrorParameter error */
  2262. actual_flags = osFlagsErrorParameter;
  2263. }
  2264. else
  2265. {
  2266. /* No clear option is used */
  2267. if ((options & osFlagsNoClear) == osFlagsNoClear)
  2268. {
  2269. if ((options & osFlagsWaitAll) == osFlagsWaitAll)
  2270. {
  2271. /* AND event option is used */
  2272. get_option = TX_AND;
  2273. }
  2274. else
  2275. {
  2276. /* OR event option is used */
  2277. get_option = TX_OR;
  2278. }
  2279. }
  2280. /* Clear option is used */
  2281. else
  2282. {
  2283. if ((options & osFlagsWaitAll) == osFlagsWaitAll)
  2284. {
  2285. /* AND clear event option is used */
  2286. get_option = TX_AND_CLEAR;
  2287. }
  2288. else
  2289. {
  2290. /* OR clear event option is used */
  2291. get_option = TX_OR_CLEAR;
  2292. }
  2293. }
  2294. /* Call the tx_event_flags_get to get flags */
  2295. status = tx_event_flags_get(eventflags_ptr, requested_flags, get_option, &actual_flags, wait_option);
  2296. /* Check the status */
  2297. if ((status == TX_NO_EVENTS) || (status == TX_WAIT_ERROR))
  2298. {
  2299. /* Return osFlagsErrorTimeout for timeout error */
  2300. actual_flags = osFlagsErrorTimeout;
  2301. }
  2302. else if (status != TX_SUCCESS)
  2303. {
  2304. /* Return osFlagsErrorResource in case of an error */
  2305. actual_flags = osFlagsErrorResource ;
  2306. }
  2307. }
  2308. return ((uint32_t)actual_flags);
  2309. }
  2310. /**
  2311. * @brief The function osEventFlagsDelete deletes the event flags object
  2312. * specified by parameter ef_id and releases the internal memory obtained
  2313. * for the event flags handling. After this call, the ef_id is no longer
  2314. * valid and cannot be used. This can cause starvation of threads that are
  2315. * waiting for flags of this event object. The ef_id may be created again
  2316. * using the function osEventFlagsNew.
  2317. * Note : This function cannot be called from Interrupt Service
  2318. * Routines.
  2319. * @param [in] ef_id event flags ID obtained by osEventFlagsNew.
  2320. * @retval status code that indicates the execution status of the function.
  2321. */
  2322. osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
  2323. {
  2324. /* For ThreadX the control block pointer is the event flags identifier */
  2325. TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id;
  2326. /* The returned status or error */
  2327. osStatus_t status;
  2328. /* Check if this API is called from Interrupt Service Routines */
  2329. if (IS_IRQ_MODE())
  2330. {
  2331. /* Return osErrorISR error */
  2332. status = osErrorISR;
  2333. }
  2334. /* Check if the event flags ID is NULL or the event flags is invalid */
  2335. else if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID))
  2336. {
  2337. /* Return osErrorParameter error */
  2338. status = osErrorParameter;
  2339. }
  2340. else
  2341. {
  2342. /* Call the tx_event_flags_delete to delete the event flags object */
  2343. if (tx_event_flags_delete(eventflags_ptr) == TX_SUCCESS)
  2344. {
  2345. /* Free the already allocated memory for thread control block */
  2346. if (MemFree(eventflags_ptr) == osOK)
  2347. {
  2348. /* Return osOK for success */
  2349. status = osOK;
  2350. }
  2351. else
  2352. {
  2353. /* Return osErrorResource in case of error */
  2354. status = osErrorResource;
  2355. }
  2356. }
  2357. else
  2358. {
  2359. /* Return osErrorResource in case of error */
  2360. status = osErrorResource;
  2361. }
  2362. }
  2363. return (status);
  2364. }
  2365. /*---------------------------------------------------------------------------*/
  2366. /*---------------------------Mutex Management APIs---------------------------*/
  2367. /*---------------------------------------------------------------------------*/
  2368. /**
  2369. * @brief The function osMutexNew creates and initializes a new mutex
  2370. * object and returns the pointer to the mutex object identifier or
  2371. * NULL in case of an error. It can be safely called before the RTOS
  2372. * is started (call to osKernelStart), but not before it is initialized
  2373. * call to osKernelInitialize).
  2374. * Note : This function cannot be called from Interrupt Service
  2375. * Routines.
  2376. * @param [in] attr mutex attributes; NULL: default values.
  2377. * @retval mutex ID for reference by other functions or NULL in case of error.
  2378. */
  2379. osMutexId_t osMutexNew(const osMutexAttr_t *attr)
  2380. {
  2381. /* For ThreadX the control block pointer is the mutex identifier */
  2382. TX_MUTEX *mutex_ptr = NULL;
  2383. /* Pointer to the mutex name */
  2384. CHAR *name_ptr = NULL;
  2385. /* The mutex inherit status */
  2386. UINT inherit = TX_NO_INHERIT;
  2387. /* The size of control block */
  2388. ULONG cb_size = sizeof(TX_MUTEX);
  2389. /* Check if this API is called from Interrupt Service Routines */
  2390. if (!IS_IRQ_MODE())
  2391. {
  2392. /* Check if the attr is not NULL */
  2393. if (attr != NULL)
  2394. {
  2395. /* Check if the name_ptr is not NULL */
  2396. if (attr->name != NULL)
  2397. {
  2398. /* Set the mutex name_ptr */
  2399. name_ptr = (CHAR *)attr->name;
  2400. }
  2401. /* Check if the attr_bits is not zero */
  2402. if (attr->attr_bits != 0)
  2403. {
  2404. /* Check the mutex inherit status */
  2405. if ((attr->attr_bits & osMutexPrioInherit) == osMutexPrioInherit)
  2406. {
  2407. inherit = TX_INHERIT;
  2408. }
  2409. else
  2410. {
  2411. inherit = TX_NO_INHERIT;
  2412. }
  2413. }
  2414. else
  2415. {
  2416. inherit = TX_NO_INHERIT;
  2417. }
  2418. /* Check if the control block size is equal to 0 */
  2419. if (attr->cb_size == 0U)
  2420. {
  2421. /* Set control block size to sizeof(TX_MUTEX) */
  2422. cb_size = sizeof(TX_MUTEX);
  2423. }
  2424. else if (attr->cb_size < sizeof(TX_MUTEX))
  2425. {
  2426. /* Return NULL pointer in case of error */
  2427. return (NULL);
  2428. }
  2429. else
  2430. {
  2431. /* Set control block size to attr->cb_size */
  2432. cb_size = (ULONG) attr->cb_size;
  2433. }
  2434. /* Check if the input control block pointer is NULL */
  2435. if (attr->cb_mem == NULL)
  2436. {
  2437. /* Allocate the mutex_ptr structure for the mutex to be created */
  2438. mutex_ptr = (TX_MUTEX *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2439. if (mutex_ptr == NULL)
  2440. {
  2441. /* Return NULL pointer in case of error */
  2442. return (NULL);
  2443. }
  2444. }
  2445. else
  2446. {
  2447. /* The control block shall point to the input cb_mem memory address */
  2448. mutex_ptr = attr->cb_mem;
  2449. }
  2450. }
  2451. else
  2452. {
  2453. /* Allocate the mutex_ptr structure for the mutex to be created */
  2454. mutex_ptr = (TX_MUTEX *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2455. }
  2456. /* Call the tx_mutex_create function to create the new mutex */
  2457. if (tx_mutex_create(mutex_ptr, name_ptr, inherit) != TX_SUCCESS)
  2458. {
  2459. if ((attr->cb_mem == NULL) || (attr == NULL))
  2460. {
  2461. /* Free the already allocated memory for mutex control block */
  2462. MemFree(mutex_ptr);
  2463. }
  2464. }
  2465. }
  2466. return ((osMutexId_t)mutex_ptr);
  2467. }
  2468. /**
  2469. * @brief The function osMutexGetName returns the pointer to the name string
  2470. * of the mutex identified by parameter mutex_id or NULL in case of
  2471. * an error.
  2472. * Note : This function cannot be called from Interrupt Service
  2473. * Routines.
  2474. * @param [in] mutex_id mutex ID obtained by osMutexNew.
  2475. * @retval name as null-terminated string.
  2476. */
  2477. const char *osMutexGetName(osMutexId_t mutex_id)
  2478. {
  2479. /* For ThreadX the control block pointer is the mutex identifier */
  2480. TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id;
  2481. /* The output name_ptr as null-terminated string */
  2482. CHAR *name_ptr;
  2483. /* Check if this API is called from Interrupt Service Routines
  2484. or the mutex_id is NULL or the mutex is invalid */
  2485. if (IS_IRQ_MODE() || (mutex_ptr == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID))
  2486. {
  2487. /* Return NULL in case of an error */
  2488. name_ptr = NULL;
  2489. }
  2490. else
  2491. {
  2492. /* Call the tx_mutex_info_get to get the mutex name_ptr */
  2493. if (tx_mutex_info_get(mutex_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  2494. {
  2495. /* Return NULL in case of an error */
  2496. name_ptr = NULL;
  2497. }
  2498. }
  2499. return (name_ptr);
  2500. }
  2501. /**
  2502. * @brief The blocking function osMutexAcquire waits until a mutex object
  2503. * specified by parameter mutex_id becomes available. If no other thread
  2504. * has obtained the mutex, the function instantly returns and blocks
  2505. * the mutex object.
  2506. * Note : This function cannot be called from Interrupt Service
  2507. * Routines.
  2508. * @param [in] mutex_id mutex ID obtained by osMutexNew.
  2509. * [in] timeout Timeout Value or 0 in case of no time-out.
  2510. * @retval status code that indicates the execution status of the function.
  2511. */
  2512. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)
  2513. {
  2514. /* For ThreadX the control block pointer is the mutex identifier */
  2515. TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id;
  2516. /* The returned status or error */
  2517. osStatus_t status;
  2518. /* The ThreadX wait option */
  2519. ULONG wait_option = (ULONG) timeout;
  2520. /* The tx_mutex_get returned status */
  2521. UINT tx_status;
  2522. /* Check if this API is called from Interrupt Service Routines */
  2523. if (IS_IRQ_MODE())
  2524. {
  2525. /* Return osErrorISR error */
  2526. status = osErrorISR;
  2527. }
  2528. /* Check if the mutex ID is NULL or the mutex is invalid */
  2529. else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID))
  2530. {
  2531. /* Return osErrorParameter error */
  2532. status = osErrorParameter;
  2533. }
  2534. else
  2535. {
  2536. /* Call the tx_mutex_get to get the mutex object */
  2537. tx_status = tx_mutex_get(mutex_ptr, wait_option);
  2538. if (tx_status == TX_SUCCESS)
  2539. {
  2540. /* Return osOK for success */
  2541. status = osOK;
  2542. }
  2543. else if ((tx_status == TX_WAIT_ABORTED) || (tx_status == TX_NOT_AVAILABLE))
  2544. {
  2545. /* Return osErrorTimeout when the mutex is not obtained in the given time */
  2546. status = osErrorTimeout;
  2547. }
  2548. else
  2549. {
  2550. /* Return osErrorResource in case of error */
  2551. status = osErrorResource;
  2552. }
  2553. }
  2554. return (status);
  2555. }
  2556. /**
  2557. * @brief The function osMutexRelease releases a mutex specified by parameter
  2558. * mutex_id. Other threads that currently wait for this mutex will be
  2559. * put into the READY state.
  2560. * Note : This function cannot be called from Interrupt Service
  2561. * Routines.
  2562. * @param [in] mutex_id mutex ID obtained by osMutexNew.
  2563. * @retval status code that indicates the execution status of the function.
  2564. */
  2565. osStatus_t osMutexRelease(osMutexId_t mutex_id)
  2566. {
  2567. /* For ThreadX the control block pointer is the mutex identifier */
  2568. TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id;
  2569. /* The returned status or error */
  2570. osStatus_t status;
  2571. /* Check if this API is called from Interrupt Service Routines */
  2572. if (IS_IRQ_MODE())
  2573. {
  2574. /* Return osErrorISR error */
  2575. status = osErrorISR;
  2576. }
  2577. /* Check if the mutex ID is NULL or the mutex is invalid */
  2578. else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID))
  2579. {
  2580. /* Return osErrorParameter error */
  2581. status = osErrorParameter;
  2582. }
  2583. else
  2584. {
  2585. /* Call the tx_mutex_put to put the mutex object */
  2586. if (tx_mutex_put(mutex_ptr) == TX_SUCCESS)
  2587. {
  2588. /* Return osOK for success */
  2589. status = osOK;
  2590. }
  2591. else
  2592. {
  2593. /* Return osErrorResource in case of error */
  2594. status = osErrorResource;
  2595. }
  2596. }
  2597. return (status);
  2598. }
  2599. /**
  2600. * @brief The function osMutexGetOwner returns the thread ID of the thread
  2601. * that acquired a mutex specified by parameter mutex_id. In case of an
  2602. * error or if the mutex is not blocked by any thread, it returns NULL.
  2603. * Note : This function cannot be called from Interrupt Service
  2604. * Routines.
  2605. * @param [in] mutex_id mutex ID obtained by osMutexNew.
  2606. * @retval thread ID of owner thread or NULL when mutex was not acquired.
  2607. */
  2608. osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)
  2609. {
  2610. /* For ThreadX the control block pointer is the mutex identifier */
  2611. TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id;
  2612. /* The owner thread of the mutex object */
  2613. TX_THREAD *thread_ptr = NULL;
  2614. /* Check if this API is called from Interrupt Service Routines */
  2615. if (IS_IRQ_MODE())
  2616. {
  2617. /* Return NULL when the API is called from ISR */
  2618. thread_ptr = NULL;
  2619. }
  2620. /* Check if the mutex ID is NULL or the mutex is invalid */
  2621. else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID))
  2622. {
  2623. /* Return NULL when mutex_id is NULL */
  2624. thread_ptr = NULL;
  2625. }
  2626. else
  2627. {
  2628. /* Call the tx_mutex_info_get to get the mutex thread owner */
  2629. if (tx_mutex_info_get(mutex_ptr, NULL, NULL, &thread_ptr, NULL, NULL, NULL) == TX_SUCCESS)
  2630. {
  2631. if (thread_ptr == TX_NULL)
  2632. {
  2633. /* Return NULL when mutex object is not acquired */
  2634. thread_ptr = NULL;
  2635. }
  2636. }
  2637. else
  2638. {
  2639. /* Return NULL when mutex_id is invalid */
  2640. thread_ptr = NULL;
  2641. }
  2642. }
  2643. return ((osThreadId_t)thread_ptr);
  2644. }
  2645. /**
  2646. * @brief The function osMutexDelete deletes a mutex object specified by
  2647. * parameter mutex_id. It releases internal memory obtained for mutex
  2648. * handling. After this call, the mutex_id is no longer valid and cannot
  2649. * be used. The mutex may be created again using the function osMutexNew.
  2650. * Note : This function cannot be called from Interrupt Service
  2651. * Routines.
  2652. * @param [in] mutex_id mutex ID obtained by osMutexNew.
  2653. * @retval status code that indicates the execution status of the function.
  2654. */
  2655. osStatus_t osMutexDelete(osMutexId_t mutex_id)
  2656. {
  2657. /* For ThreadX the control block pointer is the mutex identifier */
  2658. TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id;
  2659. /* The returned status or error */
  2660. osStatus_t status;
  2661. /* Check if this API is called from Interrupt Service Routines */
  2662. if (IS_IRQ_MODE())
  2663. {
  2664. /* Return osErrorISR error */
  2665. status = osErrorISR;
  2666. }
  2667. /* Check if the mutex ID is NULL or the mutex is invalid*/
  2668. else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID))
  2669. {
  2670. /* Return osErrorParameter error */
  2671. status = osErrorParameter;
  2672. }
  2673. else
  2674. {
  2675. /* Call the tx_mutex_delete to delete the mutex object */
  2676. if (tx_mutex_delete(mutex_ptr) == TX_SUCCESS)
  2677. {
  2678. /* Free the already allocated memory for mutex control block */
  2679. if (MemFree(mutex_ptr) == osOK)
  2680. {
  2681. /* Return osOK for success */
  2682. status = osOK;
  2683. }
  2684. else
  2685. {
  2686. /* Return osErrorResource in case of error */
  2687. status = osErrorResource;
  2688. }
  2689. }
  2690. else
  2691. {
  2692. /* Return osErrorResource in case of error */
  2693. status = osErrorResource;
  2694. }
  2695. }
  2696. return (status);
  2697. }
  2698. /*---------------------------------------------------------------------------*/
  2699. /*------------------------------Semaphores APIs------------------------------*/
  2700. /*---------------------------------------------------------------------------*/
  2701. /**
  2702. * @brief The function osSemaphoreNew creates and initializes a semaphore
  2703. * object that is used to manage access to shared resources and returns
  2704. * the pointer to the semaphore object identifier or NULL in case of an
  2705. * error. It can be safely called before the RTOS is started
  2706. * (call to osKernelStart), but not before it is initialized
  2707. * (call to osKernelInitialize).
  2708. * Note : This function cannot be called from Interrupt Service
  2709. * Routines.
  2710. * @param [in] max_count maximum number of available tokens.
  2711. * [in] initial_count initial number of available tokens.
  2712. * [in] attr semaphore attributes; NULL: default values.
  2713. * @retval semaphore ID for reference by other functions or NULL in case of error.
  2714. */
  2715. osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
  2716. {
  2717. /* For ThreadX the control block pointer is the semaphore identifier */
  2718. TX_SEMAPHORE *semaphore_ptr = NULL;
  2719. /* Pointer to the semaphore name */
  2720. CHAR *name_ptr = NULL;
  2721. /* The semaphore initial count */
  2722. ULONG init_count = (ULONG) initial_count;
  2723. /* The size of control block */
  2724. ULONG cb_size = sizeof(TX_SEMAPHORE);
  2725. /* Check if this API is called from Interrupt Service Routines */
  2726. if (!IS_IRQ_MODE())
  2727. {
  2728. /* Check if the attr is not NULL */
  2729. if (attr != NULL)
  2730. {
  2731. /* Check if the name_ptr is not NULL */
  2732. if (attr->name != NULL)
  2733. {
  2734. /* Set the semaphore name_ptr */
  2735. name_ptr = (CHAR *)attr->name;
  2736. }
  2737. /* Check if the control block size is equal to 0 */
  2738. if (attr->cb_size == 0U)
  2739. {
  2740. /* Set control block size to sizeof(TX_SEMAPHORE) */
  2741. cb_size = sizeof(TX_SEMAPHORE);
  2742. }
  2743. else if (attr->cb_size < sizeof(TX_SEMAPHORE))
  2744. {
  2745. /* Return NULL pointer in case of error */
  2746. return (NULL);
  2747. }
  2748. else
  2749. {
  2750. /* Set control block size to attr->cb_size */
  2751. cb_size = (ULONG) attr->cb_size;
  2752. }
  2753. /* Check if the input control block pointer is NULL */
  2754. if (attr->cb_mem == NULL)
  2755. {
  2756. /* Allocate the semaphore_ptr structure for the semaphore to be created */
  2757. semaphore_ptr = (TX_SEMAPHORE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2758. if (semaphore_ptr == NULL)
  2759. {
  2760. /* Return NULL pointer in case of error */
  2761. return (NULL);
  2762. }
  2763. }
  2764. else
  2765. {
  2766. /* The control block shall point to the input cb_mem memory address */
  2767. semaphore_ptr = attr->cb_mem;
  2768. }
  2769. }
  2770. else
  2771. {
  2772. /* Allocate the semaphore_ptr structure for the semaphore to be created */
  2773. semaphore_ptr = (TX_SEMAPHORE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  2774. }
  2775. /* Call the tx_semaphore_create function to create the new semaphore */
  2776. if (tx_semaphore_create(semaphore_ptr, name_ptr, init_count) != TX_SUCCESS)
  2777. {
  2778. if ((attr->cb_mem == NULL) || (attr == NULL))
  2779. {
  2780. /* Free the already allocated memory for semaphore control block */
  2781. MemFree(semaphore_ptr);
  2782. }
  2783. }
  2784. }
  2785. return ((osSemaphoreId_t)semaphore_ptr);
  2786. }
  2787. /**
  2788. * @brief The function osSemaphoreGetName returns the pointer to the name
  2789. * string of the semaphore identified by parameter semaphore_id or NULL
  2790. * in case of an error.
  2791. * Note : This function cannot be called from Interrupt Service
  2792. * Routines.
  2793. * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew.
  2794. * @retval name as null-terminated string.
  2795. */
  2796. const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
  2797. {
  2798. /* For ThreadX the control block pointer is the semaphore identifier */
  2799. TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id;
  2800. /* The output name_ptr as null-terminated string */
  2801. CHAR *name_ptr;
  2802. /* Check if this API is called from Interrupt Service Routines or the semaphore_id is NULL
  2803. and the semaphore is invalid */
  2804. if (IS_IRQ_MODE() || (semaphore_ptr == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID))
  2805. {
  2806. /* Return NULL in case of an error */
  2807. name_ptr = NULL;
  2808. }
  2809. else
  2810. {
  2811. /* Call the tx_semaphore_info_get to get the semaphore name_ptr */
  2812. if (tx_semaphore_info_get(semaphore_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  2813. {
  2814. /* Return NULL in case of an error */
  2815. name_ptr = NULL;
  2816. }
  2817. }
  2818. return (name_ptr);
  2819. }
  2820. /**
  2821. * @brief The blocking function osSemaphoreAcquire waits until a token of the
  2822. * semaphore object specified by parameter semaphore_id becomes available.
  2823. * If a token is available, the function instantly returns and decrements
  2824. * the token count.
  2825. * Note : This function cannot be called from Interrupt Service
  2826. * Routines.
  2827. * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew.
  2828. * [in] timeout Timeout Value or 0 in case of no time-out.
  2829. * @retval status code that indicates the execution status of the function.
  2830. */
  2831. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
  2832. {
  2833. /* For ThreadX the control block pointer is the semaphore identifier */
  2834. TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id;
  2835. /* The returned status or error */
  2836. osStatus_t status;
  2837. /* The ThreadX wait option */
  2838. ULONG wait_option = (ULONG) timeout;
  2839. /* The tx_semaphore_get returned status */
  2840. UINT tx_status;
  2841. /* Check if the semaphore ID is NULL or the semaphore is invalid or non-zero timeout specified in an ISR */
  2842. if ((IS_IRQ_MODE() && (timeout != 0)) || (semaphore_id == NULL) ||
  2843. (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID))
  2844. {
  2845. /* Return osErrorParameter error */
  2846. status = osErrorParameter;
  2847. }
  2848. else
  2849. {
  2850. /* Call the tx_semaphore_get to get the semaphore object */
  2851. tx_status = tx_semaphore_get(semaphore_ptr, wait_option);
  2852. if (tx_status == TX_SUCCESS)
  2853. {
  2854. /* Return osOK for success */
  2855. status = osOK;
  2856. }
  2857. else if ((tx_status == TX_WAIT_ABORTED) || (tx_status == TX_NO_INSTANCE))
  2858. {
  2859. /* Return osErrorTimeout when the semaphore is not obtained
  2860. in the given time */
  2861. status = osErrorTimeout;
  2862. }
  2863. else
  2864. {
  2865. /* Return osErrorResource in case of error */
  2866. status = osErrorResource;
  2867. }
  2868. }
  2869. return (status);
  2870. }
  2871. /**
  2872. * @brief The function osSemaphoreRelease releases a token of the semaphore
  2873. * object specified by parameter semaphore_id. Tokens can only be released
  2874. * up to the maximum count specified at creation time, see osSemaphoreNew.
  2875. * Other threads that currently wait for a token of this semaphore object
  2876. * will be put into the READY state.
  2877. * Note : This function cannot be called from Interrupt Service
  2878. * Routines.
  2879. * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew.
  2880. * @retval status code that indicates the execution status of the function.
  2881. */
  2882. osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
  2883. {
  2884. /* For ThreadX the control block pointer is the semaphore identifier */
  2885. TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id;
  2886. /* The returned status or error */
  2887. osStatus_t status;
  2888. /* Check if the semaphore ID is NULL or the semaphore is invalid */
  2889. if ((semaphore_id == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID))
  2890. {
  2891. /* Return osErrorParameter error */
  2892. status = osErrorParameter;
  2893. }
  2894. else
  2895. {
  2896. /* Call the tx_semaphore_put to put the semaphore object */
  2897. if (tx_semaphore_put(semaphore_ptr) == TX_SUCCESS)
  2898. {
  2899. /* Return osOK for success */
  2900. status = osOK;
  2901. }
  2902. else
  2903. {
  2904. /* Return osErrorResource in case of error */
  2905. status = osErrorResource;
  2906. }
  2907. }
  2908. return (status);
  2909. }
  2910. /**
  2911. * @brief The function osSemaphoreDelete deletes a semaphore object specified
  2912. * by parameter semaphore_id. It releases internal memory obtained for
  2913. * semaphore handling. After this call, the semaphore_id is no longer
  2914. * valid and cannot be used. The semaphore may be created again using
  2915. * the function osSemaphoreNew.
  2916. * Note : This function cannot be called from Interrupt Service
  2917. * Routines.
  2918. * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew.
  2919. * @retval status code that indicates the execution status of the function.
  2920. */
  2921. osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
  2922. {
  2923. /* For ThreadX the control block pointer is the semaphore identifier */
  2924. TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id;
  2925. /* The returned status or error */
  2926. osStatus_t status;
  2927. /* Check if this API is called from Interrupt Service Routines */
  2928. if (IS_IRQ_MODE())
  2929. {
  2930. /* Return osErrorISR error */
  2931. status = osErrorISR;
  2932. }
  2933. /* Check if the semaphore ID is NULL or the semaphore is invalid */
  2934. else if ((semaphore_id == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID))
  2935. {
  2936. /* Return osErrorParameter error */
  2937. status = osErrorParameter;
  2938. }
  2939. else
  2940. {
  2941. /* Call the tx_semaphore_delete to delete the semaphore object */
  2942. if (tx_semaphore_delete(semaphore_ptr) == TX_SUCCESS)
  2943. {
  2944. /* Free the already allocated memory for semaphore control block */
  2945. if (MemFree(semaphore_ptr) == osOK)
  2946. {
  2947. /* Return osOK for success */
  2948. status = osOK;
  2949. }
  2950. else
  2951. {
  2952. /* Return osErrorResource in case of error */
  2953. status = osErrorResource;
  2954. }
  2955. }
  2956. else
  2957. {
  2958. /* Return osErrorResource in case of error */
  2959. status = osErrorResource;
  2960. }
  2961. }
  2962. return (status);
  2963. }
  2964. /*---------------------------------------------------------------------------*/
  2965. /*------------------------------Message Queue APIs---------------------------*/
  2966. /*---------------------------------------------------------------------------*/
  2967. /**
  2968. * @brief The function osMessageQueueNew creates and initializes a message queue
  2969. * object. The function returns a message queue object identifier
  2970. * or NULL in case of an error.
  2971. * The function can be called after kernel initialization with osKernelInitialize.
  2972. * It is possible to create message queue objects before the RTOS kernel is
  2973. * started with osKernelStart.
  2974. * The total amount of memory required for the message queue data is at least
  2975. * msg_count * msg_size. The msg_size is rounded up to a double even number to
  2976. * ensure 32-bit alignment of the memory blocks.
  2977. * The memory blocks allocated from the message queue have a fixed size defined
  2978. * with the parameter msg_size.
  2979. * Note : This function Cannot be called from Interrupt Service
  2980. * Routines.
  2981. * @param [in] msg_count maximum number of messages in queue.
  2982. * [in] msg_size maximum message size in bytes.
  2983. * [in] attr message queue attributes; NULL: default values.
  2984. * @retval message queue ID for reference by other functions or NULL in case of error.
  2985. */
  2986. osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr)
  2987. {
  2988. /* For TX_QUEUE the control block pointer is the queue identifier */
  2989. TX_QUEUE *queue_ptr = NULL;
  2990. /* Pointer to the message queue name */
  2991. CHAR *name_ptr = NULL;
  2992. /* Pointer to start address of the message queue data */
  2993. VOID *queue_start = NULL;
  2994. /* The message queue data size */
  2995. ULONG queue_size = 0U;
  2996. /* The message queue control block size */
  2997. ULONG cb_size = 0U;
  2998. /* Check if this API is called from Interrupt Service Routines or the msg_count
  2999. is equal to 0 or msg_size is equal to 0 */
  3000. if (!IS_IRQ_MODE() && (msg_count > 0) && (msg_size > 0))
  3001. {
  3002. /* Initialize the name_ptr to NULL */
  3003. name_ptr = NULL;
  3004. /* The msg_size is rounded up to a double even number to ensure 32-bit alignment of the memory blocks. */
  3005. msg_size = msg_size + (msg_size % sizeof(ULONG));
  3006. /* Check if the attr is not NULL */
  3007. if (attr != NULL)
  3008. {
  3009. /* Check if the name_ptr is not NULL */
  3010. if (attr->name != NULL)
  3011. {
  3012. /* Set the message queue name_ptr */
  3013. name_ptr = (CHAR *)attr->name;
  3014. }
  3015. /* Check if the message queue data size is equal to 0 */
  3016. if (attr->mq_size == 0U)
  3017. {
  3018. /* Set message queue data size to msg_count * msg_size (The total amount of memory required
  3019. for the message queue data) */
  3020. queue_size = msg_count * msg_size;
  3021. }
  3022. else if (attr->mq_size < (msg_count * msg_size))
  3023. {
  3024. /* Return NULL pointer in case of error */
  3025. return (NULL);
  3026. }
  3027. else if (attr->mq_size < TX_BYTE_POOL_MIN)
  3028. {
  3029. /* Set message queue data size to TX_BYTE_POOL_MIN */
  3030. queue_size = TX_BYTE_POOL_MIN;
  3031. }
  3032. else
  3033. {
  3034. /* Set message queue data size to attr->mq_size */
  3035. queue_size = (ULONG)attr->mq_size;
  3036. }
  3037. /* Check if the input message queue data pointer is NULL */
  3038. if (attr->mq_mem == NULL)
  3039. {
  3040. /* Allocate the data for the message queue to be created */
  3041. queue_start = MemAlloc(queue_size, RTOS2_BYTE_POOL_STACK_TYPE);
  3042. if (queue_start == NULL)
  3043. {
  3044. /* Return NULL pointer in case of error */
  3045. return (NULL);
  3046. }
  3047. }
  3048. else
  3049. {
  3050. if (attr->mq_size == 0U)
  3051. {
  3052. /* Return NULL pointer in case of error */
  3053. return (NULL);
  3054. }
  3055. else
  3056. {
  3057. /* Set message queue data size to attr->mq_size */
  3058. queue_size = (ULONG)attr->mq_size;
  3059. }
  3060. /* The message queue data shall point to the input message queue data memory address */
  3061. queue_start = attr->mq_mem;
  3062. }
  3063. /* Check if the control block size is equal to 0 */
  3064. if (attr->cb_size == 0U)
  3065. {
  3066. /* Set control block size to sizeof(TX_QUEUE) */
  3067. cb_size = sizeof(TX_QUEUE);
  3068. }
  3069. else if (attr->cb_size < sizeof(TX_QUEUE))
  3070. {
  3071. /* Return NULL pointer in case of error */
  3072. return (NULL);
  3073. }
  3074. else
  3075. {
  3076. /* Set message queue data size to attr->cb_size */
  3077. cb_size = (ULONG)attr->cb_size;
  3078. }
  3079. /* Check if the input control block pointer is NULL */
  3080. if (attr->cb_mem == NULL)
  3081. {
  3082. /* Allocate the queue_ptr structure for the message queue to be created */
  3083. queue_ptr = (TX_QUEUE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  3084. if (queue_ptr == NULL)
  3085. {
  3086. /* Check if the memory for message queue data has been internally allocated */
  3087. if (attr->mq_mem == NULL)
  3088. {
  3089. /* Free the already allocated memory for message queue data */
  3090. MemFree(queue_start);
  3091. }
  3092. /* Return NULL pointer in case of error */
  3093. return (NULL);
  3094. }
  3095. }
  3096. else
  3097. {
  3098. /* The control block shall point to the input cb_mem memory address */
  3099. queue_ptr = attr->cb_mem;
  3100. }
  3101. }
  3102. else
  3103. {
  3104. /* Initialize the name_ptr to NULL */
  3105. name_ptr = NULL;
  3106. /* Initialize the message queue data size to msg_count * msg_size (The total amount of memory required
  3107. for the message queue data) */
  3108. queue_size = msg_count * msg_size;
  3109. /* Allocate the data for the message queue to be created */
  3110. queue_start = MemAlloc(queue_size, RTOS2_BYTE_POOL_STACK_TYPE);
  3111. if (queue_start == NULL)
  3112. {
  3113. /* Return NULL pointer in case of error */
  3114. return (NULL);
  3115. }
  3116. /* Allocate the queue_ptr structure for the message queue to be created */
  3117. queue_ptr = (TX_QUEUE *)MemAlloc(sizeof(TX_QUEUE), RTOS2_BYTE_POOL_HEAP_TYPE);
  3118. if (queue_ptr == NULL)
  3119. {
  3120. /* Free the already allocated memory for message queue data */
  3121. MemFree(queue_start);
  3122. /* Return NULL pointer in case of error */
  3123. return (NULL);
  3124. }
  3125. }
  3126. /* For threadX the message size is in 32-Bits */
  3127. msg_size = msg_size / sizeof(ULONG);
  3128. /* Call the tx_queue_create function to create the new message queue */
  3129. if (tx_queue_create(queue_ptr, name_ptr, msg_size, queue_start, queue_size) != TX_SUCCESS)
  3130. {
  3131. /* Check if the memory for message queue control block has been internally
  3132. allocated */
  3133. if ((attr->cb_mem == NULL) || (attr == NULL))
  3134. {
  3135. /* Free the already allocated memory for message queue control block */
  3136. MemFree(queue_ptr);
  3137. }
  3138. /* Check if the memory for message queue data has been internally allocated */
  3139. if ((attr->mq_mem == NULL) || (attr == NULL))
  3140. {
  3141. /* Free the already allocated memory for message queue data */
  3142. MemFree(queue_start);
  3143. }
  3144. /* Return NULL pointer in case of error */
  3145. queue_ptr = NULL;
  3146. }
  3147. }
  3148. return ((osMessageQueueId_t)queue_ptr);
  3149. }
  3150. /**
  3151. * @brief The function osMessageQueueGetName returns the pointer to the name
  3152. * string of the message queue identified by parameter mq_id or NULL in
  3153. * case of an error.
  3154. * Note : This function cannot be called from Interrupt Service
  3155. * Routines.
  3156. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3157. * @retval name_ptr as null-terminated string.
  3158. */
  3159. const char *osMessageQueueGetName(osMessageQueueId_t mq_id)
  3160. {
  3161. /* For TX_QUEUE the control block pointer is the queue identifier */
  3162. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3163. /* The output name_ptr as null-terminated string */
  3164. CHAR *name_ptr = NULL;
  3165. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3166. NULL or mq_id->tx_queue_id != TX_QUEUE_ID */
  3167. if (IS_IRQ_MODE() || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3168. {
  3169. /* Return NULL in case of an error */
  3170. name_ptr = NULL;
  3171. }
  3172. else
  3173. {
  3174. /* Call the tx_queue_info_get to get the queue name_ptr */
  3175. if (tx_queue_info_get(queue_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  3176. {
  3177. /* Return NULL in case of an error */
  3178. name_ptr = NULL;
  3179. }
  3180. }
  3181. return (name_ptr);
  3182. }
  3183. /**
  3184. * @brief The function osMessageQueueGetCapacity returns the maximum number of
  3185. * messages in the message queue object specified by parameter mq_id or
  3186. * 0 in case of an error.
  3187. * Note : This function may be called from Interrupt Service
  3188. * Routines.
  3189. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3190. * @retval maximum number of messages.
  3191. */
  3192. uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id)
  3193. {
  3194. /* For TX_QUEUE the control block pointer is the queue identifier */
  3195. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3196. /* The specific maximum number of messages */
  3197. uint32_t max_messages_number;
  3198. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3199. if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3200. {
  3201. /* Return 0 in case of error */
  3202. max_messages_number = 0U;
  3203. }
  3204. else
  3205. {
  3206. /* Return the total number of messages in the queue */
  3207. max_messages_number = queue_ptr->tx_queue_capacity;
  3208. }
  3209. return (max_messages_number);
  3210. }
  3211. /**
  3212. * @brief The function osMessageQueueGetMsgSize returns the maximum message
  3213. * size in bytes for the message queue object specified by parameter
  3214. * mq_id or 0 in case of an error.
  3215. * Note : This function may be called from Interrupt Service
  3216. * Routines.
  3217. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3218. * @retval maximum message size in bytes.
  3219. */
  3220. uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id)
  3221. {
  3222. /* For TX_QUEUE the control block pointer is the queue identifier */
  3223. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3224. /* The specific maximum message size in bytes */
  3225. uint32_t max_messages_size;
  3226. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3227. if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3228. {
  3229. /* Return 0 in case of error */
  3230. max_messages_size = 0U;
  3231. }
  3232. else
  3233. {
  3234. /* Return the message size that was specified in queue creation */
  3235. max_messages_size = queue_ptr->tx_queue_message_size * sizeof(ULONG);
  3236. }
  3237. return (max_messages_size);
  3238. }
  3239. /**
  3240. * @brief The function osMessageQueueGetCount returns the number of queued
  3241. * messages in the message queue object specified by parameter mq_id or
  3242. * 0 in case of an error.
  3243. * Note : This function may be called from Interrupt Service
  3244. * Routines.
  3245. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3246. * @retval number of queued messages.
  3247. */
  3248. uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id)
  3249. {
  3250. /* For TX_QUEUE the control block pointer is the queue identifier */
  3251. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3252. /* The specific number of queued messages */
  3253. uint32_t queued_messages_number = 0U;
  3254. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3255. if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3256. {
  3257. /* Return 0 in case of error */
  3258. queued_messages_number = 0U;
  3259. }
  3260. else
  3261. {
  3262. /* Call the tx_queue_info_get to get the number of queued messages */
  3263. if (tx_queue_info_get(queue_ptr, NULL, (ULONG *)&queued_messages_number, NULL, NULL, NULL, NULL) != TX_SUCCESS)
  3264. {
  3265. /* Return 0 in case of error */
  3266. queued_messages_number = 0U;
  3267. }
  3268. }
  3269. return (queued_messages_number);
  3270. }
  3271. /**
  3272. * @brief The function osMessageQueueGetSpace returns the number available
  3273. * slots for messages in the message queue object specified by
  3274. * parameter mq_id or 0 in case of an error.
  3275. * Note : This function may be called from Interrupt Service
  3276. * Routines.
  3277. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3278. * @retval number of available slots for messages.
  3279. */
  3280. uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id)
  3281. {
  3282. /* For TX_QUEUE the control block pointer is the queue identifier */
  3283. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3284. /* The specific number of queued messages */
  3285. uint32_t queue_messages_free_slots = 0U;
  3286. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3287. if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3288. {
  3289. /* Return 0 in case of error */
  3290. queue_messages_free_slots = 0U;
  3291. }
  3292. else
  3293. {
  3294. /* Call the tx_queue_info_get to get the number of available slots for
  3295. messages */
  3296. if (tx_queue_info_get(queue_ptr, NULL, NULL, (ULONG *)&queue_messages_free_slots, NULL, NULL, NULL) != TX_SUCCESS)
  3297. {
  3298. /* Return 0 in case of error */
  3299. queue_messages_free_slots = 0U;
  3300. }
  3301. }
  3302. return (queue_messages_free_slots);
  3303. }
  3304. /**
  3305. * @brief The function osMessageQueueReset resets the message queue specified
  3306. * by the parameter mq_id.
  3307. * Note : This function cannot be called from Interrupt Service
  3308. * Routines.
  3309. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3310. * @retval status code that indicates the execution status of the function.
  3311. */
  3312. osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id)
  3313. {
  3314. /* For TX_QUEUE the control block pointer is the queue identifier */
  3315. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3316. /* The returned status or error */
  3317. osStatus_t status;
  3318. /* Check if this API is called from Interrupt Service Routines */
  3319. if (IS_IRQ_MODE())
  3320. {
  3321. /* Return osErrorISR error */
  3322. status = osErrorISR;
  3323. }
  3324. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3325. else if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3326. {
  3327. /* Return osErrorParameter error */
  3328. status = osErrorParameter;
  3329. }
  3330. else
  3331. {
  3332. /* Call the tx_queue_flush deletes all messages stored in the specified
  3333. message queue */
  3334. if (tx_queue_flush(queue_ptr) == TX_SUCCESS)
  3335. {
  3336. /* Return osOK in case of success */
  3337. status = osOK;
  3338. }
  3339. else
  3340. {
  3341. /* Return osErrorResource in case of error */
  3342. status = osErrorResource;
  3343. }
  3344. }
  3345. return (status);
  3346. }
  3347. /**
  3348. * @brief The function osMessageQueueDelete deletes a message queue object
  3349. * specified by parameter mq_id. It releases internal memory obtained
  3350. * for message queue handling. After this call, the mq_id is no longer
  3351. * valid and cannot be used. The message queue may be created again
  3352. * using the function osMessageQueueNew.
  3353. * Note : This function cannot be called from Interrupt Service
  3354. * Routines.
  3355. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3356. * @retval status code that indicates the execution status of the function.
  3357. */
  3358. osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id)
  3359. {
  3360. /* For TX_QUEUE the control block pointer is the queue identifier */
  3361. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3362. /* The returned status or error */
  3363. osStatus_t status;
  3364. /* Check if this API is called from Interrupt Service Routines */
  3365. if (IS_IRQ_MODE())
  3366. {
  3367. /* Return osErrorISR error */
  3368. status = osErrorISR;
  3369. }
  3370. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */
  3371. else if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID))
  3372. {
  3373. /* Return osErrorParameter error */
  3374. status = osErrorParameter;
  3375. }
  3376. else
  3377. {
  3378. /* Call the tx_queue_delete deletes the specified message queue */
  3379. if (tx_queue_delete(queue_ptr) == TX_SUCCESS)
  3380. {
  3381. /* Free the already allocated memory for message queue data */
  3382. MemFree(queue_ptr->tx_queue_start);
  3383. /* Free the already allocated memory for message queue control block */
  3384. MemFree(queue_ptr);
  3385. /* Return osOK in case of success */
  3386. status = osOK;
  3387. }
  3388. else
  3389. {
  3390. /* Return osErrorResource in case of error */
  3391. status = osErrorResource;
  3392. }
  3393. }
  3394. return (status);
  3395. }
  3396. /**
  3397. * @brief The blocking function osMessageQueuePut puts the message pointed to
  3398. * by msg_ptr into the the message queue specified by parameter mq_id.
  3399. * The parameter msg_prio is used to sort message according their
  3400. * priority (higher numbers indicate a higher priority) on insertion.
  3401. * The parameter timeout specifies how long the system waits to put the
  3402. * message into the queue. While the system waits, the thread that is
  3403. * calling this function is put into the BLOCKED state. The parameter
  3404. * timeout can have the following values:
  3405. * * when timeout is 0, the function returns instantly (i.e. try
  3406. * semantics).
  3407. * * when timeout is set to osWaitForever the function will wait for an
  3408. * infinite time until the message is delivered (i.e. wait semantics).
  3409. * * all other values specify a time in kernel ticks for a timeout
  3410. * (i.e. timed-wait semantics).
  3411. * Note : This function may be called from Interrupt Service
  3412. * Routines.
  3413. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3414. * [in] msg_ptr pointer to buffer with message to put into a queue.
  3415. * [in] msg_prio message priority.
  3416. * [in] timeout Timeout Value or 0 in case of no time-out.
  3417. * @retval status code that indicates the execution status of the function.
  3418. */
  3419. osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout)
  3420. {
  3421. /* For TX_QUEUE the control block pointer is the queue identifier */
  3422. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3423. /* The returned value from ThreadX call */
  3424. UINT tx_status;
  3425. /* The returned status or error */
  3426. osStatus_t status;
  3427. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID or non-zero timeout specified in an ISR */
  3428. if ((IS_IRQ_MODE() && (timeout != 0)) || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID) ||
  3429. (msg_ptr == NULL))
  3430. {
  3431. /* Return osErrorParameter error */
  3432. status = osErrorParameter;
  3433. }
  3434. else
  3435. {
  3436. /* Call the tx_queue_send to send a message to the specified message queue */
  3437. tx_status = tx_queue_send(queue_ptr, (void *)msg_ptr, timeout);
  3438. if (tx_status == TX_SUCCESS)
  3439. {
  3440. /* Return osOK in case of success */
  3441. status = osOK;
  3442. }
  3443. else if (tx_status == TX_QUEUE_FULL)
  3444. {
  3445. /* Return osErrorResource in case of error */
  3446. status = osErrorResource;
  3447. }
  3448. else
  3449. {
  3450. /* Return osErrorTimeout in case of error */
  3451. status = osErrorTimeout;
  3452. }
  3453. }
  3454. return (status);
  3455. }
  3456. /**
  3457. * @brief The function osMessageQueueGet retrieves a message from the message
  3458. * queue specified by the parameter mq_id and saves it to the buffer pointed
  3459. * to by the parameter msg_ptr. The message priority is stored to parameter
  3460. * msg_prio if not token{NULL}.
  3461. * The parameter timeout specifies how long the system waits to retrieve
  3462. * the message from the queue. While the system waits, the thread that is
  3463. * calling this function is put into the BLOCKED state.
  3464. * The parameter timeout can have the following values:
  3465. * * when timeout is 0, the function returns instantly (i.e. try
  3466. * semantics).
  3467. * * when timeout is set to osWaitForever the function will wait for an
  3468. * infinite time until the message is delivered (i.e. wait semantics).
  3469. * * all other values specify a time in kernel ticks for a timeout
  3470. * (i.e. timed-wait semantics).
  3471. * Note : This function may be called from Interrupt Service
  3472. * Routines.
  3473. * @param [in] mq_id message queue ID obtained by osMessageQueueNew.
  3474. * [out] msg_ptr pointer to buffer for message to get from a queue.
  3475. * [out] msg_prio pointer to buffer for message priority or NULL.
  3476. * [in] timeout Timeout Value or 0 in case of no time-out.
  3477. * @retval status code that indicates the execution status of the function.
  3478. */
  3479. osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout)
  3480. {
  3481. /* For TX_QUEUE the control block pointer is the queue identifier */
  3482. TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id;
  3483. /* The returned value from ThreadX call */
  3484. UINT tx_status;
  3485. /* The returned status or error */
  3486. osStatus_t status;
  3487. /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID or non-zero timeout specified in an ISR */
  3488. if ((IS_IRQ_MODE() && (timeout != 0)) || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID) ||
  3489. (msg_ptr == NULL))
  3490. {
  3491. /* Return osErrorParameter error */
  3492. status = osErrorParameter;
  3493. }
  3494. else
  3495. {
  3496. /* Call the tx_queue_receive to retrieves a message from the specified message queue */
  3497. tx_status = tx_queue_receive(queue_ptr, msg_ptr, timeout);
  3498. if (tx_status == TX_SUCCESS)
  3499. {
  3500. /* Return osOK in case of success */
  3501. status = osOK;
  3502. }
  3503. else if (tx_status == TX_QUEUE_EMPTY)
  3504. {
  3505. /* Return osErrorTimeout in case of error */
  3506. status = osErrorTimeout;
  3507. }
  3508. else if (tx_status == TX_WAIT_ERROR)
  3509. {
  3510. /* Return osErrorParameter when a non-zero timeout is used in ISR context */
  3511. status = osErrorParameter;
  3512. }
  3513. else
  3514. {
  3515. /* Return osErrorResource in case of error */
  3516. status = osErrorResource;
  3517. }
  3518. }
  3519. return (status);
  3520. }
  3521. /*---------------------------------------------------------------------------*/
  3522. /*---------------------------Memory Pool Management APIs---------------------*/
  3523. /*---------------------------------------------------------------------------*/
  3524. /**
  3525. * @brief The function osMemoryPoolNew creates and initializes a memory pool
  3526. * object and returns the pointer to the memory pool object identifier
  3527. * or NULL in case of an error. It can be safely called before the RTOS
  3528. * is started (call to osKernelStart), but not before it is initialized
  3529. * (call to osKernelInitialize).
  3530. * The total amount of memory needed is at least block_count * block_size.
  3531. * Memory from the pool can only be allocated/freed in fixed portions
  3532. * of block_size.
  3533. * Note : This function cannot be called from Interrupt Service Routines.
  3534. * @param [in] block_count maximum number of memory blocks in memory pool.
  3535. * [in] block_size memory block size in bytes.
  3536. * [in] attr memory pool attributes; NULL: default values.
  3537. * @retval memory pool ID for reference by other functions or NULL in case of error.
  3538. */
  3539. osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
  3540. {
  3541. /* For TX_BLOCK_POOL the control block pointer is the memory pool identifier */
  3542. TX_BLOCK_POOL *block_pool_ptr = NULL;
  3543. /* Pointer to memory pool named */
  3544. CHAR *name_ptr = NULL;
  3545. /* Pointer to start address of the memory pool storage data */
  3546. VOID * pool_start = NULL;
  3547. /* The memory pool data size */
  3548. UINT pool_size = 0U;
  3549. /* The memory pool control block size */
  3550. ULONG cb_size = 0U;
  3551. /* Check if this API is called from Interrupt Service Routines or the block_count
  3552. is equal to 0 or block_size is equal to 0 */
  3553. if ((!IS_IRQ_MODE() && (block_size != 0) && (block_count != 0)))
  3554. {
  3555. /* Initialize the name_ptr to NULL */
  3556. name_ptr = NULL;
  3557. if (attr != NULL)
  3558. {
  3559. /* Check if the name_ptr is not NULL */
  3560. if (attr->name != NULL)
  3561. {
  3562. /* Set the message queue name_ptr */
  3563. name_ptr = (CHAR *)attr->name;
  3564. }
  3565. /* Check if the memory pool data storage size is equal to 0 */
  3566. if (attr->mp_size == 0U)
  3567. {
  3568. /* Set memory pool data size to block_count * block_size (The total amount of memory required
  3569. for the memory pool data storage) */
  3570. pool_size = block_count * block_size;
  3571. }
  3572. else if (attr->mp_size < (pool_size))
  3573. {
  3574. /* Return NULL pointer in case of error */
  3575. return (NULL);
  3576. }
  3577. else if (attr->mp_size < TX_BYTE_POOL_MIN)
  3578. {
  3579. /* Set memory pool data size to TX_BYTE_POOL_MIN */
  3580. pool_size = TX_BYTE_POOL_MIN;
  3581. }
  3582. else
  3583. {
  3584. /* Set memory pool data size to attr->mp_size */
  3585. pool_size = (ULONG)attr->mp_size;
  3586. }
  3587. /* Check if the input memory pool data pointer is NULL */
  3588. if (attr->mp_mem == NULL)
  3589. {
  3590. /* Allocate the data for the memory pool to be created */
  3591. pool_start = MemAlloc(pool_size, RTOS2_BYTE_POOL_STACK_TYPE);
  3592. if (pool_start == NULL)
  3593. {
  3594. /* Return NULL pointer in case of error */
  3595. return (NULL);
  3596. }
  3597. }
  3598. else
  3599. {
  3600. if (attr->mp_size == 0U)
  3601. {
  3602. /* Return NULL pointer in case of error */
  3603. return (NULL);
  3604. }
  3605. else
  3606. {
  3607. /* Set memory pool data size to attr->mp_size */
  3608. pool_size = (ULONG)attr->mp_size;
  3609. }
  3610. /* The memory pool shall point to the memory pool data memory address */
  3611. pool_start = attr->mp_mem;
  3612. }
  3613. /* Check if the control block size is equal to 0 */
  3614. if (attr->cb_size == 0U)
  3615. {
  3616. /* Set control block size to sizeof(TX_BLOCK_POOL) */
  3617. cb_size = sizeof(TX_BLOCK_POOL);
  3618. }
  3619. else if (attr->cb_size < sizeof(TX_BLOCK_POOL))
  3620. {
  3621. /* Return NULL pointer in case of error */
  3622. return (NULL);
  3623. }
  3624. else
  3625. {
  3626. /* Set memory pool data size to attr->cb_size */
  3627. cb_size = (ULONG)attr->cb_size;
  3628. }
  3629. /* Check if the input control block pointer is NULL */
  3630. if (attr->cb_mem == NULL)
  3631. {
  3632. /* Allocate the block_pool_ptr structure for the memory pool to be created */
  3633. block_pool_ptr = (TX_BLOCK_POOL *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE);
  3634. if (block_pool_ptr == NULL)
  3635. {
  3636. /* Check if the memory for memory pool data has been internally allocated */
  3637. if (attr->mp_mem == NULL)
  3638. {
  3639. /* Free the already allocated memory for memory pool data */
  3640. MemFree(pool_start);
  3641. }
  3642. /* Return NULL pointer in case of error */
  3643. return (NULL);
  3644. }
  3645. }
  3646. else
  3647. {
  3648. /* The control block shall point to the input cb_mem memory address */
  3649. block_pool_ptr = attr->cb_mem;
  3650. }
  3651. }
  3652. else /* attr == NULL*/
  3653. {
  3654. /* Initialize the name_ptr to NULL */
  3655. name_ptr = NULL;
  3656. /* Initialize the memory pool data size to block_count * block_size (The total amount of memory required
  3657. for the memory pool data storage) */
  3658. pool_size = block_count * block_size;
  3659. /* Allocate the data for pool_start to be created */
  3660. pool_start = MemAlloc(pool_size, RTOS2_BYTE_POOL_STACK_TYPE);
  3661. if (pool_start == NULL)
  3662. {
  3663. /* Return NULL pointer in case of error */
  3664. return (NULL);
  3665. }
  3666. /* Allocate the block_pool_ptr structure for the block pool to be created */
  3667. block_pool_ptr = (TX_BLOCK_POOL *)MemAlloc(sizeof(TX_BLOCK_POOL), RTOS2_BYTE_POOL_HEAP_TYPE);
  3668. if (block_pool_ptr == NULL)
  3669. {
  3670. /* Free the already allocated memory for block pool data */
  3671. MemFree(pool_start);
  3672. /* Return NULL pointer in case of error */
  3673. return (NULL);
  3674. }
  3675. }
  3676. /* Call the tx_block_pool_create function to create the new memory pool */
  3677. if (tx_block_pool_create(block_pool_ptr, name_ptr, block_size, pool_start, pool_size) != TX_SUCCESS)
  3678. {
  3679. /* Check if the memory for memory pool control block has been internally
  3680. allocated */
  3681. if ((attr->cb_mem == NULL) || (attr == NULL))
  3682. {
  3683. /* Free the already allocated memory for memory pool control block */
  3684. MemFree(block_pool_ptr);
  3685. }
  3686. /* Check if the memory for memory pool data has been internally allocated */
  3687. if ((attr->mp_mem == NULL) || (attr == NULL))
  3688. {
  3689. /* Free the already allocated memory for memory pool data */
  3690. MemFree(pool_start);
  3691. }
  3692. /* Return NULL pointer in case of error */
  3693. block_pool_ptr = NULL;
  3694. }
  3695. }
  3696. else
  3697. {
  3698. block_pool_ptr = NULL;
  3699. }
  3700. return((osMemoryPoolId_t)(block_pool_ptr));
  3701. }
  3702. /**
  3703. * @brief The function osMemoryPoolGetName returns the pointer to the name
  3704. * string of the memory pool identified by parameter mp_id or NULL in
  3705. * case of an error.
  3706. * Note : This function cannot be called from Interrupt Service
  3707. * Routines.
  3708. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3709. * @retval maximum number of memory blocks in the memory pool object.
  3710. */
  3711. const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
  3712. {
  3713. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3714. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3715. /* The output name_ptr as null-terminated string */
  3716. CHAR *name_ptr = NULL;
  3717. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3718. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3719. if (IS_IRQ_MODE() || (block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3720. {
  3721. /* Return NULL in case of an error */
  3722. name_ptr = NULL;
  3723. }
  3724. else
  3725. {
  3726. /* Call the tx_block_pool_info_get to get the block_pool name_ptr */
  3727. if (tx_block_pool_info_get(block_pool_ptr, &name_ptr, TX_NULL,TX_NULL, TX_NULL,TX_NULL, TX_NULL)!= TX_SUCCESS)
  3728. {
  3729. /* Return NULL in case of an error */
  3730. name_ptr = NULL;
  3731. }
  3732. }
  3733. return (name_ptr);
  3734. }
  3735. /**
  3736. * @brief The blocking function osMemoryPoolAlloc allocates the memory pool
  3737. * parameter mp_id and returns a pointer to the address of the allocated
  3738. * memory or 0 in case of an error.
  3739. * The parameter timeout specifies how long the system waits to allocate
  3740. * the memory. While the system waits, the thread that is calling this
  3741. * function is put into the BLOCKED state. The thread will become READY
  3742. * as soon as at least one block of memory gets available.
  3743. * The parameter timeout can have the following values:
  3744. * - when timeout is 0, the function returns instantly (i.e. try semantics).
  3745. * - when timeout is set to osWaitForever the function will wait for an
  3746. * infinite time until the memory is allocated (i.e. wait semantics).
  3747. * - All other values specify a time in kernel ticks for a timeout
  3748. * (i.e. timed-wait semantics).
  3749. * Note :
  3750. * - This function may be called from Interrupt Service Routines.
  3751. * - It is in the responsibility of the user to respect the block size,
  3752. * i.e. not access memory beyond the blocks limit.
  3753. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3754. * @param [in] timeout Timeout Value or 0 in case of no time-out.
  3755. * @retval address of the allocated memory block or NULL in case of no memory
  3756. * is available.
  3757. */
  3758. void * osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
  3759. {
  3760. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3761. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3762. /* The output name_ptr as null-terminated string */
  3763. void *block;
  3764. /* Check if the mq_id is NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3765. if((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3766. {
  3767. /* Return NULL in case of an error */
  3768. block = NULL;
  3769. }
  3770. else
  3771. {
  3772. block = NULL;
  3773. /* Get a block from the free-list */
  3774. if(tx_block_allocate(block_pool_ptr, &block, timeout) != TX_SUCCESS)
  3775. {
  3776. /* Return NULL in case of an error */
  3777. block = NULL;
  3778. }
  3779. }
  3780. return (block);
  3781. }
  3782. /**
  3783. * @brief The function osMemoryPoolFree frees the memory pool block specified
  3784. * by the parameter block in the memory pool object specified by the
  3785. * parameter mp_id. The memory block is put back to the list of
  3786. * available blocks
  3787. * If another thread is waiting for memory to become available the
  3788. * thread is put to READY state.
  3789. * Possible osStatus_t return values:
  3790. * - osOK: the memory has been freed.
  3791. * - oosErrorParameter: parameter mp_id is NULL or invalid, block
  3792. * points to invalid memory.
  3793. * - oosErrorResource: the memory pool is in an invalid state.
  3794. * Note : osMemoryPoolFree may perform certain checks on the block
  3795. * pointer given. But using osMemoryPoolFree with a pointer other
  3796. * than one received from osMemoryPoolAlloc has UNPREDICTED behaviour.
  3797. * This function may be called from Interrupt Service Routines.
  3798. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3799. * [in] [in] block address of the allocated memory block to be
  3800. * returned to the memory pool
  3801. * @retval status code that indicates the execution status of the function.
  3802. */
  3803. osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void * block)
  3804. {
  3805. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3806. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3807. osStatus_t status;
  3808. /* Check if the mq_id is NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3809. if((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID) || (block == NULL))
  3810. {
  3811. /* Invalid input parameters */
  3812. status = osErrorParameter;
  3813. }
  3814. else
  3815. {
  3816. if(tx_block_release((VOID *)block) != TX_SUCCESS)
  3817. {
  3818. status = osErrorResource;
  3819. }
  3820. else
  3821. {
  3822. status = osOK;
  3823. }
  3824. }
  3825. return (status);
  3826. }
  3827. /**
  3828. * @brief The function osMemoryPoolGetCapacity returns the maximum number
  3829. * of memory blocks in the memory pool object specified by
  3830. * parameter mp_id or 0 in case of an error.
  3831. * Note : This function may be called from Interrupt Service
  3832. * Routines.
  3833. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3834. * @retval maximum number of memory blocks in the memory pool object.
  3835. */
  3836. uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
  3837. {
  3838. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3839. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3840. /* The output name_ptr as null-terminated string */
  3841. ULONG total_blocks = 0;
  3842. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3843. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3844. if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3845. {
  3846. /* Return 0 in case of an error */
  3847. total_blocks = 0;
  3848. }
  3849. else
  3850. {
  3851. /* Call the tx_block_pool_info_get to get the total_blocks */
  3852. if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, TX_NULL, &total_blocks, TX_NULL,TX_NULL, TX_NULL)!= TX_SUCCESS)
  3853. {
  3854. /* Return 0 in case of an error */
  3855. total_blocks = 0;
  3856. }
  3857. }
  3858. return (total_blocks);
  3859. }
  3860. /**
  3861. * @brief The function osMemoryPoolGetBlockSize returns the memory block size
  3862. * in bytes in the memory pool object specified by parameter mp_id
  3863. * or 0 in case of an error.
  3864. * Note : This function may be called from Interrupt Service
  3865. * Routines.
  3866. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3867. * @retval memory block size in bytes.
  3868. */
  3869. uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
  3870. {
  3871. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3872. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3873. /* The output name_ptr as null-terminated string */
  3874. uint32_t block_pool_size = 0;
  3875. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3876. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3877. if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3878. {
  3879. /* Return 0 in case of an error */
  3880. block_pool_size = 0;
  3881. }
  3882. else
  3883. {
  3884. block_pool_size = block_pool_ptr->tx_block_pool_block_size;
  3885. }
  3886. return (block_pool_size);
  3887. }
  3888. /**
  3889. * @brief The function osMemoryPoolGetCount returns the number of memory blocks
  3890. * used in the memory pool object specified by parameter mp_id or 0 in
  3891. * case of an error.
  3892. * Note : This function may be called from Interrupt Service
  3893. * Routines.
  3894. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3895. * @retval number of memory blocks used.
  3896. */
  3897. uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
  3898. {
  3899. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3900. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3901. /* The output name_ptr as null-terminated string */
  3902. ULONG block_pool_total = 0;
  3903. ULONG block_pool_available = 0;
  3904. ULONG block_pool_used = 0;
  3905. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3906. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3907. if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3908. {
  3909. /* Return 0 in case of an error */
  3910. block_pool_used = 0;
  3911. }
  3912. else
  3913. {
  3914. /* Call the tx_block_pool_info_get to get the block_pool name_ptr */
  3915. if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, &block_pool_available, &block_pool_total, TX_NULL, TX_NULL, TX_NULL)!= TX_SUCCESS)
  3916. {
  3917. /* Return 0 in case of an error */
  3918. block_pool_used = 0;
  3919. }
  3920. else
  3921. {
  3922. /* Return number of used blocks */
  3923. block_pool_used = (block_pool_total - block_pool_available);
  3924. }
  3925. }
  3926. return ((uint32_t)(block_pool_used));
  3927. }
  3928. /**
  3929. * @brief The function osMemoryPoolGetSpace returns the number of memory blocks
  3930. * available in the memory pool object specified by parameter mp_id
  3931. * or 0 in case of an error.
  3932. * Note : This function may be called from Interrupt Service
  3933. * Routines.
  3934. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3935. * @retval number of memory blocks available.
  3936. */
  3937. uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
  3938. {
  3939. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3940. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3941. /* The output name_ptr as null-terminated string */
  3942. ULONG block_pool_available = 0;
  3943. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3944. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3945. if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3946. {
  3947. /* Return 0 in case of an error */
  3948. block_pool_available = 0;
  3949. }
  3950. else
  3951. {
  3952. /* Call the tx_block_pool_info_get to get the block_pool name_ptr */
  3953. if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, &block_pool_available, TX_NULL, TX_NULL, TX_NULL, TX_NULL)!= TX_SUCCESS)
  3954. {
  3955. /* Return 0 in case of an error */
  3956. block_pool_available = 0;
  3957. }
  3958. }
  3959. return (block_pool_available);
  3960. }
  3961. /**
  3962. * @brief The function osMemoryPoolDelete deletes a memory pool object
  3963. * specified by parameter mp_id. It releases internal memory obtained
  3964. * for memory pool handling. After this call, the mp_id is no longer
  3965. * valid and cannot be used. The memory pool may be created again using
  3966. * the function osMemoryPoolNew
  3967. * Possible osStatus_t return values:
  3968. * - osOK: the memory pool object has been deleted.
  3969. * - osErrorParameter: parameter mp_id is NULL or invalid.
  3970. * - osErrorResource: the memory pool is in an invalid state.
  3971. * - osErrorISR: osMemoryPoolDelete cannot be called from interrupt service routines.
  3972. * Note : This function cannot be called from Interrupt Service Routines.
  3973. * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew.
  3974. * @retval status code that indicates the execution status of the function.
  3975. */
  3976. osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
  3977. {
  3978. /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */
  3979. TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id;
  3980. osStatus_t status;
  3981. /* Check if this API is called from Interrupt Service Routines, the mq_id is
  3982. NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */
  3983. if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID))
  3984. {
  3985. status = osErrorParameter;
  3986. }
  3987. else if(IS_IRQ_MODE())
  3988. {
  3989. status = osErrorISR;
  3990. }
  3991. else
  3992. {
  3993. if(tx_block_pool_delete(block_pool_ptr) != TX_SUCCESS)
  3994. {
  3995. status = osErrorResource;
  3996. }
  3997. else
  3998. {
  3999. status = osOK;
  4000. }
  4001. }
  4002. return(status);
  4003. }
  4004. /*---------------------------------------------------------------------------*/
  4005. /*------------------------tx_application_define API--------------------------*/
  4006. /*---------------------------------------------------------------------------*/
  4007. __attribute__((weak)) VOID tx_application_define(VOID *first_unused_memory)
  4008. {
  4009. /* Empty tx_application_define() */
  4010. }