cmsis_os2.c 156 KB

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