ch.hpp 100 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @file ch.hpp
  15. * @brief C++ wrapper classes and definitions.
  16. *
  17. * @addtogroup cpp_library
  18. * @{
  19. */
  20. #include <ch.h>
  21. #ifndef _CH_HPP_
  22. #define _CH_HPP_
  23. /**
  24. * @brief ChibiOS-RT kernel-related classes and interfaces.
  25. */
  26. namespace chibios_rt {
  27. /* Forward declaration of some classes.*/
  28. class ThreadReference;
  29. /*------------------------------------------------------------------------*
  30. * chibios_rt::System *
  31. *------------------------------------------------------------------------*/
  32. /**
  33. * @brief Class encapsulating the base system functionalities.
  34. */
  35. class System {
  36. public:
  37. /**
  38. * @brief ChibiOS/RT initialization.
  39. * @details After executing this function the current instructions stream
  40. * becomes the main thread.
  41. * @pre Interrupts must be still disabled when @p chSysInit() is invoked
  42. * and are internally enabled.
  43. * @post The main thread is created with priority @p NORMALPRIO.
  44. * @note This function has special, architecture-dependent, requirements,
  45. * see the notes into the various port reference manuals.
  46. *
  47. * @special
  48. */
  49. static void init(void) {
  50. chSysInit();
  51. }
  52. /**
  53. * @brief Halts the system.
  54. * @details This function is invoked by the operating system when an
  55. * unrecoverable error is detected, for example because a programming
  56. * error in the application code that triggers an assertion while
  57. * in debug mode.
  58. * @note Can be invoked from any system state.
  59. *
  60. * @param[in] reason pointer to an error string
  61. *
  62. * @special
  63. */
  64. static void halt(const char *reason) {
  65. chSysHalt(reason);
  66. }
  67. /**
  68. * @brief System integrity check.
  69. * @details Performs an integrity check of the important ChibiOS/RT data
  70. * structures.
  71. * @note The appropriate action in case of failure is to halt the system
  72. * before releasing the critical zone.
  73. * @note If the system is corrupted then one possible outcome of this
  74. * function is an exception caused by @p nullptr or corrupted
  75. * pointers in list elements. Exception vectors must be monitored
  76. * as well.
  77. * @note This function is not used internally, it is up to the
  78. * application to define if and where to perform system
  79. * checking.
  80. * @note Performing all tests at once can be a slow operation and can
  81. * degrade the system response time. It is suggested to execute
  82. * one test at time and release the critical zone in between tests.
  83. *
  84. * @param[in] testmask Each bit in this mask is associated to a test to be
  85. * performed.
  86. * @return The test result.
  87. * @retval false The test succeeded.
  88. * @retval true Test failed.
  89. *
  90. * @iclass
  91. */
  92. static bool integrityCheckI(unsigned int testmask) {
  93. return chSysIntegrityCheckI(testmask);
  94. }
  95. /**
  96. * @brief Raises the system interrupt priority mask to the maximum level.
  97. * @details All the maskable interrupt sources are disabled regardless their
  98. * hardware priority.
  99. * @note Do not invoke this API from within a kernel lock.
  100. *
  101. * @special
  102. */
  103. static void disable(void) {
  104. chSysDisable();
  105. }
  106. /**
  107. * @brief Raises the system interrupt priority mask to system level.
  108. * @details The interrupt sources that should not be able to preempt the kernel
  109. * are disabled, interrupt sources with higher priority are still
  110. * enabled.
  111. * @note Do not invoke this API from within a kernel lock.
  112. * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
  113. * could do more than just disable the interrupts.
  114. *
  115. * @special
  116. */
  117. static void suspend(void) {
  118. chSysSuspend();
  119. }
  120. /**
  121. * @brief Lowers the system interrupt priority mask to user level.
  122. * @details All the interrupt sources are enabled.
  123. * @note Do not invoke this API from within a kernel lock.
  124. * @note This API is no replacement for @p chSysUnlock(), the
  125. * @p chSysUnlock() could do more than just enable the interrupts.
  126. *
  127. * @special
  128. */
  129. static void enable(void) {
  130. chSysEnable();
  131. }
  132. /**
  133. * @brief Enters the kernel lock mode.
  134. *
  135. * @special
  136. */
  137. static void lock(void) {
  138. chSysLock();
  139. }
  140. /**
  141. * @brief Leaves the kernel lock mode.
  142. *
  143. * @special
  144. */
  145. static void unlock(void) {
  146. chSysUnlock();
  147. }
  148. /**
  149. * @brief Enters the kernel lock mode from within an interrupt handler.
  150. * @note This API may do nothing on some architectures, it is required
  151. * because on ports that support preemptable interrupt handlers
  152. * it is required to raise the interrupt mask to the same level of
  153. * the system mutual exclusion zone.<br>
  154. * It is good practice to invoke this API before invoking any I-class
  155. * syscall from an interrupt handler.
  156. * @note This API must be invoked exclusively from interrupt handlers.
  157. *
  158. * @special
  159. */
  160. static void lockFromIsr(void) {
  161. chSysLockFromISR();
  162. }
  163. /**
  164. * @brief Leaves the kernel lock mode from within an interrupt handler.
  165. *
  166. * @note This API may do nothing on some architectures, it is required
  167. * because on ports that support preemptable interrupt handlers
  168. * it is required to raise the interrupt mask to the same level of
  169. * the system mutual exclusion zone.<br>
  170. * It is good practice to invoke this API after invoking any I-class
  171. * syscall from an interrupt handler.
  172. * @note This API must be invoked exclusively from interrupt handlers.
  173. *
  174. * @special
  175. */
  176. static void unlockFromIsr(void) {
  177. chSysUnlockFromISR();
  178. }
  179. /**
  180. * @brief Unconditionally enters the kernel lock state.
  181. * @note Can be called without previous knowledge of the current lock state.
  182. * The final state is "s-locked".
  183. *
  184. * @special
  185. */
  186. static void unconditionalLock(void) {
  187. chSysUnconditionalLock();
  188. }
  189. /**
  190. * @brief Unconditionally leaves the kernel lock state.
  191. * @note Can be called without previous knowledge of the current lock state.
  192. * The final state is "normal".
  193. *
  194. * @special
  195. */
  196. static void unconditionalUnlock(void) {
  197. chSysUnconditionalUnlock();
  198. }
  199. /**
  200. * @brief Returns the execution status and enters a critical zone.
  201. * @details This functions enters into a critical zone and can be called
  202. * from any context. Because its flexibility it is less efficient
  203. * than @p chSysLock() which is preferable when the calling context
  204. * is known.
  205. * @post The system is in a critical zone.
  206. *
  207. * @return The previous system status, the encoding of this
  208. * status word is architecture-dependent and opaque.
  209. *
  210. * @xclass
  211. */
  212. static syssts_t getStatusAndLockX(void) {
  213. return chSysGetStatusAndLockX();
  214. }
  215. /**
  216. * @brief Restores the specified execution status and leaves a critical zone.
  217. * @note A call to @p chSchRescheduleS() is automatically performed
  218. * if exiting the critical zone and if not in ISR context.
  219. *
  220. * @param[in] sts the system status to be restored.
  221. *
  222. * @xclass
  223. */
  224. static void restoreStatusX(syssts_t sts) {
  225. chSysRestoreStatusX(sts);
  226. }
  227. #if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
  228. /**
  229. * @brief Returns the current value of the system real time counter.
  230. * @note This function is only available if the port layer supports the
  231. * option @p PORT_SUPPORTS_RT.
  232. *
  233. * @return The value of the system realtime counter of
  234. * type rtcnt_t.
  235. *
  236. * @xclass
  237. */
  238. static rtcnt_t getRealtimeCounterX(void) {
  239. return chSysGetRealtimeCounterX();
  240. }
  241. /**
  242. * @brief Realtime window test.
  243. * @details This function verifies if the current realtime counter value
  244. * lies within the specified range or not. The test takes care
  245. * of the realtime counter wrapping to zero on overflow.
  246. * @note When start==end then the function returns always true because the
  247. * whole time range is specified.
  248. * @note This function is only available if the port layer supports the
  249. * option @p PORT_SUPPORTS_RT.
  250. *
  251. * @param[in] cnt the counter value to be tested
  252. * @param[in] start the start of the time window (inclusive)
  253. * @param[in] end the end of the time window (non inclusive)
  254. * @retval true current time within the specified time window.
  255. * @retval false current time not within the specified time window.
  256. *
  257. * @xclass
  258. */
  259. static bool isCounterWithinX(rtcnt_t cnt,
  260. rtcnt_t start,
  261. rtcnt_t end) {
  262. return chSysIsCounterWithinX(cnt, start, end);
  263. }
  264. /**
  265. * @brief Polled delay.
  266. * @note The real delay is always few cycles in excess of the specified
  267. * value.
  268. * @note This function is only available if the port layer supports the
  269. * option @p PORT_SUPPORTS_RT.
  270. *
  271. * @param[in] cycles number of cycles
  272. *
  273. * @xclass
  274. */
  275. static void polledDelayX(rtcnt_t cycles) {
  276. chSysPolledDelayX(cycles);
  277. }
  278. #endif /* PORT_SUPPORTS_RT == TRUE */
  279. /**
  280. * @brief Returns the system time as system ticks.
  281. * @note The system tick time interval is implementation dependent.
  282. *
  283. * @return The system time.
  284. *
  285. * @api
  286. */
  287. static systime_t getTime(void) {
  288. return chVTGetSystemTime();
  289. }
  290. /**
  291. * @brief Returns the system time as system ticks.
  292. * @note The system tick time interval is implementation dependent.
  293. *
  294. * @return The system time.
  295. *
  296. * @xclass
  297. */
  298. static systime_t getTimeX(void) {
  299. return chVTGetSystemTimeX();
  300. }
  301. /**
  302. * @brief Checks if the current system time is within the specified time
  303. * window.
  304. * @note When start==end then the function returns always true because the
  305. * whole time range is specified.
  306. *
  307. * @param[in] start the start of the time window (inclusive)
  308. * @param[in] end the end of the time window (non inclusive)
  309. * @retval true current time within the specified time window.
  310. * @retval false current time not within the specified time window.
  311. *
  312. * @api
  313. */
  314. static bool isSystemTimeWithin(systime_t start, systime_t end) {
  315. return chVTIsSystemTimeWithin(start, end);
  316. }
  317. #if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
  318. /**
  319. * @brief Returns a reference to the idle thread.
  320. * @pre In order to use this function the option @p CH_CFG_NO_IDLE_THREAD
  321. * must be disabled.
  322. * @note The reference counter of the idle thread is not incremented but
  323. * it is not strictly required being the idle thread a static
  324. * object.
  325. *
  326. * @return Reference to the idle thread.
  327. *
  328. * @xclass
  329. */
  330. static ThreadReference getIdleThreadX(void);
  331. #endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
  332. };
  333. /*------------------------------------------------------------------------*
  334. * chibios_rt::CriticalSectionLocker *
  335. *------------------------------------------------------------------------*/
  336. /**
  337. * @brief RAII helper for reentrant critical sections.
  338. */
  339. class CriticalSectionLocker {
  340. volatile const syssts_t syssts = chSysGetStatusAndLockX();
  341. public:
  342. ~CriticalSectionLocker() {
  343. chSysRestoreStatusX(syssts);
  344. }
  345. };
  346. /*------------------------------------------------------------------------*
  347. * chibios_rt::Scheduler *
  348. *------------------------------------------------------------------------*/
  349. /**
  350. * @brief Class encapsulating the low level scheduler functionalities.
  351. */
  352. class Scheduler {
  353. public:
  354. /**
  355. * @brief Performs a reschedule if a higher priority thread is runnable.
  356. * @details If a thread with a higher priority than the current thread is in
  357. * the ready list then make the higher priority thread running.
  358. *
  359. * @sclass
  360. */
  361. static void rescheduleS(void) {
  362. void chSchRescheduleS();
  363. }
  364. };
  365. #if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
  366. /*------------------------------------------------------------------------*
  367. * chibios_rt::Core *
  368. *------------------------------------------------------------------------*/
  369. /**
  370. * @brief Class encapsulating the base system functionalities.
  371. */
  372. class Core {
  373. public:
  374. /**
  375. * @brief Allocates a memory block.
  376. * @details The size of the returned block is aligned to the alignment
  377. * type so it is not possible to allocate less
  378. * than <code>MEM_ALIGN_SIZE</code>.
  379. *
  380. * @param[in] size the size of the block to be allocated
  381. * @return A pointer to the allocated memory block.
  382. * @retval nullptr allocation failed, core memory exhausted.
  383. *
  384. * @api
  385. */
  386. static void *alloc(size_t size) {
  387. return chCoreAlloc(size);
  388. }
  389. /**
  390. * @brief Allocates a memory block.
  391. * @details The size of the returned block is aligned to the alignment
  392. * type so it is not possible to allocate less than
  393. * <code>MEM_ALIGN_SIZE</code>.
  394. *
  395. * @param[in] size the size of the block to be allocated.
  396. * @return A pointer to the allocated memory block.
  397. * @retval nullptr allocation failed, core memory exhausted.
  398. *
  399. * @iclass
  400. */
  401. static void *allocI(size_t size) {
  402. return chCoreAllocI(size);
  403. }
  404. /**
  405. * @brief Core memory status.
  406. *
  407. * @return The size, in bytes, of the free core memory.
  408. *
  409. * @xclass
  410. */
  411. static size_t getStatusX(void) {
  412. return chCoreGetStatusX();
  413. }
  414. };
  415. #endif /* CH_CFG_USE_MEMCORE == TRUE */
  416. /*------------------------------------------------------------------------*
  417. * chibios_rt::Timer *
  418. *------------------------------------------------------------------------*/
  419. /**
  420. * @brief Timer class.
  421. */
  422. class Timer {
  423. /**
  424. * @brief Embedded @p virtual_timer_t structure.
  425. */
  426. virtual_timer_t vt;
  427. public:
  428. /**
  429. * @brief Construct a virtual timer.
  430. */
  431. Timer() : vt() {
  432. chVTObjectInit(&vt);
  433. }
  434. /* Prohibit copy construction and assignment.*/
  435. Timer(const Timer &) = delete;
  436. Timer &operator=(const Timer &) = delete;
  437. /**
  438. * @brief Enables a virtual timer.
  439. * @note The associated function is invoked from interrupt context.
  440. *
  441. * @param[in] timeout the number of ticks before the operation timeouts,
  442. * the special values are handled as follow:
  443. * - @a TIME_INFINITE is allowed but interpreted as a
  444. * normal time specification.
  445. * - @a TIME_IMMEDIATE this value is not allowed.
  446. * .
  447. * @param[in] vtfunc the timer callback function. After invoking the
  448. * callback the timer is disabled and the structure
  449. * can be disposed or reused.
  450. * @param[in] par a parameter that will be passed to the callback
  451. * function
  452. *
  453. * @api
  454. */
  455. void set(sysinterval_t timeout, vtfunc_t vtfunc, void *par) {
  456. chVTSet(&vt, timeout, vtfunc, par);
  457. }
  458. /**
  459. * @brief Enables a virtual timer.
  460. * @note The associated function is invoked from interrupt context.
  461. *
  462. * @param[in] timeout the number of ticks before the operation timeouts,
  463. * the special values are handled as follow:
  464. * - @a TIME_INFINITE is allowed but interpreted as a
  465. * normal time specification.
  466. * - @a TIME_IMMEDIATE this value is not allowed.
  467. * .
  468. * @param[in] vtfunc the timer callback function. After invoking the
  469. * callback the timer is disabled and the structure
  470. * can be disposed or reused.
  471. * @param[in] par a parameter that will be passed to the callback
  472. * function
  473. *
  474. * @iclass
  475. */
  476. void setI(sysinterval_t timeout, vtfunc_t vtfunc, void *par) {
  477. chVTSetI(&vt, timeout, vtfunc, par);
  478. }
  479. /**
  480. * @brief Resets the timer, if armed.
  481. *
  482. * @api
  483. */
  484. void reset() {
  485. chVTReset(&vt);
  486. }
  487. /**
  488. * @brief Resets the timer, if armed.
  489. *
  490. * @iclass
  491. */
  492. void resetI() {
  493. chVTResetI(&vt);
  494. }
  495. /**
  496. * @brief Returns the timer status.
  497. *
  498. * @return The timer status.
  499. * @retval true If the timer is armed.
  500. * @retval false If the timer already fired its callback.
  501. *
  502. * @iclass
  503. */
  504. bool isArmedI(void) const {
  505. return chVTIsArmedI(&vt);
  506. }
  507. };
  508. /*------------------------------------------------------------------------*
  509. * chibios_rt::ThreadReference *
  510. *------------------------------------------------------------------------*/
  511. /**
  512. * @brief Thread reference class.
  513. * @details This class encapsulates a reference to a system thread. All
  514. * operations involving another thread are performed through
  515. * an object of this type.
  516. */
  517. class ThreadReference final {
  518. /**
  519. * @brief Pointer to the system thread.
  520. */
  521. thread_t *thread_ref;
  522. public:
  523. /**
  524. * @brief Thread reference constructor.
  525. * @note Do not call this version directly, this constructor is empty
  526. * and is here only to do nothing when an object of this kind
  527. * is declared then assigned.
  528. * @note Automatic instances of this object are not initialized
  529. * because this constructor, this is intentional.
  530. *
  531. * @param[in] tp the target thread
  532. *
  533. * @init
  534. */
  535. ThreadReference(void) {
  536. }
  537. /**
  538. * @brief Thread reference constructor.
  539. *
  540. * @param[in] tp the target thread
  541. *
  542. * @init
  543. */
  544. ThreadReference(thread_t *tp) : thread_ref(tp) {
  545. }
  546. /**
  547. * @brief Returns the reference state.
  548. *
  549. * @return The reference state.
  550. * @retval false if the reference is still valid.
  551. * @retval true if the reference is set to @p nullptr.
  552. */
  553. bool isNull(void) const {
  554. return (bool)(thread_ref == nullptr);
  555. }
  556. /**
  557. * @brief Returns the low level pointer to the referenced thread.
  558. */
  559. thread_t *getInner(void) {
  560. return thread_ref;
  561. }
  562. /**
  563. * @brief Requests a thread termination.
  564. * @pre The target thread must be written to invoke periodically
  565. * @p chThdShouldTerminate() and terminate cleanly if it returns
  566. * @p TRUE.
  567. * @post The specified thread will terminate after detecting the
  568. * termination condition.
  569. *
  570. * @api
  571. */
  572. void requestTerminate(void) const {
  573. chThdTerminate(thread_ref);
  574. }
  575. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  576. /**
  577. * @brief Adds a reference to a thread object.
  578. * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled
  579. * in order to use this function.
  580. *
  581. * @return A new thread reference.
  582. *
  583. * @api
  584. */
  585. ThreadReference addRef(void) const {
  586. return ThreadReference(chThdAddRef(thread_ref));
  587. }
  588. /**
  589. * @brief Releases a reference to a thread object.
  590. * @details If the references counter reaches zero <b>and</b> the thread
  591. * is in the @p CH_STATE_FINAL state then the thread's memory is
  592. * returned to the proper allocator and the thread is removed
  593. * from the registry.<br>
  594. * Threads whose counter reaches zero and are still active become
  595. * "detached" and will be removed from registry on termination.
  596. * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
  597. * order to use this function.
  598. * @post The reference is set to @p nullptr.
  599. * @note Static threads are not affected.
  600. *
  601. * @api
  602. */
  603. void release(void) {
  604. thread_t *tp = thread_ref;
  605. thread_ref = nullptr;
  606. chThdRelease(tp);
  607. }
  608. #endif /* CH_CFG_USE_REGISTRY == TRUE */
  609. #if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
  610. /**
  611. * @brief Blocks the execution of the invoking thread until the specified
  612. * thread terminates then the exit code is returned.
  613. * @details This function waits for the specified thread to terminate then
  614. * decrements its reference counter, if the counter reaches zero
  615. * then the thread working area is returned to the proper
  616. * allocator.<br>
  617. * The memory used by the exited thread is handled in different
  618. * ways depending on the API that spawned the thread:
  619. * - If the thread was spawned by @p chThdCreateStatic() or by
  620. * @p chThdCreateI() then nothing happens and the thread working
  621. * area is not released or modified in any way. This is the
  622. * default, totally static, behavior.
  623. * - If the thread was spawned by @p chThdCreateFromHeap() then
  624. * the working area is returned to the system heap.
  625. * - If the thread was spawned by @p chThdCreateFromMemoryPool()
  626. * then the working area is returned to the owning memory pool.
  627. * .
  628. * @pre The configuration option @p CH_USE_WAITEXIT must be enabled in
  629. * order to use this function.
  630. * @post Enabling @p chThdWait() requires 2-4 (depending on the
  631. * architecture) extra bytes in the @p Thread structure.
  632. * @post The reference is set to @p nullptr.
  633. * @note If @p CH_USE_DYNAMIC is not specified this function just waits
  634. * for the thread termination, no memory allocators are involved.
  635. *
  636. * @return The exit code from the terminated thread.
  637. *
  638. * @api
  639. */
  640. msg_t wait(void) {
  641. thread_t *tp = thread_ref;
  642. thread_ref = nullptr;
  643. msg_t msg = chThdWait(tp);
  644. return msg;
  645. }
  646. #endif /* CH_CFG_USE_WAITEXIT == TRUE */
  647. #if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
  648. /**
  649. * @brief Sends a message to the thread and returns the answer.
  650. *
  651. * @param[in] msg the sent message
  652. * @return The returned message.
  653. *
  654. * @api
  655. */
  656. msg_t sendMessage(msg_t msg) const {
  657. return chMsgSend(thread_ref, msg);
  658. }
  659. /**
  660. * @brief Returns true if there is at least one message in queue.
  661. *
  662. * @retval true A message is waiting in queue.
  663. * @retval false A message is not waiting in queue.
  664. *
  665. * @api
  666. */
  667. bool isPendingMessage(void) const {
  668. return chMsgIsPendingI(thread_ref);
  669. }
  670. /**
  671. * @brief Returns an enqueued message or @p nullptr.
  672. *
  673. * @return The incoming message.
  674. *
  675. * @api
  676. */
  677. msg_t getMessage(void) const {
  678. return chMsgGet(thread_ref);
  679. }
  680. /**
  681. * @brief Releases the next message in queue with a reply.
  682. * @post The reference is set to @p nullptr.
  683. *
  684. * @param[in] msg the answer message
  685. *
  686. * @api
  687. */
  688. void releaseMessage(msg_t msg) {
  689. thread_t *tp = thread_ref;
  690. thread_ref = nullptr;
  691. chMsgRelease(tp, msg);
  692. }
  693. #endif /* CH_CFG_USE_MESSAGES == TRUE */
  694. #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
  695. /**
  696. * @brief Adds a set of event flags directly to specified @p Thread.
  697. *
  698. * @param[in] mask the event flags set to be ORed
  699. *
  700. * @api
  701. */
  702. void signalEvents(eventmask_t mask) const {
  703. chEvtSignal(thread_ref, mask);
  704. }
  705. /**
  706. * @brief Adds a set of event flags directly to specified @p Thread.
  707. *
  708. * @param[in] mask the event flags set to be ORed
  709. *
  710. * @iclass
  711. */
  712. void signalEventsI(eventmask_t mask) const {
  713. chEvtSignalI(thread_ref, mask);
  714. }
  715. #endif /* CH_CFG_USE_EVENTS == TRUE */
  716. #if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
  717. /**
  718. * @brief Returns the number of ticks consumed by the specified thread.
  719. * @note This function is only available when the
  720. * @p CH_DBG_THREADS_PROFILING configuration option is enabled.
  721. *
  722. * @param[in] tp pointer to the thread
  723. * @return The number of consumed system ticks.
  724. *
  725. * @xclass
  726. */
  727. systime_t getTicksX(void) const {
  728. return chThdGetTicksX(thread_ref);
  729. }
  730. #endif /* CH_DBG_THREADS_PROFILING == TRUE */
  731. };
  732. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  733. /*------------------------------------------------------------------------*
  734. * chibios_rt::Registry *
  735. *------------------------------------------------------------------------*/
  736. class Registry {
  737. public:
  738. /**
  739. * @brief Returns the first thread in the system.
  740. * @details Returns the most ancient thread in the system, usually this is
  741. * the main thread unless it terminated. A reference is added to the
  742. * returned thread in order to make sure its status is not lost.
  743. * @note This function cannot return @p nullptr because there is always at
  744. * least one thread in the system.
  745. *
  746. * @return A reference to the most ancient thread.
  747. *
  748. * @api
  749. */
  750. static ThreadReference firstThread(void) {
  751. return ThreadReference(chRegFirstThread());
  752. }
  753. /**
  754. * @brief Returns the thread next to the specified one.
  755. * @details The reference counter of the specified thread is decremented and
  756. * the reference counter of the returned thread is incremented.
  757. *
  758. * @param[in] tref reference to the thread
  759. * @return A reference to the next thread. The reference is
  760. * set to @p nullptr if there is no next thread.
  761. *
  762. * @api
  763. */
  764. static ThreadReference nextThread(ThreadReference tref) {
  765. return ThreadReference(chRegNextThread(tref.getInner()));
  766. }
  767. /**
  768. * @brief Retrieves a thread reference by name.
  769. * @note The reference counter of the found thread is increased by one so
  770. * it cannot be disposed incidentally after the pointer has been
  771. * returned.
  772. *
  773. * @param[in] name the thread name
  774. * @return A pointer to the found thread.
  775. * @return A reference to the found thread. The reference is
  776. * set to @p nullptr if no next thread is found.
  777. *
  778. * @api
  779. */
  780. static ThreadReference findThreadByName(const char *name) {
  781. return ThreadReference(chRegFindThreadByName(name));
  782. }
  783. };
  784. #endif /* CH_CFG_USE_REGISTRY == TRUE */
  785. /*------------------------------------------------------------------------*
  786. * chibios_rt::BaseThread *
  787. *------------------------------------------------------------------------*/
  788. /**
  789. * @brief Abstract base class for a ChibiOS/RT thread.
  790. * @details The thread body is the virtual function @p Main().
  791. */
  792. class BaseThread {
  793. public:
  794. /**
  795. * @brief BaseThread constructor.
  796. *
  797. * @init
  798. */
  799. BaseThread(void) {
  800. }
  801. /**
  802. * @brief Thread body function.
  803. *
  804. * @return The exit message.
  805. *
  806. * @api
  807. */
  808. virtual void main(void) = 0;
  809. /**
  810. * @brief Creates and starts a system thread.
  811. *
  812. * @param[in] prio thread priority
  813. * @return A reference to the created thread with
  814. * reference counter set to one.
  815. *
  816. * @api
  817. */
  818. virtual ThreadReference start(tprio_t prio) = 0;
  819. /**
  820. * @brief Returns a reference to the current thread.
  821. *
  822. * @return A reference to the current thread.
  823. *
  824. * @xclass
  825. */
  826. static ThreadReference getSelfX(void) {
  827. return ThreadReference(chThdGetSelfX());
  828. }
  829. /**
  830. * @brief Sets the current thread name.
  831. * @pre This function only stores the pointer to the name if the option
  832. * @p CH_USE_REGISTRY is enabled else no action is performed.
  833. *
  834. * @param[in] tname thread name as a zero terminated string
  835. *
  836. * @api
  837. */
  838. static void setName(const char *tname) {
  839. chRegSetThreadName(tname);
  840. }
  841. /**
  842. * @brief Changes the running thread priority level then reschedules if
  843. * necessary.
  844. * @note The function returns the real thread priority regardless of the
  845. * current priority that could be higher than the real priority
  846. * because the priority inheritance mechanism.
  847. *
  848. * @param[in] newprio the new priority level of the running thread
  849. * @return The old priority level.
  850. *
  851. * @api
  852. */
  853. static tprio_t setPriority(tprio_t newprio) {
  854. return chThdSetPriority(newprio);
  855. }
  856. /**
  857. * @brief Returns the current thread priority.
  858. * @note Can be invoked in any context.
  859. *
  860. * @return The current thread priority.
  861. *
  862. * @xclass
  863. */
  864. static tprio_t getPriorityX(void) {
  865. return chThdGetPriorityX();
  866. }
  867. /**
  868. * @brief Terminates the current thread.
  869. * @details The thread goes in the @p THD_STATE_FINAL state holding the
  870. * specified exit status code, other threads can retrieve the
  871. * exit status code by invoking the function @p chThdWait().
  872. * @post Eventual code after this function will never be executed,
  873. * this function never returns. The compiler has no way to
  874. * know this so do not assume that the compiler would remove
  875. * the dead code.
  876. *
  877. * @param[in] msg thread exit code
  878. *
  879. * @api
  880. */
  881. static void exit(msg_t msg) {
  882. chThdExit(msg);
  883. }
  884. /**
  885. * @brief Terminates the current thread.
  886. * @details The thread goes in the @p THD_STATE_FINAL state holding the
  887. * specified exit status code, other threads can retrieve the
  888. * exit status code by invoking the function @p chThdWait().
  889. * @post Eventual code after this function will never be executed,
  890. * this function never returns. The compiler has no way to
  891. * know this so do not assume that the compiler would remove
  892. * the dead code.
  893. *
  894. * @param[in] msg thread exit code
  895. *
  896. * @sclass
  897. */
  898. static void exitS(msg_t msg) {
  899. chThdExitS(msg);
  900. }
  901. /**
  902. * @brief Verifies if the current thread has a termination request
  903. * pending.
  904. * @note Can be invoked in any context.
  905. *
  906. * @retval TRUE termination request pending.
  907. * @retval FALSE termination request not pending.
  908. *
  909. * @special
  910. */
  911. static bool shouldTerminate(void) {
  912. return chThdShouldTerminateX();
  913. }
  914. /**
  915. * @brief Suspends the invoking thread for the specified time.
  916. *
  917. * @param[in] interval the delay in system ticks, the special values are
  918. * handled as follow:
  919. * - @a TIME_INFINITE the thread enters an infinite
  920. * sleep state.
  921. * - @a TIME_IMMEDIATE this value is not allowed.
  922. * .
  923. *
  924. * @api
  925. */
  926. static void sleep(sysinterval_t interval) {
  927. chThdSleep(interval);
  928. }
  929. /**
  930. * @brief Suspends the invoking thread until the system time arrives to
  931. * the specified value.
  932. *
  933. * @param[in] time absolute system time
  934. *
  935. * @api
  936. */
  937. static void sleepUntil(systime_t time) {
  938. chThdSleepUntil(time);
  939. }
  940. /**
  941. * @brief Suspends the invoking thread until the system time arrives to the
  942. * specified value.
  943. * @note The system time is assumed to be between @p prev and @p time
  944. * else the call is assumed to have been called outside the
  945. * allowed time interval, in this case no sleep is performed.
  946. * @see chThdSleepUntil()
  947. *
  948. * @param[in] prev absolute system time of the previous deadline
  949. * @param[in] next absolute system time of the next deadline
  950. * @return the @p next parameter
  951. *
  952. * @api
  953. */
  954. static systime_t sleepUntilWindowed(systime_t prev, systime_t next) {
  955. return chThdSleepUntilWindowed(prev, next);
  956. }
  957. /**
  958. * @brief Yields the time slot.
  959. * @details Yields the CPU control to the next thread in the ready list
  960. * with equal priority, if any.
  961. *
  962. * @api
  963. */
  964. static void yield(void) {
  965. chThdYield();
  966. }
  967. #if CH_CFG_USE_MESSAGES || defined(__DOXYGEN__)
  968. /**
  969. * @brief Waits for a message.
  970. * @post On the returned reference it is mandatory to call
  971. * @p releaseMessage() or the sender thread would be waiting
  972. * undefinitely.
  973. *
  974. * @return The sender thread reference.
  975. *
  976. * @api
  977. */
  978. static ThreadReference waitMessage(void) {
  979. return ThreadReference(chMsgWait());
  980. }
  981. #endif /* CH_CFG_USE_MESSAGES == TRUE */
  982. #if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
  983. /**
  984. * @brief Clears the pending events specified in the mask.
  985. *
  986. * @param[in] mask the events to be cleared
  987. * @return The pending events that were cleared.
  988. *
  989. * @api
  990. */
  991. static eventmask_t getAndClearEvents(eventmask_t mask) {
  992. return chEvtGetAndClearEvents(mask);
  993. }
  994. /**
  995. * @brief Adds (OR) a set of event flags on the current thread, this is
  996. * @b much faster than using @p chEvtBroadcast() or
  997. * @p chEvtSignal().
  998. *
  999. * @param[in] mask the event flags to be added
  1000. * @return The current pending events mask.
  1001. *
  1002. * @api
  1003. */
  1004. static eventmask_t addEvents(eventmask_t mask) {
  1005. return chEvtAddEvents(mask);
  1006. }
  1007. /**
  1008. * @brief Waits for a single event.
  1009. * @details A pending event among those specified in @p ewmask is selected,
  1010. * cleared and its mask returned.
  1011. * @note One and only one event is served in the function, the one with
  1012. * the lowest event id. The function is meant to be invoked into
  1013. * a loop in order to serve all the pending events.<br>
  1014. * This means that Event Listeners with a lower event identifier
  1015. * have an higher priority.
  1016. *
  1017. * @param[in] ewmask mask of the events that the function should
  1018. * wait for, @p ALL_EVENTS enables all the events
  1019. * @return The mask of the lowest id served and cleared
  1020. * event.
  1021. *
  1022. * @api
  1023. */
  1024. static eventmask_t waitOneEvent(eventmask_t ewmask) {
  1025. return chEvtWaitOne(ewmask);
  1026. }
  1027. /**
  1028. * @brief Waits for any of the specified events.
  1029. * @details The function waits for any event among those specified in
  1030. * @p ewmask to become pending then the events are cleared and
  1031. * returned.
  1032. *
  1033. * @param[in] ewmask mask of the events that the function should
  1034. * wait for, @p ALL_EVENTS enables all the events
  1035. * @return The mask of the served and cleared events.
  1036. *
  1037. * @api
  1038. */
  1039. static eventmask_t waitAnyEvent(eventmask_t ewmask) {
  1040. return chEvtWaitAny(ewmask);
  1041. }
  1042. /**
  1043. * @brief Waits for all the specified event flags then clears them.
  1044. * @details The function waits for all the events specified in @p ewmask
  1045. * to become pending then the events are cleared and returned.
  1046. *
  1047. * @param[in] ewmask mask of the event ids that the function should
  1048. * wait for
  1049. * @return The mask of the served and cleared events.
  1050. *
  1051. * @api
  1052. */
  1053. static eventmask_t waitAllEvents(eventmask_t ewmask) {
  1054. return chEvtWaitAll(ewmask);
  1055. }
  1056. #if CH_CFG_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
  1057. /**
  1058. * @brief Waits for a single event.
  1059. * @details A pending event among those specified in @p ewmask is selected,
  1060. * cleared and its mask returned.
  1061. * @note One and only one event is served in the function, the one with
  1062. * the lowest event id. The function is meant to be invoked into
  1063. * a loop in order to serve all the pending events.<br>
  1064. * This means that Event Listeners with a lower event identifier
  1065. * have an higher priority.
  1066. *
  1067. * @param[in] ewmask mask of the events that the function should
  1068. * wait for, @p ALL_EVENTS enables all the events
  1069. *
  1070. * @param[in] timeout the number of ticks before the operation
  1071. * timouts
  1072. * @return The mask of the lowest id served and cleared
  1073. * event.
  1074. * @retval 0 if the specified timeout expired.
  1075. *
  1076. * @api
  1077. */
  1078. static eventmask_t waitOneEventTimeout(eventmask_t ewmask,
  1079. sysinterval_t timeout) {
  1080. return chEvtWaitOneTimeout(ewmask, timeout);
  1081. }
  1082. /**
  1083. * @brief Waits for any of the specified events.
  1084. * @details The function waits for any event among those specified in
  1085. * @p ewmask to become pending then the events are cleared and
  1086. * returned.
  1087. *
  1088. * @param[in] ewmask mask of the events that the function should
  1089. * wait for, @p ALL_EVENTS enables all the events
  1090. * @param[in] timeout the number of ticks before the operation
  1091. * timouts
  1092. * @return The mask of the served and cleared events.
  1093. * @retval 0 if the specified timeout expired.
  1094. *
  1095. * @api
  1096. */
  1097. static eventmask_t waitAnyEventTimeout(eventmask_t ewmask,
  1098. sysinterval_t timeout) {
  1099. return chEvtWaitAnyTimeout(ewmask, timeout);
  1100. }
  1101. /**
  1102. * @brief Waits for all the specified event flags then clears them.
  1103. * @details The function waits for all the events specified in @p ewmask
  1104. * to become pending then the events are cleared and returned.
  1105. *
  1106. * @param[in] ewmask mask of the event ids that the function should
  1107. * wait for
  1108. * @param[in] timeout the number of ticks before the operation
  1109. * timouts
  1110. * @return The mask of the served and cleared events.
  1111. * @retval 0 if the specified timeout expired.
  1112. *
  1113. * @api
  1114. */
  1115. static eventmask_t waitAllEventsTimeout(eventmask_t ewmask,
  1116. sysinterval_t timeout) {
  1117. return chEvtWaitAllTimeout(ewmask, timeout);
  1118. }
  1119. #endif /* CH_CFG_USE_EVENTS_TIMEOUT == TRUE */
  1120. /**
  1121. * @brief Invokes the event handlers associated to an event flags mask.
  1122. *
  1123. * @param[in] mask mask of the event flags to be dispatched
  1124. * @param[in] handlers an array of @p evhandler_t. The array must have
  1125. * size equal to the number of bits in eventmask_t.
  1126. *
  1127. * @api
  1128. */
  1129. static void dispatchEvents(const evhandler_t handlers[],
  1130. eventmask_t mask) {
  1131. chEvtDispatch(handlers, mask);
  1132. }
  1133. #endif /* CH_CFG_USE_EVENTS == TRUE */
  1134. #if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
  1135. /**
  1136. * @brief Unlocks all the mutexes owned by the invoking thread.
  1137. * @post The stack of owned mutexes is emptied and all the found
  1138. * mutexes are unlocked.
  1139. * @note This function is <b>MUCH MORE</b> efficient than releasing the
  1140. * mutexes one by one and not just because the call overhead,
  1141. * this function does not have any overhead related to the
  1142. * priority inheritance mechanism.
  1143. *
  1144. * @api
  1145. */
  1146. static void unlockAllMutexes(void) {
  1147. chMtxUnlockAll();
  1148. }
  1149. #endif /* CH_CFG_USE_MUTEXES == TRUE */
  1150. };
  1151. /*------------------------------------------------------------------------*
  1152. * chibios_rt::BaseStaticThread *
  1153. *------------------------------------------------------------------------*/
  1154. /**
  1155. * @brief Static threads template base class.
  1156. * @details This class introduces static working area instantiation.
  1157. *
  1158. * @param N the working area size for the thread class
  1159. */
  1160. template <int N>
  1161. class BaseStaticThread : public BaseThread {
  1162. protected:
  1163. THD_WORKING_AREA(wa, N);
  1164. public:
  1165. /**
  1166. * @brief Starts a static thread.
  1167. *
  1168. * @param[in] prio thread priority
  1169. * @return A reference to the created thread with
  1170. * reference counter set to one.
  1171. *
  1172. * @api
  1173. */
  1174. ThreadReference start(tprio_t prio) override {
  1175. void _thd_start(void *arg);
  1176. return ThreadReference(chThdCreateStatic(wa, sizeof(wa), prio,
  1177. _thd_start, this));
  1178. }
  1179. };
  1180. /*------------------------------------------------------------------------*
  1181. * chibios_rt::BaseDynamicThread *
  1182. *------------------------------------------------------------------------*/
  1183. /**
  1184. * @brief Dynamic threads base class.
  1185. */
  1186. class BaseDynamicThread : public BaseThread {
  1187. };
  1188. /*------------------------------------------------------------------------*
  1189. * chibios_rt::ThreadStayPoint *
  1190. *------------------------------------------------------------------------*/
  1191. /**
  1192. * @brief Thread suspension point class.
  1193. * @details This class encapsulates a reference to a suspended thread.
  1194. */
  1195. class ThreadStayPoint {
  1196. /**
  1197. * @brief Pointer to the suspended thread.
  1198. */
  1199. thread_reference_t thread_ref = nullptr;
  1200. public:
  1201. /**
  1202. * @brief Thread stay point constructor.
  1203. *
  1204. * @init
  1205. */
  1206. ThreadStayPoint() {
  1207. }
  1208. /* Prohibit copy construction and assignment.*/
  1209. ThreadStayPoint(const ThreadStayPoint &) = delete;
  1210. ThreadStayPoint &operator=(const ThreadStayPoint &) = delete;
  1211. /**
  1212. * @brief Suspends the current thread on the stay point.
  1213. * @details The suspended thread becomes the referenced thread. It is
  1214. * possible to use this method only if the thread reference
  1215. * was set to @p nullptr.
  1216. *
  1217. * @return The incoming message.
  1218. *
  1219. * @sclass
  1220. */
  1221. msg_t suspendS(void) {
  1222. return chThdSuspendS(&thread_ref);
  1223. }
  1224. /**
  1225. * @brief Suspends the current thread on the stay point with timeout.
  1226. * @details The suspended thread becomes the referenced thread. It is
  1227. * possible to use this method only if the thread reference
  1228. * was set to @p nullptr.
  1229. *
  1230. *
  1231. * @param[in] timeout the number of ticks before the operation timeouts,
  1232. * the following special values are allowed:
  1233. * - @a TIME_IMMEDIATE immediate timeout.
  1234. * - @a TIME_INFINITE no timeout.
  1235. * .
  1236. * @return A message specifying how the invoking thread has
  1237. * been released from the semaphore.
  1238. * @retval MSG_OK if the binary semaphore has been successfully
  1239. * taken.
  1240. * @retval MSG_RESET if the binary semaphore has been reset using
  1241. * @p bsemReset().
  1242. * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
  1243. * or reset within the specified timeout.
  1244. *
  1245. * @sclass
  1246. */
  1247. msg_t suspendS(sysinterval_t timeout) {
  1248. return chThdSuspendTimeoutS(&thread_ref, timeout);
  1249. }
  1250. /**
  1251. * @brief Resumes the currently referenced thread, if any.
  1252. *
  1253. * @param[in] msg the wakeup message
  1254. *
  1255. * @iclass
  1256. */
  1257. void resumeI(msg_t msg) {
  1258. chThdResumeI(&thread_ref, msg);
  1259. }
  1260. /**
  1261. * @brief Resumes the currently referenced thread, if any.
  1262. *
  1263. * @param[in] msg the wakeup message
  1264. *
  1265. * @sclass
  1266. */
  1267. void resumeS(msg_t msg) {
  1268. chThdResumeS(&thread_ref, msg);
  1269. }
  1270. };
  1271. /*------------------------------------------------------------------------*
  1272. * chibios_rt::SynchronizationObject *
  1273. *------------------------------------------------------------------------*/
  1274. /**
  1275. * @brief Base class for all synchronization objects.
  1276. * @note No other uses.
  1277. */
  1278. class SynchronizationObject {
  1279. };
  1280. /*------------------------------------------------------------------------*
  1281. * chibios_rt::ThreadsQueue *
  1282. *------------------------------------------------------------------------*/
  1283. /**
  1284. * @brief Threads queue class.
  1285. * @details This class encapsulates a queue of threads.
  1286. */
  1287. class ThreadsQueue : public SynchronizationObject {
  1288. /**
  1289. * @brief Pointer to the system thread.
  1290. */
  1291. threads_queue_t threads_queue;
  1292. public:
  1293. /**
  1294. * @brief Threads queue constructor.
  1295. *
  1296. * @init
  1297. */
  1298. ThreadsQueue() {
  1299. chThdQueueObjectInit(&threads_queue);
  1300. }
  1301. /* Prohibit copy construction and assignment.*/
  1302. ThreadsQueue(const ThreadsQueue &) = delete;
  1303. ThreadsQueue &operator=(const ThreadsQueue &) = delete;
  1304. /**
  1305. * @brief Enqueues the caller thread on a threads queue object.
  1306. * @details The caller thread is enqueued and put to sleep until it is
  1307. * dequeued or the specified timeouts expires.
  1308. *
  1309. * @param[in] timeout the timeout in system ticks, the special values are
  1310. * handled as follow:
  1311. * - @a TIME_INFINITE the thread enters an infinite sleep
  1312. * state.
  1313. * - @a TIME_IMMEDIATE the thread is not enqueued and
  1314. * the function returns @p MSG_TIMEOUT as if a timeout
  1315. * occurred.
  1316. * .
  1317. * @return The message from @p osalQueueWakeupOneI() or
  1318. * @p osalQueueWakeupAllI() functions.
  1319. * @retval MSG_TIMEOUT if the thread has not been dequeued within the
  1320. * specified timeout or if the function has been
  1321. * invoked with @p TIME_IMMEDIATE as timeout
  1322. * specification.
  1323. *
  1324. * @sclass
  1325. */
  1326. msg_t enqueueSelfS(sysinterval_t timeout) {
  1327. return chThdEnqueueTimeoutS(&threads_queue, timeout);
  1328. }
  1329. /**
  1330. * @brief Dequeues and wakes up one thread from the threads queue object,
  1331. * if any.
  1332. *
  1333. * @param[in] msg the message code
  1334. *
  1335. * @iclass
  1336. */
  1337. void dequeueNextI(msg_t msg) {
  1338. chThdDequeueNextI(&threads_queue, msg);
  1339. }
  1340. /**
  1341. * @brief Dequeues and wakes up all threads from the threads queue object.
  1342. *
  1343. * @param[in] msg the message code
  1344. *
  1345. * @iclass
  1346. */
  1347. void chdequeueAllI(msg_t msg) {
  1348. chThdDequeueAllI(&threads_queue, msg);
  1349. }
  1350. };
  1351. #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
  1352. /*------------------------------------------------------------------------*
  1353. * chibios_rt::CounterSemaphore *
  1354. *------------------------------------------------------------------------*/
  1355. /**
  1356. * @brief Class encapsulating a semaphore.
  1357. */
  1358. class CounterSemaphore : public SynchronizationObject {
  1359. /**
  1360. * @brief Embedded @p semaphore_t structure.
  1361. */
  1362. semaphore_t sem;
  1363. public:
  1364. /**
  1365. * @brief CounterSemaphore constructor.
  1366. * @details The embedded @p Semaphore structure is initialized.
  1367. *
  1368. * @param[in] n the semaphore counter value, must be greater
  1369. * or equal to zero
  1370. *
  1371. * @init
  1372. */
  1373. CounterSemaphore(cnt_t n) {
  1374. chSemObjectInit(&sem, n);
  1375. }
  1376. /**
  1377. * @brief Performs a reset operation on the semaphore.
  1378. * @post After invoking this function all the threads waiting on the
  1379. * semaphore, if any, are released and the semaphore counter is
  1380. * set to the specified, non negative, value.
  1381. * @note The released threads can recognize they were waked up by a
  1382. * reset rather than a signal because the @p chSemWait() will
  1383. * return @p MSG_RESET instead of @p MSG_OK.
  1384. *
  1385. * @param[in] n the new value of the semaphore counter. The value
  1386. * must be non-negative.
  1387. *
  1388. * @api
  1389. */
  1390. void reset(cnt_t n) {
  1391. chSemReset(&sem, n);
  1392. }
  1393. /**
  1394. * @brief Performs a reset operation on the semaphore.
  1395. * @post After invoking this function all the threads waiting on the
  1396. * semaphore, if any, are released and the semaphore counter is
  1397. * set to the specified, non negative, value.
  1398. * @post This function does not reschedule so a call to a rescheduling
  1399. * function must be performed before unlocking the kernel. Note
  1400. * that interrupt handlers always reschedule on exit so an
  1401. * explicit reschedule must not be performed in ISRs.
  1402. * @note The released threads can recognize they were waked up by a
  1403. * reset rather than a signal because the @p chSemWait() will
  1404. * return @p MSG_RESET instead of @p MSG_OK.
  1405. *
  1406. * @param[in] n the new value of the semaphore counter. The value
  1407. * must be non-negative.
  1408. *
  1409. * @iclass
  1410. */
  1411. void resetI(cnt_t n) {
  1412. chSemResetI(&sem, n);
  1413. }
  1414. /**
  1415. * @brief Performs a wait operation on a semaphore.
  1416. *
  1417. * @return A message specifying how the invoking thread has
  1418. * been released from the semaphore.
  1419. * @retval MSG_OK if the thread has not stopped on the semaphore or
  1420. * the semaphore has been signaled.
  1421. * @retval MSG_RESET if the semaphore has been reset using
  1422. * @p chSemReset().
  1423. *
  1424. * @api
  1425. */
  1426. msg_t wait(void) {
  1427. return chSemWait(&sem);
  1428. }
  1429. /**
  1430. * @brief Performs a wait operation on a semaphore.
  1431. *
  1432. * @return A message specifying how the invoking thread has
  1433. * been released from the semaphore.
  1434. * @retval MSG_OK if the thread has not stopped on the semaphore or
  1435. * the semaphore has been signaled.
  1436. * @retval MSG_RESET if the semaphore has been reset using
  1437. * @p chSemReset().
  1438. *
  1439. * @sclass
  1440. */
  1441. msg_t waitS(void) {
  1442. return chSemWaitS(&sem);
  1443. }
  1444. /**
  1445. * @brief Performs a wait operation on a semaphore with timeout
  1446. * specification.
  1447. *
  1448. * @param[in] timeout the number of ticks before the operation timeouts,
  1449. * the following special values are allowed:
  1450. * - @a TIME_IMMEDIATE immediate timeout.
  1451. * - @a TIME_INFINITE no timeout.
  1452. * .
  1453. * @return A message specifying how the invoking thread has
  1454. * been released from the semaphore.
  1455. * @retval MSG_OK if the thread has not stopped on the semaphore or
  1456. * the semaphore has been signaled.
  1457. * @retval MSG_RESET if the semaphore has been reset using
  1458. * @p chSemReset().
  1459. * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset
  1460. * within the specified timeout.
  1461. *
  1462. * @api
  1463. */
  1464. msg_t wait(sysinterval_t timeout) {
  1465. return chSemWaitTimeout(&sem, timeout);
  1466. }
  1467. /**
  1468. * @brief Performs a wait operation on a semaphore with timeout
  1469. * specification.
  1470. *
  1471. * @param[in] timeout the number of ticks before the operation timeouts,
  1472. * the following special values are allowed:
  1473. * - @a TIME_IMMEDIATE immediate timeout.
  1474. * - @a TIME_INFINITE no timeout.
  1475. * .
  1476. * @return A message specifying how the invoking thread has
  1477. * been released from the semaphore.
  1478. * @retval MSG_OK if the thread has not stopped on the semaphore or
  1479. * the semaphore has been signaled.
  1480. * @retval MSG_RESET if the semaphore has been reset using
  1481. * @p chSemReset().
  1482. * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset
  1483. * within the specified timeout.
  1484. *
  1485. * @sclass
  1486. */
  1487. msg_t waitS(sysinterval_t timeout) {
  1488. return chSemWaitTimeoutS(&sem, timeout);
  1489. }
  1490. /**
  1491. * @brief Performs a signal operation on a semaphore.
  1492. *
  1493. * @api
  1494. */
  1495. void signal(void) {
  1496. chSemSignal(&sem);
  1497. }
  1498. /**
  1499. * @brief Performs a signal operation on a semaphore.
  1500. * @post This function does not reschedule so a call to a rescheduling
  1501. * function must be performed before unlocking the kernel. Note
  1502. * that interrupt handlers always reschedule on exit so an
  1503. * explicit reschedule must not be performed in ISRs.
  1504. *
  1505. * @iclass
  1506. */
  1507. void signalI(void) {
  1508. chSemSignalI(&sem);
  1509. }
  1510. /**
  1511. * @brief Adds the specified value to the semaphore counter.
  1512. * @post This function does not reschedule so a call to a rescheduling
  1513. * function must be performed before unlocking the kernel. Note
  1514. * that interrupt handlers always reschedule on exit so an explicit
  1515. * reschedule must not be performed in ISRs.
  1516. *
  1517. * @param[in] n value to be added to the semaphore counter. The
  1518. * value must be positive.
  1519. *
  1520. * @iclass
  1521. */
  1522. void addCounterI(cnt_t n) {
  1523. chSemAddCounterI(&sem, n);
  1524. }
  1525. /**
  1526. * @brief Returns the semaphore counter value.
  1527. *
  1528. * @return The semaphore counter value.
  1529. *
  1530. * @iclass
  1531. */
  1532. cnt_t getCounterI(void) const {
  1533. return chSemGetCounterI(&sem);
  1534. }
  1535. /**
  1536. * @brief Atomic signal and wait operations.
  1537. *
  1538. * @param[in] ssem @p Semaphore object to be signaled
  1539. * @param[in] wsem @p Semaphore object to wait on
  1540. * @return A message specifying how the invoking thread
  1541. * has been released from the semaphore.
  1542. * @retval MSG_OK if the thread has not stopped on the semaphore
  1543. * or the semaphore has been signaled.
  1544. * @retval MSG_RESET if the semaphore has been reset using
  1545. * @p chSemReset().
  1546. *
  1547. * @api
  1548. */
  1549. static msg_t signalWait(CounterSemaphore *ssem,
  1550. CounterSemaphore *wsem) {
  1551. return chSemSignalWait(&ssem->sem, &wsem->sem);
  1552. }
  1553. };
  1554. /*------------------------------------------------------------------------*
  1555. * chibios_rt::BinarySemaphore *
  1556. *------------------------------------------------------------------------*/
  1557. /**
  1558. * @brief Class encapsulating a binary semaphore.
  1559. */
  1560. class BinarySemaphore : public SynchronizationObject {
  1561. /**
  1562. * @brief Embedded @p binary_semaphore_t structure.
  1563. */
  1564. binary_semaphore_t bsem;
  1565. public:
  1566. /**
  1567. * @brief BinarySemaphore constructor.
  1568. * @details The embedded @p ::BinarySemaphore structure is initialized.
  1569. *
  1570. * @param[in] taken initial state of the binary semaphore:
  1571. * - @a false, the initial state is not taken.
  1572. * - @a true, the initial state is taken.
  1573. * .
  1574. *
  1575. * @init
  1576. */
  1577. BinarySemaphore(bool taken) {
  1578. chBSemObjectInit(&bsem, taken);
  1579. }
  1580. /**
  1581. * @brief Wait operation on the binary semaphore.
  1582. *
  1583. * @return A message specifying how the invoking thread has
  1584. * been released from the semaphore.
  1585. * @retval MSG_OK if the binary semaphore has been successfully
  1586. * taken.
  1587. * @retval MSG_RESET if the binary semaphore has been reset using
  1588. * @p bsemReset().
  1589. *
  1590. * @api
  1591. */
  1592. msg_t wait(void) {
  1593. return chBSemWait(&bsem);
  1594. }
  1595. /**
  1596. * @brief Wait operation on the binary semaphore.
  1597. *
  1598. * @return A message specifying how the invoking thread has
  1599. * been released from the semaphore.
  1600. * @retval MSG_OK if the binary semaphore has been successfully
  1601. * taken.
  1602. * @retval MSG_RESET if the binary semaphore has been reset using
  1603. * @p bsemReset().
  1604. *
  1605. * @sclass
  1606. */
  1607. msg_t waitS(void) {
  1608. return chBSemWaitS(&bsem);
  1609. }
  1610. /**
  1611. * @brief Wait operation on the binary semaphore.
  1612. *
  1613. * @param[in] timeout the number of ticks before the operation timeouts,
  1614. * the following special values are allowed:
  1615. * - @a TIME_IMMEDIATE immediate timeout.
  1616. * - @a TIME_INFINITE no timeout.
  1617. * .
  1618. * @return A message specifying how the invoking thread has
  1619. * been released from the semaphore.
  1620. * @retval MSG_OK if the binary semaphore has been successfully
  1621. * taken.
  1622. * @retval MSG_RESET if the binary semaphore has been reset using
  1623. * @p bsemReset().
  1624. * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
  1625. * or reset within the specified timeout.
  1626. *
  1627. * @api
  1628. */
  1629. msg_t wait(sysinterval_t timeout) {
  1630. return chBSemWaitTimeout(&bsem, timeout);
  1631. }
  1632. /**
  1633. * @brief Wait operation on the binary semaphore.
  1634. *
  1635. * @param[in] timeout the number of ticks before the operation timeouts,
  1636. * the following special values are allowed:
  1637. * - @a TIME_IMMEDIATE immediate timeout.
  1638. * - @a TIME_INFINITE no timeout.
  1639. * .
  1640. * @return A message specifying how the invoking thread has
  1641. * been released from the semaphore.
  1642. * @retval MSG_OK if the binary semaphore has been successfully
  1643. * taken.
  1644. * @retval MSG_RESET if the binary semaphore has been reset using
  1645. * @p bsemReset().
  1646. * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
  1647. * or reset within the specified timeout.
  1648. *
  1649. * @sclass
  1650. */
  1651. msg_t waitS(sysinterval_t timeout) {
  1652. return chBSemWaitTimeoutS(&bsem, timeout);
  1653. }
  1654. /**
  1655. * @brief Reset operation on the binary semaphore.
  1656. * @note The released threads can recognize they were waked up by a
  1657. * reset rather than a signal because the @p bsemWait() will
  1658. * return @p MSG_RESET instead of @p MSG_OK.
  1659. *
  1660. * @param[in] taken new state of the binary semaphore
  1661. * - @a FALSE, the new state is not taken.
  1662. * - @a TRUE, the new state is taken.
  1663. * .
  1664. *
  1665. * @api
  1666. */
  1667. void reset(bool taken) {
  1668. chBSemReset(&bsem, taken);
  1669. }
  1670. /**
  1671. * @brief Reset operation on the binary semaphore.
  1672. * @note The released threads can recognize they were waked up by a
  1673. * reset rather than a signal because the @p bsemWait() will
  1674. * return @p MSG_RESET instead of @p MSG_OK.
  1675. * @note This function does not reschedule.
  1676. *
  1677. * @param[in] taken new state of the binary semaphore
  1678. * - @a FALSE, the new state is not taken.
  1679. * - @a TRUE, the new state is taken.
  1680. * .
  1681. *
  1682. * @iclass
  1683. */
  1684. void resetI(bool taken) {
  1685. chBSemResetI(&bsem, taken);
  1686. }
  1687. /**
  1688. * @brief Performs a signal operation on a binary semaphore.
  1689. *
  1690. * @api
  1691. */
  1692. void signal(void) {
  1693. chBSemSignal(&bsem);
  1694. }
  1695. /**
  1696. * @brief Performs a signal operation on a binary semaphore.
  1697. * @note This function does not reschedule.
  1698. *
  1699. * @iclass
  1700. */
  1701. void signalI(void) {
  1702. chBSemSignalI(&bsem);
  1703. }
  1704. /**
  1705. * @brief Returns the binary semaphore current state.
  1706. *
  1707. * @return The binary semaphore current state.
  1708. * @retval false if the binary semaphore is not taken.
  1709. * @retval true if the binary semaphore is taken.
  1710. *
  1711. * @iclass
  1712. */
  1713. bool getStateI(void) const {
  1714. return (bool)chBSemGetStateI(&bsem);
  1715. }
  1716. };
  1717. #endif /* CH_CFG_USE_SEMAPHORES == TRUE */
  1718. #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
  1719. /*------------------------------------------------------------------------*
  1720. * chibios_rt::Mutex *
  1721. *------------------------------------------------------------------------*/
  1722. /**
  1723. * @brief Class encapsulating a mutex.
  1724. */
  1725. class Mutex : public SynchronizationObject {
  1726. /**
  1727. * @brief Embedded @p mutex_t structure.
  1728. */
  1729. mutex_t mutex;
  1730. public:
  1731. /**
  1732. * @brief Mutex object constructor.
  1733. * @details The embedded @p mutex_t structure is initialized.
  1734. *
  1735. * @init
  1736. */
  1737. Mutex(void) {
  1738. chMtxObjectInit(&mutex);
  1739. }
  1740. /**
  1741. * @brief Tries to lock a mutex.
  1742. * @details This function attempts to lock a mutex, if the mutex is already
  1743. * locked by another thread then the function exits without
  1744. * waiting.
  1745. * @post The mutex is locked and inserted in the per-thread stack of
  1746. * owned mutexes.
  1747. * @note This function does not have any overhead related to the
  1748. * priority inheritance mechanism because it does not try to
  1749. * enter a sleep state.
  1750. *
  1751. * @return The operation status.
  1752. * @retval TRUE if the mutex has been successfully acquired
  1753. * @retval FALSE if the lock attempt failed.
  1754. *
  1755. * @api
  1756. */
  1757. bool tryLock(void) {
  1758. return chMtxTryLock(&mutex);
  1759. }
  1760. /**
  1761. * @brief Tries to lock a mutex.
  1762. * @details This function attempts to lock a mutex, if the mutex is already
  1763. * taken by another thread then the function exits without
  1764. * waiting.
  1765. * @post The mutex is locked and inserted in the per-thread stack of
  1766. * owned mutexes.
  1767. * @note This function does not have any overhead related to the
  1768. * priority inheritance mechanism because it does not try to
  1769. * enter a sleep state.
  1770. *
  1771. * @return The operation status.
  1772. * @retval TRUE if the mutex has been successfully acquired
  1773. * @retval FALSE if the lock attempt failed.
  1774. *
  1775. * @sclass
  1776. */
  1777. bool tryLockS(void) {
  1778. return chMtxTryLockS(&mutex);
  1779. }
  1780. /**
  1781. * @brief Locks the specified mutex.
  1782. * @post The mutex is locked and inserted in the per-thread stack of
  1783. * owned mutexes.
  1784. *
  1785. * @api
  1786. */
  1787. void lock(void) {
  1788. chMtxLock(&mutex);
  1789. }
  1790. /**
  1791. * @brief Locks the specified mutex.
  1792. * @post The mutex is locked and inserted in the per-thread stack of
  1793. * owned mutexes.
  1794. *
  1795. * @sclass
  1796. */
  1797. void lockS(void) {
  1798. chMtxLockS(&mutex);
  1799. }
  1800. /**
  1801. * @brief Unlocks the next owned mutex in reverse lock order.
  1802. * @pre The invoking thread <b>must</b> have at least one owned mutex.
  1803. * @post The mutex is unlocked and removed from the per-thread stack of
  1804. * owned mutexes.
  1805. *
  1806. * @api
  1807. */
  1808. void unlock(void) {
  1809. chMtxUnlock(&mutex);
  1810. }
  1811. /**
  1812. * @brief Unlocks the next owned mutex in reverse lock order.
  1813. * @pre The invoking thread <b>must</b> have at least one owned mutex.
  1814. * @post The mutex is unlocked and removed from the per-thread stack of
  1815. * owned mutexes.
  1816. * @post This function does not reschedule so a call to a rescheduling
  1817. * function must be performed before unlocking the kernel.
  1818. *
  1819. * @sclass
  1820. */
  1821. void unlockS(void) {
  1822. chMtxUnlockS(&mutex);
  1823. }
  1824. /**
  1825. * @brief Unlocks the next owned mutex in reverse lock order.
  1826. * @pre The invoking thread <b>must</b> have at least one owned mutex.
  1827. * @post The mutex is unlocked and removed from the per-thread stack of
  1828. * owned mutexes.
  1829. *
  1830. * @return A pointer to the unlocked mutex.
  1831. *
  1832. * @api
  1833. */
  1834. void unlockMutex(void) {
  1835. chMtxUnlock(&mutex);
  1836. }
  1837. /**
  1838. * @brief Unlocks the next owned mutex in reverse lock order.
  1839. * @pre The invoking thread <b>must</b> have at least one owned mutex.
  1840. * @post The mutex is unlocked and removed from the per-thread stack of
  1841. * owned mutexes.
  1842. * @post This function does not reschedule so a call to a rescheduling
  1843. * function must be performed before unlocking the kernel.
  1844. *
  1845. * @return A pointer to the unlocked mutex.
  1846. *
  1847. * @sclass
  1848. */
  1849. void unlockMutexS(void) {
  1850. chMtxUnlockS(&mutex);
  1851. }
  1852. };
  1853. /*------------------------------------------------------------------------*
  1854. * chibios_rt::MutexLocker *
  1855. *------------------------------------------------------------------------*/
  1856. /**
  1857. * @brief RAII helper for mutexes.
  1858. */
  1859. class MutexLocker
  1860. {
  1861. Mutex& mutex;
  1862. public:
  1863. MutexLocker(Mutex& m) : mutex(m) {
  1864. mutex.lock();
  1865. }
  1866. ~MutexLocker() {
  1867. mutex.unlock();
  1868. }
  1869. };
  1870. #if (CH_CFG_USE_CONDVARS == TRUE) || defined(__DOXYGEN__)
  1871. /*------------------------------------------------------------------------*
  1872. * chibios_rt::Monitor *
  1873. *------------------------------------------------------------------------*/
  1874. /**
  1875. * @brief Template class to be used for implementing a monitor.
  1876. */
  1877. template <unsigned N>
  1878. class Monitor: protected Mutex {
  1879. condition_variable_t condvars[N];
  1880. protected:
  1881. /**
  1882. * @brief Waits on the condition variable releasing the mutex lock.
  1883. *
  1884. * @param[in] var the condition variable index
  1885. * @return A message specifying how the invoking thread has
  1886. * been released from the condition variable.
  1887. * @retval MSG_OK if the condition variable has been signaled using
  1888. * @p signal().
  1889. * @retval MSG_RESET if the condition variable has been signaled using
  1890. * @p broadcast().
  1891. *
  1892. * @api
  1893. */
  1894. msg_t wait(unsigned var) {
  1895. chDbgCheck(var < N);
  1896. return chCondWait(&condvars[var]);
  1897. }
  1898. /**
  1899. * @brief Waits on the condition variable releasing the mutex lock.
  1900. *
  1901. * @param[in] var the condition variable index
  1902. * @return A message specifying how the invoking thread has
  1903. * been released from the condition variable.
  1904. * @retval MSG_OK if the condition variable has been signaled using
  1905. * @p signal().
  1906. * @retval MSG_RESET if the condition variable has been signaled using
  1907. * @p broadcast().
  1908. *
  1909. * @sclass
  1910. */
  1911. msg_t waitS(unsigned var) {
  1912. chDbgCheck(var < N);
  1913. return chCondWaitS(&condvars[var]);
  1914. }
  1915. #if (CH_CFG_USE_CONDVARS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
  1916. /**
  1917. * @brief Waits on the CondVar while releasing the controlling mutex.
  1918. *
  1919. * @param[in] var the condition variable index
  1920. * @param[in] timeout the number of ticks before the operation fails
  1921. * @return The wakep mode.
  1922. * @retval MSG_OK if the condition variable was signaled using
  1923. * @p signal().
  1924. * @retval MSG_RESET if the condition variable was signaled using
  1925. * @p broadcast().
  1926. * @retval MSG_TIMEOUT if the condition variable was not signaled
  1927. * within the specified timeout.
  1928. *
  1929. * @api
  1930. */
  1931. msg_t wait(unsigned var, sysinterval_t timeout) {
  1932. chDbgCheck(var < N);
  1933. return chCondWaitTimeout(&condvars[var], timeout);
  1934. }
  1935. /**
  1936. * @brief Waits on the CondVar while releasing the controlling mutex.
  1937. *
  1938. * @param[in] var the condition variable index
  1939. * @param[in] timeout the number of ticks before the operation fails
  1940. * @return The wakep mode.
  1941. * @retval MSG_OK if the condition variable was signaled using
  1942. * @p signal().
  1943. * @retval MSG_RESET if the condition variable was signaled using
  1944. * @p broadcast().
  1945. * @retval MSG_TIMEOUT if the condition variable was not signaled
  1946. * within the specified timeout.
  1947. *
  1948. * @sclass
  1949. */
  1950. msg_t waitS(unsigned var, sysinterval_t timeout) {
  1951. chDbgCheck(var < N);
  1952. return chCondWaitTimeoutS(&condvars[var], timeout);
  1953. }
  1954. #endif /* CH_CFG_USE_CONDVARS_TIMEOUT == TRUE */
  1955. public:
  1956. /**
  1957. * @brief Monitor object constructor.
  1958. *
  1959. * @init
  1960. */
  1961. Monitor(void) : Mutex() {
  1962. for (unsigned i = 0; i < N; i++) {
  1963. chCondObjectInit(&condvars[i]);
  1964. }
  1965. }
  1966. /**
  1967. * @brief Signals one thread that is waiting on the condition variable.
  1968. *
  1969. * @param[in] var the condition variable index
  1970. *
  1971. * @api
  1972. */
  1973. void signal(unsigned var) {
  1974. chDbgCheck(var < N);
  1975. chCondSignal(&condvars[var]);
  1976. }
  1977. /**
  1978. * @brief Signals one thread that is waiting on the condition variable.
  1979. * @post This function does not reschedule so a call to a rescheduling
  1980. * function must be performed before unlocking the kernel. Note
  1981. * that interrupt handlers always reschedule on exit so an
  1982. * explicit reschedule must not be performed in ISRs.
  1983. *
  1984. * @param[in] var the condition variable index
  1985. *
  1986. * @iclass
  1987. */
  1988. void signalI(unsigned var) {
  1989. chDbgCheck(var < N);
  1990. chCondSignalI(&condvars[var]);
  1991. }
  1992. /**
  1993. * @brief Signals all threads that are waiting on the condition variable.
  1994. *
  1995. * @param[in] var the condition variable index
  1996. *
  1997. * @api
  1998. */
  1999. void broadcast(unsigned var) {
  2000. chDbgCheck(var < N);
  2001. chCondBroadcast(&condvars[var]);
  2002. }
  2003. /**
  2004. * @brief Signals all threads that are waiting on the condition variable.
  2005. * @post This function does not reschedule so a call to a rescheduling
  2006. * function must be performed before unlocking the kernel. Note
  2007. * that interrupt handlers always reschedule on exit so an
  2008. * explicit reschedule must not be performed in ISRs.
  2009. *
  2010. * @param[in] var the condition variable index
  2011. *
  2012. * @iclass
  2013. */
  2014. void broadcastI(unsigned var) {
  2015. chDbgCheck(var < N);
  2016. chCondBroadcastI(&condvars[var]);
  2017. }
  2018. };
  2019. #endif /* CH_CFG_USE_CONDVARS == TRUE */
  2020. #endif /* CH_CFG_USE_MUTEXES == TRUE */
  2021. #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
  2022. /*------------------------------------------------------------------------*
  2023. * chibios_rt::EvtListener *
  2024. *------------------------------------------------------------------------*/
  2025. /**
  2026. * @brief Class encapsulating an event listener.
  2027. */
  2028. class EventListener {
  2029. public:
  2030. /**
  2031. * @brief Embedded @p event_listener_t structure.
  2032. */
  2033. event_listener_t ev_listener;
  2034. /**
  2035. * @brief Returns the pending flags from the listener and clears them.
  2036. *
  2037. * @return The flags added to the listener by the
  2038. * associated event source.
  2039. *
  2040. * @api
  2041. */
  2042. eventflags_t getAndClearFlags(void) {
  2043. return chEvtGetAndClearFlags(&ev_listener);
  2044. }
  2045. /**
  2046. * @brief Returns the flags associated to an @p event_listener_t.
  2047. * @details The flags are returned and the @p event_listener_t flags mask is
  2048. * cleared.
  2049. *
  2050. * @return The flags added to the listener by the associated
  2051. * event source.
  2052. *
  2053. * @iclass
  2054. */
  2055. eventflags_t getAndClearFlagsI(void) {
  2056. return chEvtGetAndClearFlagsI(&ev_listener);
  2057. }
  2058. };
  2059. /*------------------------------------------------------------------------*
  2060. * chibios_rt::EvtSource *
  2061. *------------------------------------------------------------------------*/
  2062. /**
  2063. * @brief Class encapsulating an event source.
  2064. */
  2065. class EventSource {
  2066. /**
  2067. * @brief Embedded @p event_source_t structure.
  2068. */
  2069. event_source_t ev_source;
  2070. public:
  2071. /**
  2072. * @brief EvtSource object constructor.
  2073. * @details The embedded @p event_source_t structure is initialized.
  2074. *
  2075. * @init
  2076. */
  2077. EventSource(void) {
  2078. chEvtObjectInit(&ev_source);
  2079. }
  2080. /**
  2081. * @brief Registers a listener on the event source.
  2082. *
  2083. * @param[in] elp pointer to the @p EvtListener object
  2084. * @param[in] eid numeric identifier assigned to the Event
  2085. * Listener
  2086. *
  2087. * @api
  2088. */
  2089. void registerOne(EventListener *elp,
  2090. eventid_t eid) {
  2091. chEvtRegister(&ev_source, &elp->ev_listener, eid);
  2092. }
  2093. /**
  2094. * @brief Registers an Event Listener on an Event Source.
  2095. * @note Multiple Event Listeners can specify the same bits to be added.
  2096. *
  2097. * @param[in] elp pointer to the @p EvtListener object
  2098. * @param[in] emask the mask of event flags to be pended to the
  2099. * thread when the event source is broadcasted
  2100. *
  2101. * @api
  2102. */
  2103. void registerMask(EventListener *elp,
  2104. eventmask_t emask) {
  2105. chEvtRegisterMask(&ev_source, &elp->ev_listener, emask);
  2106. }
  2107. /**
  2108. * @brief Unregisters a listener.
  2109. * @details The specified listeners is no more signaled by the event
  2110. * source.
  2111. *
  2112. * @param[in] elp the listener to be unregistered
  2113. *
  2114. * @api
  2115. */
  2116. void unregister(EventListener *elp) {
  2117. chEvtUnregister(&ev_source, &elp->ev_listener);
  2118. }
  2119. /**
  2120. * @brief Broadcasts on an event source.
  2121. * @details All the listeners registered on the event source are signaled
  2122. * and the flags are added to the listener's flags mask.
  2123. *
  2124. * @param[in] flags the flags set to be added to the listener
  2125. * flags mask
  2126. *
  2127. * @api
  2128. */
  2129. void broadcastFlags(eventflags_t flags) {
  2130. chEvtBroadcastFlags(&ev_source, flags);
  2131. }
  2132. /**
  2133. * @brief Broadcasts on an event source.
  2134. * @details All the listeners registered on the event source are signaled
  2135. * and the flags are added to the listener's flags mask.
  2136. *
  2137. * @param[in] flags the flags set to be added to the listener
  2138. * flags mask
  2139. *
  2140. * @iclass
  2141. */
  2142. void broadcastFlagsI(eventflags_t flags) {
  2143. chEvtBroadcastFlagsI(&ev_source, flags);
  2144. }
  2145. };
  2146. #endif /* CH_CFG_USE_EVENTS == TRUE */
  2147. #if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
  2148. /*------------------------------------------------------------------------*
  2149. * chibios_rt::Mailbox *
  2150. *------------------------------------------------------------------------*/
  2151. /**
  2152. * @brief Base mailbox class.
  2153. *
  2154. * @param T type of objects that mailbox able to handle
  2155. */
  2156. template <typename T>
  2157. class MailboxBase {
  2158. /**
  2159. * @brief Embedded @p mailbox_t structure.
  2160. */
  2161. mailbox_t mb;
  2162. public:
  2163. /**
  2164. * @brief Mailbox constructor.
  2165. * @details The embedded @p mailbox_t structure is initialized.
  2166. *
  2167. * @param[in] buf pointer to the messages buffer as an array of
  2168. * @p msg_t
  2169. * @param[in] n number of elements in the buffer array
  2170. *
  2171. * @init
  2172. */
  2173. MailboxBase(msg_t *buf, cnt_t n) {
  2174. chMBObjectInit(&mb, buf, n);
  2175. }
  2176. /**
  2177. * @brief Resets a Mailbox object.
  2178. * @details All the waiting threads are resumed with status @p MSG_RESET
  2179. * and the queued messages are lost.
  2180. *
  2181. * @api
  2182. */
  2183. void reset(void) {
  2184. chMBReset(&mb);
  2185. }
  2186. /**
  2187. * @brief Terminates the reset state.
  2188. *
  2189. * @xclass
  2190. */
  2191. void resumeX(void) {
  2192. chMBResumeX(&mb);
  2193. }
  2194. /**
  2195. * @brief Posts a message into a mailbox.
  2196. * @details The invoking thread waits until a empty slot in the mailbox
  2197. * becomes available or the specified time runs out.
  2198. *
  2199. * @param[in] msg the message to be posted on the mailbox
  2200. * @param[in] timeout the number of ticks before the operation timeouts,
  2201. * the following special values are allowed:
  2202. * - @a TIME_IMMEDIATE immediate timeout.
  2203. * - @a TIME_INFINITE no timeout.
  2204. * .
  2205. * @return The operation status.
  2206. * @retval MSG_OK if a message has been correctly posted.
  2207. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2208. * @retval MSG_TIMEOUT if the operation has timed out.
  2209. *
  2210. * @api
  2211. */
  2212. msg_t post(T msg, sysinterval_t timeout) {
  2213. return chMBPostTimeout(&mb, reinterpret_cast<msg_t>(msg), timeout);
  2214. }
  2215. /**
  2216. * @brief Posts a message into a mailbox.
  2217. * @details The invoking thread waits until a empty slot in the mailbox
  2218. * becomes available or the specified time runs out.
  2219. *
  2220. * @param[in] msg the message to be posted on the mailbox
  2221. * @param[in] timeout the number of ticks before the operation timeouts,
  2222. * the following special values are allowed:
  2223. * - @a TIME_IMMEDIATE immediate timeout.
  2224. * - @a TIME_INFINITE no timeout.
  2225. * .
  2226. * @return The operation status.
  2227. * @retval MSG_OK if a message has been correctly posted.
  2228. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2229. * @retval MSG_TIMEOUT if the operation has timed out.
  2230. *
  2231. * @sclass
  2232. */
  2233. msg_t postS(T msg, sysinterval_t timeout) {
  2234. return chMBPostTimeoutS(&mb, reinterpret_cast<msg_t>(msg), timeout);
  2235. }
  2236. /**
  2237. * @brief Posts a message into a mailbox.
  2238. * @details This variant is non-blocking, the function returns a timeout
  2239. * condition if the queue is full.
  2240. *
  2241. * @param[in] msg the message to be posted on the mailbox
  2242. * @return The operation status.
  2243. * @retval MSG_OK if a message has been correctly posted.
  2244. * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
  2245. * posted.
  2246. *
  2247. * @iclass
  2248. */
  2249. msg_t postI(T msg) {
  2250. return chMBPostI(&mb, reinterpret_cast<msg_t>(msg));
  2251. }
  2252. /**
  2253. * @brief Posts an high priority message into a mailbox.
  2254. * @details The invoking thread waits until a empty slot in the mailbox
  2255. * becomes available or the specified time runs out.
  2256. *
  2257. * @param[in] msg the message to be posted on the mailbox
  2258. * @param[in] timeout the number of ticks before the operation timeouts,
  2259. * the following special values are allowed:
  2260. * - @a TIME_IMMEDIATE immediate timeout.
  2261. * - @a TIME_INFINITE no timeout.
  2262. * .
  2263. * @return The operation status.
  2264. * @retval MSG_OK if a message has been correctly posted.
  2265. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2266. * @retval MSG_TIMEOUT if the operation has timed out.
  2267. *
  2268. * @api
  2269. */
  2270. msg_t postAhead(T msg, sysinterval_t timeout) {
  2271. return chMBPostAheadTimeout(&mb, reinterpret_cast<msg_t>(msg), timeout);
  2272. }
  2273. /**
  2274. * @brief Posts an high priority message into a mailbox.
  2275. * @details The invoking thread waits until a empty slot in the mailbox
  2276. * becomes available or the specified time runs out.
  2277. *
  2278. * @param[in] msg the message to be posted on the mailbox
  2279. * @param[in] timeout the number of ticks before the operation timeouts,
  2280. * the following special values are allowed:
  2281. * - @a TIME_IMMEDIATE immediate timeout.
  2282. * - @a TIME_INFINITE no timeout.
  2283. * .
  2284. * @return The operation status.
  2285. * @retval MSG_OK if a message has been correctly posted.
  2286. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2287. * @retval MSG_TIMEOUT if the operation has timed out.
  2288. *
  2289. * @sclass
  2290. */
  2291. msg_t postAheadS(T msg, sysinterval_t timeout) {
  2292. return chMBPostAheadTimeoutS(&mb, reinterpret_cast<msg_t>(msg), timeout);
  2293. }
  2294. /**
  2295. * @brief Posts an high priority message into a mailbox.
  2296. * @details This variant is non-blocking, the function returns a timeout
  2297. * condition if the queue is full.
  2298. *
  2299. * @param[in] msg the message to be posted on the mailbox
  2300. * @return The operation status.
  2301. * @retval MSG_OK if a message has been correctly posted.
  2302. * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
  2303. * posted.
  2304. *
  2305. * @iclass
  2306. */
  2307. msg_t postAheadI(T msg) {
  2308. return chMBPostAheadI(&mb, reinterpret_cast<msg_t>(msg));
  2309. }
  2310. /**
  2311. * @brief Retrieves a message from a mailbox.
  2312. * @details The invoking thread waits until a message is posted in the
  2313. * mailbox or the specified time runs out.
  2314. *
  2315. * @param[out] msgp pointer to a message variable for the received
  2316. * @param[in] timeout message the number of ticks before the operation
  2317. * timeouts, the following special values are allowed:
  2318. * - @a TIME_IMMEDIATE immediate timeout.
  2319. * - @a TIME_INFINITE no timeout.
  2320. * .
  2321. * @return The operation status.
  2322. * @retval MSG_OK if a message has been correctly fetched.
  2323. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2324. * @retval MSG_TIMEOUT if the operation has timed out.
  2325. *
  2326. * @api
  2327. */
  2328. msg_t fetch(T *msgp, sysinterval_t timeout) {
  2329. return chMBFetchTimeout(&mb, reinterpret_cast<msg_t*>(msgp), timeout);
  2330. }
  2331. /**
  2332. * @brief Retrieves a message from a mailbox.
  2333. * @details The invoking thread waits until a message is posted in the
  2334. * mailbox or the specified time runs out.
  2335. *
  2336. * @param[out] msgp pointer to a message variable for the received
  2337. * @param[in] timeout message the number of ticks before the operation
  2338. * timeouts, the following special values are allowed:
  2339. * - @a TIME_IMMEDIATE immediate timeout.
  2340. * - @a TIME_INFINITE no timeout.
  2341. * .
  2342. * @return The operation status.
  2343. * @retval MSG_OK if a message has been correctly fetched.
  2344. * @retval MSG_RESET if the mailbox has been reset while waiting.
  2345. * @retval MSG_TIMEOUT if the operation has timed out.
  2346. *
  2347. * @sclass
  2348. */
  2349. msg_t fetchS(T *msgp, sysinterval_t timeout) {
  2350. return chMBFetchTimeoutS(&mb, reinterpret_cast<msg_t*>(msgp), timeout);
  2351. }
  2352. /**
  2353. * @brief Retrieves a message from a mailbox.
  2354. * @details This variant is non-blocking, the function returns a timeout
  2355. * condition if the queue is empty.
  2356. *
  2357. * @param[out] msgp pointer to a message variable for the received
  2358. * message
  2359. * @return The operation status.
  2360. * @retval MSG_OK if a message has been correctly fetched.
  2361. * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be
  2362. * fetched.
  2363. *
  2364. * @iclass
  2365. */
  2366. msg_t fetchI(T *msgp) {
  2367. return chMBFetchI(&mb, reinterpret_cast<msg_t*>(msgp));
  2368. }
  2369. /**
  2370. * @brief Returns the next message in the queue without removing it.
  2371. * @pre A message must be waiting in the queue for this function to work
  2372. * or it would return garbage. The correct way to use this macro is
  2373. * to use @p getUsedCountI() and then use this macro, all within
  2374. * a lock state.
  2375. *
  2376. * @return The next message in queue.
  2377. *
  2378. * @iclass
  2379. */
  2380. T peekI(const mailbox_t *mbp) const {
  2381. return chMBPeekI(&mb);
  2382. }
  2383. /**
  2384. * @brief Returns the number of free message slots into a mailbox.
  2385. * @note Can be invoked in any system state but if invoked out of a
  2386. * locked state then the returned value may change after reading.
  2387. * @note The returned value can be less than zero when there are waiting
  2388. * threads on the internal semaphore.
  2389. *
  2390. * @return The number of empty message slots.
  2391. *
  2392. * @iclass
  2393. */
  2394. cnt_t getFreeCountI(void) const {
  2395. return chMBGetFreeCountI(&mb);
  2396. }
  2397. /**
  2398. * @brief Returns the number of used message slots into a mailbox.
  2399. * @note Can be invoked in any system state but if invoked out of a
  2400. * locked state then the returned value may change after reading.
  2401. * @note The returned value can be less than zero when there are waiting
  2402. * threads on the internal semaphore.
  2403. *
  2404. * @return The number of queued messages.
  2405. *
  2406. * @iclass
  2407. */
  2408. cnt_t getUsedCountI(void) const {
  2409. return chMBGetUsedCountI(&mb);
  2410. }
  2411. };
  2412. /*------------------------------------------------------------------------*
  2413. * chibios_rt::Mailbox *
  2414. *------------------------------------------------------------------------*/
  2415. /**
  2416. * @brief Template class encapsulating a mailbox and its messages buffer.
  2417. *
  2418. * @param N length of the mailbox buffer
  2419. */
  2420. template <typename T, int N>
  2421. class Mailbox : public MailboxBase<T> {
  2422. static_assert(sizeof(T) <= sizeof(msg_t),
  2423. "Mailbox type does not fit in msg_t");
  2424. private:
  2425. msg_t mb_buf[N];
  2426. public:
  2427. /**
  2428. * @brief Mailbox constructor.
  2429. *
  2430. * @init
  2431. */
  2432. Mailbox(void) :
  2433. MailboxBase<T>(mb_buf, (cnt_t)(sizeof mb_buf / sizeof (msg_t))) {
  2434. }
  2435. };
  2436. #endif /* CH_CFG_USE_MAILBOXES == TRUE */
  2437. #if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
  2438. /*------------------------------------------------------------------------*
  2439. * chibios_rt::MemoryPool *
  2440. *------------------------------------------------------------------------*/
  2441. /**
  2442. * @brief Class encapsulating a memory pool.
  2443. */
  2444. class MemoryPool {
  2445. /**
  2446. * @brief Embedded @p memory_pool_t structure.
  2447. */
  2448. memory_pool_t pool;
  2449. public:
  2450. /**
  2451. * @brief MemoryPool constructor.
  2452. *
  2453. * @param[in] size the size of the objects contained in this memory
  2454. * pool, the minimum accepted size is the size of
  2455. * a pointer to void.
  2456. * @param[in] provider memory provider function for the memory pool or
  2457. * @p nullptr if the pool is not allowed to grow
  2458. * automatically
  2459. *
  2460. * @init
  2461. */
  2462. MemoryPool(size_t size, memgetfunc_t provider=0) : pool() {
  2463. chPoolObjectInit(&pool, size, provider);
  2464. }
  2465. /**
  2466. * @brief MemoryPool constructor.
  2467. *
  2468. * @param[in] size the size of the objects contained in this memory
  2469. * pool, the minimum accepted size is the size of
  2470. * a pointer to void.
  2471. * @param[in] provider memory provider function for the memory pool or
  2472. * @p nullptr if the pool is not allowed to grow
  2473. * automatically
  2474. * @param[in] p pointer to the array first element
  2475. * @param[in] n number of elements in the array
  2476. *
  2477. * @init
  2478. */
  2479. MemoryPool(size_t size, void* p, size_t n,
  2480. memgetfunc_t provider=0) : pool() {
  2481. chPoolObjectInit(&pool, size, provider);
  2482. chPoolLoadArray(&pool, p, n);
  2483. }
  2484. /* Prohibit copy construction and assignment, but allow move.*/
  2485. MemoryPool(const MemoryPool &) = delete;
  2486. MemoryPool &operator=(const MemoryPool &) = delete;
  2487. MemoryPool(MemoryPool &&) = default;
  2488. MemoryPool &operator=(MemoryPool &&) = default;
  2489. /**
  2490. * @brief Loads a memory pool with an array of static objects.
  2491. * @pre The memory pool must be already been initialized.
  2492. * @pre The array elements must be of the right size for the specified
  2493. * memory pool.
  2494. * @post The memory pool contains the elements of the input array.
  2495. *
  2496. * @param[in] p pointer to the array first element
  2497. * @param[in] n number of elements in the array
  2498. *
  2499. * @api
  2500. */
  2501. void loadArray(void *p, size_t n) {
  2502. chPoolLoadArray(&pool, p, n);
  2503. }
  2504. /**
  2505. * @brief Allocates an object from a memory pool.
  2506. * @pre The memory pool must be already been initialized.
  2507. *
  2508. * @return The pointer to the allocated object.
  2509. * @retval nullptr if pool is empty.
  2510. *
  2511. * @iclass
  2512. */
  2513. void *allocI(void) {
  2514. return chPoolAllocI(&pool);
  2515. }
  2516. /**
  2517. * @brief Allocates an object from a memory pool.
  2518. * @pre The memory pool must be already been initialized.
  2519. *
  2520. * @return The pointer to the allocated object.
  2521. * @retval nullptr if pool is empty.
  2522. *
  2523. * @api
  2524. */
  2525. void *alloc(void) {
  2526. return chPoolAlloc(&pool);
  2527. }
  2528. /**
  2529. * @brief Releases an object into a memory pool.
  2530. * @pre The memory pool must be already been initialized.
  2531. * @pre The freed object must be of the right size for the specified
  2532. * memory pool.
  2533. * @pre The object must be properly aligned to contain a pointer to
  2534. * void.
  2535. *
  2536. * @param[in] objp the pointer to the object to be released
  2537. *
  2538. * @iclass
  2539. */
  2540. void free(void *objp) {
  2541. chPoolFree(&pool, objp);
  2542. }
  2543. /**
  2544. * @brief Adds an object to a memory pool.
  2545. * @pre The memory pool must be already been initialized.
  2546. * @pre The added object must be of the right size for the specified
  2547. * memory pool.
  2548. * @pre The added object must be memory aligned to the size of
  2549. * @p stkalign_t type.
  2550. * @note This function is just an alias for @p chPoolFree() and has been
  2551. * added for clarity.
  2552. *
  2553. * @param[in] objp the pointer to the object to be added
  2554. *
  2555. * @iclass
  2556. */
  2557. void freeI(void *objp) {
  2558. chPoolFreeI(&pool, objp);
  2559. }
  2560. };
  2561. /*------------------------------------------------------------------------*
  2562. * chibios_rt::ObjectsPool *
  2563. *------------------------------------------------------------------------*/
  2564. /**
  2565. * @brief Template class encapsulating a memory pool and its elements.
  2566. */
  2567. template<class T, size_t N>
  2568. class ObjectsPool : public MemoryPool {
  2569. /* The buffer is declared as an array of pointers to void for two
  2570. reasons:
  2571. 1) The objects must be properly aligned to hold a pointer as
  2572. first field.
  2573. 2) Objects are dirtied when loaded in the pool.*/
  2574. void *pool_buf[(N * sizeof (T)) / sizeof (void *)];
  2575. public:
  2576. /**
  2577. * @brief ObjectsPool constructor.
  2578. *
  2579. * @init
  2580. */
  2581. ObjectsPool(void) : MemoryPool(sizeof (T), nullptr) {
  2582. loadArray(pool_buf, N);
  2583. }
  2584. };
  2585. /*------------------------------------------------------------------------*
  2586. * chibios_rt::ThreadsPool *
  2587. *------------------------------------------------------------------------*/
  2588. /**
  2589. * @brief Template class encapsulating a pool of threads.
  2590. */
  2591. template<size_t S, size_t N, const char *C>
  2592. class ThreadsPool : public BaseDynamicThread {
  2593. THD_WORKING_AREA(working_areas, S)[N];
  2594. MemoryPool threads_pool;
  2595. public:
  2596. /**
  2597. * @brief ThreadsPool constructor.
  2598. *
  2599. * @init
  2600. */
  2601. ThreadsPool(void) : threads_pool(THD_WORKING_AREA_SIZE(S)) {
  2602. threads_pool.loadArray(working_areas, N);
  2603. }
  2604. /**
  2605. * @brief Starts a dynamic thread from the pool.
  2606. *
  2607. * @param[in] prio thread priority
  2608. * @return A reference to the created thread with
  2609. * reference counter set to one.
  2610. *
  2611. * @api
  2612. */
  2613. ThreadReference start(tprio_t prio) override {
  2614. void _thd_start(void *arg);
  2615. return ThreadReference(chThdCreateFromMemoryPool(&threads_pool.pool,
  2616. C,
  2617. prio,
  2618. _thd_start,
  2619. this));
  2620. }
  2621. };
  2622. #endif /* CH_CFG_USE_MEMPOOLS == TRUE */
  2623. #if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
  2624. /*------------------------------------------------------------------------*
  2625. * chibios_rt::Heap *
  2626. *------------------------------------------------------------------------*/
  2627. /**
  2628. * @brief Class encapsulating a heap.
  2629. */
  2630. class Heap {
  2631. /**
  2632. * @brief Embedded @p memory_heap_t structure.
  2633. */
  2634. memory_heap_t heap;
  2635. public:
  2636. /**
  2637. * @brief Heap constructor.
  2638. * @pre Both the heap buffer base and the heap size must be aligned to
  2639. * the @p stkalign_t type size.
  2640. *
  2641. * @param[in] buffer heap buffer base
  2642. * @param[in] size the size of the memory area located at \e buffer
  2643. * @init
  2644. */
  2645. Heap(void *buffer, const size_t size) : heap() {
  2646. chHeapObjectInit(&heap, buffer, size);
  2647. }
  2648. /* Prohibit copy construction and assignment, but allow move.*/
  2649. Heap(const Heap &) = delete;
  2650. Heap &operator=(const Heap &) = delete;
  2651. Heap(Heap &&) = default;
  2652. Heap &operator=(Heap &&) = default;
  2653. /**
  2654. * @brief Allocates an object from a heap.
  2655. * @pre The heap must be already been initialized.
  2656. *
  2657. * @return The pointer to the allocated object.
  2658. * @retval nullptr if pool is empty.
  2659. *
  2660. * @api
  2661. */
  2662. void *alloc(const size_t size) {
  2663. return chHeapAlloc(&heap, size);
  2664. }
  2665. /**
  2666. * @brief Releases an object into the heap.
  2667. *
  2668. * @param[in] objp the pointer to the object to be released
  2669. *
  2670. * @api
  2671. */
  2672. void free(void *objp) {
  2673. chHeapFree(objp);
  2674. }
  2675. /**
  2676. * @brief Reports the heap status.
  2677. *
  2678. * @param[out] frag the size of total fragmented free space
  2679. * @param[in] largestp pointer to a variable that will receive the largest
  2680. * free free block found space or @p nullptr
  2681. * @return the number of fragments in the heap
  2682. *
  2683. * @api
  2684. */
  2685. size_t status(size_t &frag, size_t *largestp=0) {
  2686. return chHeapStatus(&heap, &frag, largestp);
  2687. }
  2688. };
  2689. #endif /* CH_CFG_USE_MEMPOOLS == TRUE */
  2690. /*------------------------------------------------------------------------*
  2691. * chibios_rt::BaseSequentialStreamInterface *
  2692. *------------------------------------------------------------------------*/
  2693. /**
  2694. * @brief Interface of a BaseSequentialStream.
  2695. * @note You can cast a BaseSequentialStream to this interface and use
  2696. * it, the memory layout is the same.
  2697. */
  2698. class BaseSequentialStreamInterface {
  2699. public:
  2700. /**
  2701. * @brief Sequential Stream write.
  2702. * @details The function writes data from a buffer to a stream.
  2703. *
  2704. * @param[in] bp pointer to the data buffer
  2705. * @param[in] n the maximum amount of data to be transferred
  2706. * @return The number of bytes transferred. The return value
  2707. * can be less than the specified number of bytes if
  2708. * an end-of-file condition has been met.
  2709. *
  2710. * @api
  2711. */
  2712. virtual size_t write(const uint8_t *bp, const size_t n) = 0;
  2713. /**
  2714. * @brief Sequential Stream read.
  2715. * @details The function reads data from a stream into a buffer.
  2716. *
  2717. * @param[out] bp pointer to the data buffer
  2718. * @param[in] n the maximum amount of data to be transferred
  2719. * @return The number of bytes transferred. The return value
  2720. * can be less than the specified number of bytes if
  2721. * an end-of-file condition has been met.
  2722. *
  2723. * @api
  2724. */
  2725. virtual size_t read(uint8_t *bp, const size_t n) = 0;
  2726. /**
  2727. * @brief Sequential Stream blocking byte write.
  2728. * @details This function writes a byte value to a channel. If the channel
  2729. * is not ready to accept data then the calling thread is
  2730. * suspended.
  2731. *
  2732. * @param[in] b the byte value to be written to the channel
  2733. *
  2734. * @return The operation status.
  2735. * @retval Q_OK if the operation succeeded.
  2736. * @retval Q_RESET if an end-of-file condition has been met.
  2737. *
  2738. * @api
  2739. */
  2740. virtual msg_t put(const uint8_t b) = 0;
  2741. /**
  2742. * @brief Sequential Stream blocking byte read.
  2743. * @details This function reads a byte value from a channel. If the data
  2744. * is not available then the calling thread is suspended.
  2745. *
  2746. * @return A byte value from the queue.
  2747. * @retval Q_RESET if an end-of-file condition has been met.
  2748. *
  2749. * @api
  2750. */
  2751. virtual msg_t get(void) = 0;
  2752. };
  2753. }
  2754. #endif /* _CH_HPP_ */
  2755. /** @} */