qpc.qm 594 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <model version="5.2.5" links="1">
  3. <documentation>QP/C Real-Time Embedded Framework (RTEF)
  4. The model is used to generate the whole QP/C source code.
  5. Copyright (C) 2005 Quantum Leaps, LLC &lt;state-machine.com&gt;.
  6. SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
  7. This software is dual-licensed under the terms of the open source GNU
  8. General Public License version 3 (or any later version), or alternatively,
  9. under the terms of one of the closed source Quantum Leaps commercial
  10. licenses.
  11. The terms of the open source GNU General Public License version 3
  12. can be found at: &lt;www.gnu.org/licenses/gpl-3.0&gt;
  13. The terms of the closed source Quantum Leaps commercial licenses
  14. can be found at: &lt;www.state-machine.com/licensing&gt;
  15. Redistributions in source code must retain this copyright notice.
  16. Plagiarizing this software to sidestep the license obligations is illegal.
  17. Contact information:
  18. &lt;www.state-machine.com/licensing&gt;
  19. &lt;info@state-machine.com&gt;</documentation>
  20. <!--${qpc}-->
  21. <framework name="qpc" license="LICENSES/LicenseRef-QL-dual.qlc"/>
  22. <!--${DbC}-->
  23. <package name="DbC" stereotype="0x05">
  24. <!--${DbC::active}-->
  25. <package name="active" stereotype="0x05">
  26. <!--${DbC::active::Q_DEFINE_THIS_MODULE}-->
  27. <operation name="Q_DEFINE_THIS_MODULE" type="" visibility="0x03" properties="0x00">
  28. <documentation>/*! Define the user-specified module name for assertions in this file.
  29. *
  30. * @details
  31. * Macro to be placed at the top of each C/C++ module to define the
  32. * single instance of the module name string to be used in reporting
  33. * assertions in this module. This macro takes the user-supplied parameter
  34. * `name_` instead of `__FILE__` to precisely control the name of the
  35. * module.
  36. *
  37. * @param[in] name_ string constant representing the module name
  38. *
  39. * @note
  40. * This macro should **not** be terminated by a semicolon.
  41. */</documentation>
  42. <!--${DbC::active::Q_DEFINE_THIS_MO~::name_}-->
  43. <parameter name="name_" type="char const *"/>
  44. <code>\
  45. static char const Q_this_module_[] = name_;</code>
  46. </operation>
  47. <!--${DbC::active::Q_ASSERT_ID}-->
  48. <operation name="Q_ASSERT_ID" type="void" visibility="0x03" properties="0x00">
  49. <documentation>/*! General-purpose assertion with user-specified ID number.
  50. *
  51. * @details
  52. * Evaluates the Boolean expression `expr_` and does nothing else when
  53. * it evaluates to 'true'. However, when `expr_` evaluates to 'false',
  54. * the Q_ASSERT_ID() macro calls the no-return function Q_onAssert().
  55. *
  56. * @param[in] id_ ID number (unique within the module) of the assertion
  57. * @param[in] expr_ Boolean expression to check
  58. *
  59. * @attention
  60. * When assertions are disabled (by defining the ::Q_NASSERT macro), the
  61. * Q_ASSERT_ID() macro expands to nothing, and consequently the Boolean
  62. * expression `expr_` is **not** evaluated and the callback function
  63. * Q_onAssert() is **not** called.
  64. */</documentation>
  65. <!--${DbC::active::Q_ASSERT_ID::id_}-->
  66. <parameter name="id_" type="int"/>
  67. <!--${DbC::active::Q_ASSERT_ID::expr_}-->
  68. <parameter name="expr_" type="bool"/>
  69. <code>((expr_) \
  70. ? ((void)0) : Q_onAssert(&amp;Q_this_module_[0], (id_)))</code>
  71. </operation>
  72. <!--${DbC::active::Q_ERROR_ID}-->
  73. <operation name="Q_ERROR_ID" type="void" visibility="0x03" properties="0x00">
  74. <documentation>/*! Assertion with user-specified ID for a wrong path through the code
  75. *
  76. * @details
  77. * Calls the Q_onAssert() callback if ever executed. This assertion
  78. * takes the user-supplied parameter `id_` to identify the location of
  79. * this assertion within the file. This avoids the volatility of using
  80. * line numbers, which change whenever a line of code is added or removed
  81. * upstream from the assertion.
  82. *
  83. * @param[in] id_ ID number (unique within the module) of the assertion
  84. *
  85. * @note
  86. * Does noting if assertions are disabled with the ::Q_NASSERT switch.
  87. */</documentation>
  88. <!--${DbC::active::Q_ERROR_ID::id_}-->
  89. <parameter name="id_" type="int"/>
  90. <code>Q_onAssert(&amp;Q_this_module_[0], (id_))</code>
  91. </operation>
  92. <!--${DbC::active::Q_ALLEGE_ID}-->
  93. <operation name="Q_ALLEGE_ID" type="void" visibility="0x03" properties="0x00">
  94. <documentation>/*! General purpose assertion with user-specified ID number that
  95. * **always** evaluates the `expr_` expression.
  96. *
  97. * @details
  98. * Like the Q_ASSERT_ID() macro, except it **always** evaluates the
  99. * `expr_` expression even when assertions are disabled with the
  100. * ::Q_NASSERT macro. However, when the ::Q_NASSERT macro is defined, the
  101. * Q_onAssert() callback is **not** called, even if `expr_` evaluates
  102. * to FALSE.
  103. *
  104. * @param[in] id_ ID number (unique within the module) of the assertion
  105. * @param[in] expr_ Boolean expression to check
  106. */</documentation>
  107. <!--${DbC::active::Q_ALLEGE_ID::id_}-->
  108. <parameter name="id_" type="int"/>
  109. <!--${DbC::active::Q_ALLEGE_ID::expr_}-->
  110. <parameter name="expr_" type="bool"/>
  111. <code>Q_ASSERT_ID((id_), (expr_))</code>
  112. </operation>
  113. </package>
  114. <!--${DbC::inactive}-->
  115. <package name="inactive" stereotype="0x05">
  116. <!--${DbC::inactive::Q_DEFINE_THIS_MODULE}-->
  117. <operation name="Q_DEFINE_THIS_MODULE" type="" visibility="0x03" properties="0x00">
  118. <documentation>/*! inactive version of Q_DEFINE_THIS_MODULE() */</documentation>
  119. <!--${DbC::inactive::Q_DEFINE_THIS_MO~::name_}-->
  120. <parameter name="name_" type="char const *"/>
  121. </operation>
  122. <!--${DbC::inactive::Q_ASSERT_ID}-->
  123. <operation name="Q_ASSERT_ID" type="void" visibility="0x03" properties="0x00">
  124. <documentation>/*! inactive version of Q_ASSERT_ID() */</documentation>
  125. <!--${DbC::inactive::Q_ASSERT_ID::id_}-->
  126. <parameter name="id_" type="int"/>
  127. <!--${DbC::inactive::Q_ASSERT_ID::expr_}-->
  128. <parameter name="expr_" type="bool"/>
  129. <code>((void)0)</code>
  130. </operation>
  131. <!--${DbC::inactive::Q_ERROR_ID}-->
  132. <operation name="Q_ERROR_ID" type="void" visibility="0x03" properties="0x00">
  133. <documentation>/*! inactive version of Q_ERROR_ID() */</documentation>
  134. <!--${DbC::inactive::Q_ERROR_ID::id_}-->
  135. <parameter name="id_" type="int"/>
  136. <code>((void)0)</code>
  137. </operation>
  138. <!--${DbC::inactive::Q_ALLEGE_ID}-->
  139. <operation name="Q_ALLEGE_ID" type="void" visibility="0x03" properties="0x00">
  140. <documentation>/*! inactive version of Q_ALLEGE_ID()
  141. *
  142. * @attention
  143. * The expression `expr_` **is** evaluated, even though assertion
  144. * callback Q_onAssert() is NOT called when `expr_` evaluates to
  145. * false.
  146. */</documentation>
  147. <!--${DbC::inactive::Q_ALLEGE_ID::id_}-->
  148. <parameter name="id_" type="int"/>
  149. <!--${DbC::inactive::Q_ALLEGE_ID::expr_}-->
  150. <parameter name="expr_" type="bool"/>
  151. <code>((void)(expr_))</code>
  152. </operation>
  153. </package>
  154. <!--${DbC::Q_DEFINE_THIS_FILE}-->
  155. <attribute name="Q_DEFINE_THIS_FILE" type="void" visibility="0x03" properties="0x00">
  156. <documentation>/*! Define the file name (with `__FILE__`) for assertions in this file
  157. *
  158. * @details
  159. * Macro to be placed at the top of each C/C++ module to define the
  160. * single instance of the file name string to be used in reporting
  161. * assertions in this module.
  162. *
  163. * @note
  164. * The file name string literal is defined by means of the standard
  165. * preprocessor macro `__FILE__`. However, please note that, depending
  166. * on the compiler, the `__FILE__` macro might contain the whole path name
  167. * to the file, which might be inconvenient to log assertions.
  168. *
  169. * @attention
  170. * This macro should **not** be terminated by a semicolon.
  171. *
  172. * @sa Q_DEFINE_THIS_MODULE()
  173. */</documentation>
  174. <code>Q_DEFINE_THIS_MODULE(__FILE__)</code>
  175. </attribute>
  176. <!--${DbC::Q_ASSERT}-->
  177. <operation name="Q_ASSERT" type="void" visibility="0x03" properties="0x00">
  178. <documentation>/*! General-purpose assertion (with __LINE__ used as location in the file)
  179. *
  180. * @details
  181. * Equivalent to Q_ASSERT_ID(), except it uses __LINE__ to identify the
  182. * assertion within a file.
  183. *
  184. * @param[in] expr_ Boolean expression to check
  185. *
  186. * @sa Q_ASSERT_ID()
  187. */</documentation>
  188. <!--${DbC::Q_ASSERT::expr_}-->
  189. <parameter name="expr_" type="bool"/>
  190. <code>Q_ASSERT_ID(__LINE__, (expr_))</code>
  191. </operation>
  192. <!--${DbC::Q_ERROR}-->
  193. <operation name="Q_ERROR" type="void" visibility="0x03" properties="0x00">
  194. <documentation>/*! Assertion for a wrong path through the code
  195. *
  196. * @details
  197. * Calls the Q_onAssert() callback if ever executed.
  198. *
  199. * @note
  200. * This macro identifies the problem location with the line number,
  201. * which might change as the code is modified.
  202. *
  203. * @sa Q_ERROR_ID()
  204. */</documentation>
  205. <code>Q_ERROR_ID(__LINE__)</code>
  206. </operation>
  207. <!--${DbC::Q_REQUIRE_ID}-->
  208. <operation name="Q_REQUIRE_ID" type="void" visibility="0x03" properties="0x00">
  209. <documentation>/*! Assertion for checking **preconditions**.
  210. *
  211. * @details
  212. * Equivalent to Q_ASSERT_ID(), except the name provides a better
  213. * documentation of the intention of this assertion.
  214. *
  215. * @param[in] id_ ID number (unique within the module) of the assertion
  216. * @param[in] expr_ Boolean expression
  217. */</documentation>
  218. <!--${DbC::Q_REQUIRE_ID::id_}-->
  219. <parameter name="id_" type="int"/>
  220. <!--${DbC::Q_REQUIRE_ID::expr_}-->
  221. <parameter name="expr_" type="bool"/>
  222. <code>Q_ASSERT_ID((id_), (expr_))</code>
  223. </operation>
  224. <!--${DbC::Q_REQUIRE}-->
  225. <operation name="Q_REQUIRE" type="void" visibility="0x03" properties="0x00">
  226. <documentation>/*! Assertion for checking preconditions (based on __LINE__).
  227. *
  228. * @details
  229. * Equivalent to Q_ASSERT(), except the name provides a better documentation
  230. * of the intention of this assertion.
  231. *
  232. * @param[in] expr_ Boolean expression
  233. */</documentation>
  234. <!--${DbC::Q_REQUIRE::expr_}-->
  235. <parameter name="expr_" type="bool"/>
  236. <code>Q_ASSERT(expr_)</code>
  237. </operation>
  238. <!--${DbC::Q_ENSURE_ID}-->
  239. <operation name="Q_ENSURE_ID" type="void" visibility="0x03" properties="0x00">
  240. <documentation>/*! Assertion for checking postconditions.
  241. *
  242. * @details
  243. * Equivalent to Q_ASSERT_ID(), except the name provides a better documentation
  244. * of the intention of this assertion.
  245. *
  246. * @param[in] id_ ID number (unique within the module) of the assertion
  247. * @param[in] expr_ Boolean expression
  248. */</documentation>
  249. <!--${DbC::Q_ENSURE_ID::id_}-->
  250. <parameter name="id_" type="int"/>
  251. <!--${DbC::Q_ENSURE_ID::expr_}-->
  252. <parameter name="expr_" type="bool"/>
  253. <code>Q_ASSERT_ID((id_), (expr_))</code>
  254. </operation>
  255. <!--${DbC::Q_ENSURE}-->
  256. <operation name="Q_ENSURE" type="void" visibility="0x03" properties="0x00">
  257. <documentation>/*! Assertion for checking postconditions.
  258. *
  259. * @details
  260. * Equivalent to Q_ASSERT(), except the name provides a better documentation
  261. * of the intention of this assertion.
  262. *
  263. * @param[in] expr_ Boolean expression
  264. */</documentation>
  265. <!--${DbC::Q_ENSURE::expr_}-->
  266. <parameter name="expr_" type="bool"/>
  267. <code>Q_ASSERT(expr_)</code>
  268. </operation>
  269. <!--${DbC::Q_INVARIANT_ID}-->
  270. <operation name="Q_INVARIANT_ID" type="void" visibility="0x03" properties="0x00">
  271. <documentation>/*! Assertion for checking invariants.
  272. *
  273. * @details
  274. * Equivalent to Q_ASSERT_ID(), except the name provides a better
  275. * documentation of the intention of this assertion.
  276. *
  277. * @param[in] id_ ID number (unique within the module) of the assertion
  278. * @param[in] expr_ Boolean expression
  279. */</documentation>
  280. <!--${DbC::Q_INVARIANT_ID::id_}-->
  281. <parameter name="id_" type="int"/>
  282. <!--${DbC::Q_INVARIANT_ID::expr_}-->
  283. <parameter name="expr_" type="bool"/>
  284. <code>Q_ASSERT_ID((id_), (expr_))</code>
  285. </operation>
  286. <!--${DbC::Q_INVARIANT}-->
  287. <operation name="Q_INVARIANT" type="void" visibility="0x03" properties="0x00">
  288. <documentation>/*! Assertion for checking invariants.
  289. *
  290. * @details
  291. * Equivalent to Q_ASSERT(), except the name provides a better documentation
  292. * of the intention of this assertion.
  293. *
  294. * @param[in] expr_ Boolean expression
  295. */</documentation>
  296. <!--${DbC::Q_INVARIANT::expr_}-->
  297. <parameter name="expr_" type="bool"/>
  298. <code>Q_ASSERT(expr_)</code>
  299. </operation>
  300. <!--${DbC::Q_ALLEGE}-->
  301. <operation name="Q_ALLEGE" type="void" visibility="0x03" properties="0x00">
  302. <documentation>/*! General purpose assertion with user-specified ID number that
  303. * **always** evaluates the `expr_` expression.
  304. *
  305. * @details
  306. * Equivalent to Q_ALLEGE_ID(), except it identifies the problem location
  307. * with the line number `__LINE__`, which might change as the code is modified.
  308. *
  309. * @param[in] expr_ Boolean expression to check
  310. *
  311. * @sa Q_ALLEGE_ID()
  312. */</documentation>
  313. <!--${DbC::Q_ALLEGE::expr_}-->
  314. <parameter name="expr_" type="bool"/>
  315. <code>Q_ALLEGE_ID(__LINE__, (expr_))</code>
  316. </operation>
  317. <!--${DbC::Q_ASSERT_STATIC}-->
  318. <operation name="Q_ASSERT_STATIC" type="void" visibility="0x03" properties="0x00">
  319. <documentation>/*! Static (compile-time) assertion.
  320. *
  321. * @details
  322. * This type of assertion deliberately causes a compile-time error when
  323. * the `expr_` Boolean expression evaluates to FALSE. The macro exploits
  324. * the fact that in C/C++ a dimension of an array cannot be negative.
  325. * The compile-time assertion has no runtime side effects.
  326. *
  327. * @param[in] expr_ Compile-time Boolean expression
  328. *
  329. * @note
  330. * The static assertion macro is provided for backwards compatibility with
  331. * older C standards. Newer C11 supports `_Static_assert()`, which should
  332. * be used instead of Q_ASSERT_STATIC().
  333. */</documentation>
  334. <!--${DbC::Q_ASSERT_STATIC::expr_}-->
  335. <parameter name="expr_" type="bool"/>
  336. <code>extern char Q_static_assert_[(expr_) ? 1 : -1]</code>
  337. </operation>
  338. <!--${DbC::Q_NORETURN}-->
  339. <attribute name="Q_NORETURN?ndef Q_NORETURN" type="void" visibility="0x03" properties="0x00">
  340. <documentation>/*! No-return function specifier for the Q_onAssert() callback function.
  341. *
  342. * @details
  343. * If the `Q_NORETURN` macro is undefined, the default definition uses
  344. * the C99 specifier `_Noreturn`.
  345. *
  346. * @note
  347. * The `Q_NORETURN` macro can be defined in the QP port (typically in
  348. * `qep_port.h` or `qep_port.hpp`). If such definition is porvided
  349. * the default won't be used.
  350. *
  351. * @trace
  352. * @tr{PQA01_4}
  353. */</documentation>
  354. <code>_Noreturn void</code>
  355. </attribute>
  356. <!--${DbC::int_t}-->
  357. <attribute name="int_t?ndef QP_VERSION" type="typedef int" visibility="0x04" properties="0x00">
  358. <documentation>/*! typedef for assertions-ids and line numbers in assertions.
  359. *
  360. * @details
  361. * This typedef specifies integer type for exclusive use in assertions.
  362. * Use of this type, rather than plain 'int', is in compliance
  363. * with the MISRA-C 2012 Dir 4.6 (adv).
  364. */</documentation>
  365. </attribute>
  366. <!--${DbC::Q_onAssert}-->
  367. <operation name="Q_onAssert" type="Q_NORETURN" visibility="0x00" properties="0x00">
  368. <documentation>/*! Callback function invoked in case of an assertion failure.
  369. *
  370. * @details
  371. * This callback function needs to be defined in the application to perform
  372. * any corrective action after a non-recoverable error has been detected.
  373. * The Q_onAssert() function is the last line of defense after the
  374. * system failure and its implementation shouild be very **carefully**
  375. * designed and **tested** under various fault conditions, including but
  376. * not limited to: stack overflow, stack corruption, or calling Q_onAssert()
  377. * from an interrupt.
  378. *
  379. * @param[in] module name of the file/module in which the assertion failed
  380. * (constant, zero-terminated C string)
  381. * @param[in] location location of the assertion within the module. This could
  382. * be a line number or a user-specified ID-number.
  383. *
  384. * @returns
  385. * This callback function should **not return** (see ::Q_NORETURN),
  386. * as continuation after an assertion failure does not make sense.
  387. *
  388. * @note
  389. * During debugging, Q_onAssert() is an ideal place to put a breakpoint.
  390. * For deployment, tt is typically a **bad idea** to implement Q_onAssert()
  391. * as an endless loop that ties up the CPU (denial of service).
  392. *
  393. * Called by the following: Q_ASSERT_ID(), Q_ERROR_ID(), Q_REQUIRE_ID(),
  394. * Q_ENSURE_ID(), Q_INVARIANT_ID() and Q_ALLEGE_ID() as well as:
  395. * Q_ASSERT(), Q_ERROR(), Q_REQUIRE(), Q_ENSURE(), Q_INVARIANT(),
  396. * and Q_ALLEGE().
  397. *
  398. * @trace
  399. * @tr{PQA01_4}
  400. */</documentation>
  401. <!--${DbC::Q_onAssert::module}-->
  402. <parameter name="module" type="char const *"/>
  403. <!--${DbC::Q_onAssert::location}-->
  404. <parameter name="location" type="int_t"/>
  405. </operation>
  406. <!--${DbC::Q_DIM}-->
  407. <operation name="Q_DIM?ndef QP_VERSION" type="unsigned" visibility="0x03" properties="0x00">
  408. <documentation>/*! Helper macro to calculate static dimension of a 1-dim `array_`
  409. *
  410. * @param array_ 1-dimensional array
  411. * @returns the length of the array (number of elements it can hold)
  412. */</documentation>
  413. <!--${DbC::Q_DIM::array_}-->
  414. <parameter name="array_" type="1-dimensional array"/>
  415. <code>(sizeof(array_) / sizeof((array_)[0U]))</code>
  416. </operation>
  417. </package>
  418. <!--${glob-types}-->
  419. <package name="glob-types" stereotype="0x00">
  420. <!--${glob-types::int_t}-->
  421. <attribute name="int_t" type="typedef int" visibility="0x04" properties="0x00">
  422. <documentation>/*! alias for line numbers in assertions and return from QF_run() */</documentation>
  423. </attribute>
  424. <!--${glob-types::enum_t}-->
  425. <attribute name="enum_t" type="typedef int" visibility="0x04" properties="0x00">
  426. <documentation>/*! alias for enumerations used for event signals */</documentation>
  427. </attribute>
  428. <!--${glob-types::float32_t}-->
  429. <attribute name="float32_t" type="typedef float" visibility="0x04" properties="0x00">
  430. <documentation>/*! alias for IEEE 754 32-bit floating point number,
  431. * MISRA-C 2012 Dir 4.6(A)
  432. *
  433. * @note
  434. * QP does not use floating-point types anywhere in the internal
  435. * implementation, except in QS software tracing, where utilities for
  436. * output of floating-point numbers are provided for application-specific
  437. * trace records.
  438. */</documentation>
  439. </attribute>
  440. <!--${glob-types::float64_t}-->
  441. <attribute name="float64_t" type="typedef double" visibility="0x04" properties="0x00">
  442. <documentation>/*! alias for IEEE 754 64-bit floating point number,
  443. * MISRA-C 2012 Dir 4.6(A)
  444. *
  445. * @note
  446. * QP does not use floating-point types anywhere in the internal
  447. * implementation, except in QS software tracing, where utilities for
  448. * output of floating-point numbers are provided for application-specific
  449. * trace records.
  450. */</documentation>
  451. </attribute>
  452. </package>
  453. <!--${QEP-config}-->
  454. <package name="QEP-config" stereotype="0x02">
  455. <!--${QEP-config::Q_SIGNAL_SIZE}-->
  456. <attribute name="Q_SIGNAL_SIZE?ndef Q_SIGNAL_SIZE" type="" visibility="0x03" properties="0x00">
  457. <documentation>/*! The size (in bytes) of the signal of an event. Valid values:
  458. * 1U, 2U, or 4U; default 2U
  459. *
  460. * @details
  461. * This macro can be defined in the QEP port file (qep_port.h) to
  462. * configure the ::QSignal type. When the macro is not defined, the
  463. * default of 2 bytes is applied.
  464. */</documentation>
  465. <code>2U</code>
  466. </attribute>
  467. </package>
  468. <!--${QEP-macros}-->
  469. <package name="QEP-macros" stereotype="0x02">
  470. <!--${QEP-macros::QHSM_INIT}-->
  471. <operation name="QHSM_INIT?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  472. <documentation>/*! Virtual call to the top-most initial transition in a HSM.
  473. *
  474. * @param[in,out] me_ current instance pointer (see @ref oop)
  475. * @param[in] par_ pointer the optional initialization parameter
  476. * @param[in] qs_id_ QS local filter ID (used only when Q_SPY is defined)
  477. *
  478. * @note Must be called only ONCE after the SM &quot;constructor&quot;.
  479. *
  480. * @trace
  481. * @tr{RQP102}
  482. *
  483. * @usage
  484. * The following example illustrates how to initialize a SM, and dispatch
  485. * events to it:
  486. * @include qep_qhsm_use.c
  487. */</documentation>
  488. <!--${QEP-macros::QHSM_INIT::me_}-->
  489. <parameter name="me_" type="&lt;QHsm subclass*&gt;"/>
  490. <!--${QEP-macros::QHSM_INIT::par_}-->
  491. <parameter name="par_" type="void *"/>
  492. <!--${QEP-macros::QHSM_INIT::qs_id_}-->
  493. <parameter name="qs_id_" type="uint8_t"/>
  494. <code>do { \
  495. Q_ASSERT((me_)-&gt;vptr); \
  496. (*(me_)-&gt;vptr-&gt;init)((me_), (par_), (qs_id_)); \
  497. } while (false)</code>
  498. </operation>
  499. <!--${QEP-macros::QHSM_INIT}-->
  500. <operation name="QHSM_INIT?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  501. <!--${QEP-macros::QHSM_INIT::me_}-->
  502. <parameter name="me_" type="&lt;QHsm subclass*&gt;"/>
  503. <!--${QEP-macros::QHSM_INIT::par_}-->
  504. <parameter name="par_" type="void *"/>
  505. <!--${QEP-macros::QHSM_INIT::dummy}-->
  506. <parameter name="dummy" type=""/>
  507. <code>do { \
  508. Q_ASSERT((me_)-&gt;vptr); \
  509. (*(me_)-&gt;vptr-&gt;init)((me_), (par_), 0U); \
  510. } while (false)</code>
  511. </operation>
  512. <!--${QEP-macros::QHSM_DISPATCH}-->
  513. <operation name="QHSM_DISPATCH?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  514. <documentation>/*! Virtual call to dispatch an event to a HSM
  515. *
  516. * @details
  517. * Processes one event at a time in Run-to-Completion fashion.
  518. *
  519. * @param[in,out] me_ current instance pointer (see @ref oop)
  520. * @param[in] e_ constant pointer the ::QEvt or a class
  521. * derived from ::QEvt (see @ref oop)
  522. * @param[in] qs_id_ QS local filter ID (used only when Q_SPY is defined)
  523. *
  524. * @note Must be called after the &quot;constructor&quot; and after QHSM_INIT().
  525. *
  526. * @trace
  527. * @tr{RQP102}
  528. */</documentation>
  529. <!--${QEP-macros::QHSM_DISPATCH::me_}-->
  530. <parameter name="me_" type="&lt;QHsm subclass*&gt;"/>
  531. <!--${QEP-macros::QHSM_DISPATCH::e_}-->
  532. <parameter name="e_" type="QEvt *"/>
  533. <!--${QEP-macros::QHSM_DISPATCH::qs_id_}-->
  534. <parameter name="qs_id_" type="uint8_t"/>
  535. <code>\
  536. ((*(me_)-&gt;vptr-&gt;dispatch)((me_), (e_), (qs_id_)))</code>
  537. </operation>
  538. <!--${QEP-macros::QHSM_DISPATCH}-->
  539. <operation name="QHSM_DISPATCH?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  540. <!--${QEP-macros::QHSM_DISPATCH::me_}-->
  541. <parameter name="me_" type="&lt;QHsm subclass*&gt;"/>
  542. <!--${QEP-macros::QHSM_DISPATCH::e_}-->
  543. <parameter name="e_" type="QEvt *"/>
  544. <!--${QEP-macros::QHSM_DISPATCH::dummy}-->
  545. <parameter name="dummy" type=""/>
  546. <code>\
  547. ((*(me_)-&gt;vptr-&gt;dispatch)((me_), (e_), 0U))</code>
  548. </operation>
  549. <!--${QEP-macros::Q_HSM_UPCAST}-->
  550. <operation name="Q_HSM_UPCAST" type="" visibility="0x03" properties="0x00">
  551. <documentation>/*! Perform upcast from a subclass of ::QHsm to the base class ::QHsm
  552. *
  553. * @details
  554. * Upcasting from a subclass to superclass is a very frequent and **safe**
  555. * operation in object-oriented programming and object-oriented languages
  556. * (such as C++) perform such upcasting automatically. However, OOP is
  557. * implemented in C just as a set of coding conventions (see @ref oop),
  558. * and the C compiler does not &quot;know&quot; that certain types are related by
  559. * inheritance. Therefore for C, the upcast must be performed explicitly.
  560. * Unfortunately, pointer casting violates the advisory MISRA-C 2012
  561. * Rule 11.3(req) &quot;A cast shall not be performed between a pointer to object
  562. * type and a pointer to a different object type&quot;. This macro encapsulates
  563. * this deviation and provides a descriptive name for the reason of this cast.
  564. */</documentation>
  565. <!--${QEP-macros::Q_HSM_UPCAST::ptr_}-->
  566. <parameter name="ptr_" type="&lt;QHsm subclass*&gt;"/>
  567. <code>((QHsm *)(ptr_))</code>
  568. </operation>
  569. <!--${QEP-macros::Q_TRAN}-->
  570. <operation name="Q_TRAN" type="" visibility="0x03" properties="0x00">
  571. <documentation>/*! Perform upcast from a subclass of ::QHsm to the base class ::QHsm
  572. *
  573. * @details
  574. * Upcasting from a subclass to superclass is a very frequent and **safe**
  575. * operation in object-oriented programming and object-oriented languages
  576. * (such as C++) perform such upcasting automatically. However, OOP is
  577. * implemented in C just as a set of coding conventions (see @ref oop),
  578. * and the C compiler does not &quot;know&quot; that certain types are related by
  579. * inheritance. Therefore for C, the upcast must be performed explicitly.
  580. * Unfortunately, pointer casting violates the advisory MISRA-C 2012
  581. * Rule 11.3(req) &quot;A cast shall not be performed between a pointer to object
  582. * type and a pointer to a different object type&quot;. This macro encapsulates
  583. * this deviation and provides a descriptive name for the reason of this cast.
  584. */</documentation>
  585. <!--${QEP-macros::Q_TRAN::target_}-->
  586. <parameter name="target_" type="QStateHandler"/>
  587. <code>\
  588. ((Q_HSM_UPCAST(me))-&gt;temp.fun = Q_STATE_CAST(target_), Q_RET_TRAN)</code>
  589. </operation>
  590. <!--${QEP-macros::Q_TRAN_HIST}-->
  591. <operation name="Q_TRAN_HIST" type="" visibility="0x03" properties="0x00">
  592. <documentation>/*! Macro to call in a state-handler when it executes a transition
  593. * to history. Applicable only to HSMs.
  594. *
  595. * @trace
  596. * @tr{RQP103}, @tr{RQP120H}
  597. *
  598. * @usage
  599. * @include qep_qhist.c
  600. */</documentation>
  601. <!--${QEP-macros::Q_TRAN_HIST::hist_}-->
  602. <parameter name="hist_" type="QStateHandler"/>
  603. <code>\
  604. ((Q_HSM_UPCAST(me))-&gt;temp.fun = (hist_), Q_RET_TRAN_HIST)</code>
  605. </operation>
  606. <!--${QEP-macros::Q_SUPER}-->
  607. <operation name="Q_SUPER" type="" visibility="0x03" properties="0x00">
  608. <documentation>/*! Macro to call in a state-handler when it designates the superstate
  609. * of a given state. Applicable only to ::QHsm subclasses.
  610. *
  611. * @trace
  612. * @tr{RQP103}
  613. *
  614. * @usage
  615. * @include qep_qsuper.c
  616. */</documentation>
  617. <!--${QEP-macros::Q_SUPER::super_}-->
  618. <parameter name="super_" type="QStateHandler"/>
  619. <code>\
  620. ((Q_HSM_UPCAST(me))-&gt;temp.fun = Q_STATE_CAST(super_), Q_RET_SUPER)</code>
  621. </operation>
  622. <!--${QEP-macros::Q_HANDLED}-->
  623. <operation name="Q_HANDLED" type="" visibility="0x03" properties="0x00">
  624. <documentation>/*! Macro to call in a state-handler when it handles an event.
  625. *
  626. * @trace
  627. * @tr{RQP103}, @tr{RQP120B}, @tr{RQP120C}
  628. */</documentation>
  629. <code>(Q_RET_HANDLED)</code>
  630. </operation>
  631. <!--${QEP-macros::Q_UNHANDLED}-->
  632. <operation name="Q_UNHANDLED" type="" visibility="0x03" properties="0x00">
  633. <documentation>/*! Macro to call in a state-handler when it attempts to handle
  634. * an event but a guard condition evaluates to 'false' and there is no other
  635. * explicit way of handling the event. Applicable only to ::QHsm subclasses.
  636. */</documentation>
  637. <code>(Q_RET_UNHANDLED)</code>
  638. </operation>
  639. <!--${QEP-macros::Q_ACTION_NULL}-->
  640. <attribute name="Q_ACTION_NULL" type="void" visibility="0x03" properties="0x00">
  641. <documentation>/*! Macro to provide strictly-typed zero-action to terminate action lists
  642. *! in the transition-action-tables
  643. */</documentation>
  644. <code>((QActionHandler)0)</code>
  645. </attribute>
  646. <!--${QEP-macros::Q_EVT_CAST}-->
  647. <operation name="Q_EVT_CAST" type="&lt;QEvt subclass&gt;*" visibility="0x03" properties="0x00">
  648. <documentation>/*! Perform downcast of an event onto a subclass of ::QEvt `class_`
  649. *
  650. * @details
  651. * This macro encapsulates the downcast of ::QEvt pointers, which violates
  652. * MISRA-C 2012 Rule 11.3(R) &quot;A cast shall not be performed between a
  653. * pointer to object type and a pointer to a different object type&quot;. This
  654. * macro helps to localize this deviation.
  655. *
  656. * @param class_ a subclass of ::QEvt
  657. *
  658. * @trace
  659. * @tr{RQP003}, @tr{PQA11_3}
  660. */</documentation>
  661. <!--${QEP-macros::Q_EVT_CAST::class_}-->
  662. <parameter name="class_" type="&lt;QEvt subclass&gt;"/>
  663. <code>((class_ const *)(e))</code>
  664. </operation>
  665. <!--${QEP-macros::Q_STATE_CAST}-->
  666. <operation name="Q_STATE_CAST" type="QStateHandler" visibility="0x03" properties="0x00">
  667. <documentation>/*! Perform cast to ::QStateHandler.
  668. * @details
  669. * This macro encapsulates the cast of a specific state handler function
  670. * pointer to ::QStateHandler, which violates MISRA:C-2012 Rule 11.1(req)
  671. * &quot;Conversions shall not be performed between a pointer to function and
  672. * any other type&quot;. This macro helps to localize this deviation.
  673. *
  674. * @trace
  675. * @tr{PQP11_1}, @tr{PQA11_1}
  676. *
  677. * @usage
  678. * @include qep_qhsm_ctor.c
  679. */</documentation>
  680. <!--${QEP-macros::Q_STATE_CAST::handler_}-->
  681. <parameter name="handler_" type="&lt;state handler&gt;"/>
  682. <code>((QStateHandler)(handler_))</code>
  683. </operation>
  684. <!--${QEP-macros::Q_ACTION_CAST}-->
  685. <operation name="Q_ACTION_CAST" type="QActionHandler" visibility="0x03" properties="0x00">
  686. <documentation>/*! Perform cast to ::QActionHandler.
  687. * @details
  688. * This macro encapsulates the cast of a specific action handler function
  689. * pointer to ::QActionHandler, which violates MISRA:C-2012 Rule 11.1(R)
  690. * &quot;Conversions shall not be performed between a pointer to function and
  691. * any other type&quot;. This macro helps to localize this deviation.
  692. *
  693. * @trace
  694. * @tr{PQP11_1}, @tr{PQA11_1}
  695. */</documentation>
  696. <!--${QEP-macros::Q_ACTION_CAST::action_}-->
  697. <parameter name="action_" type="&lt;action handler&gt;"/>
  698. <code>((QActionHandler)(action_))</code>
  699. </operation>
  700. <!--${QEP-macros::Q_UNUSED_PAR}-->
  701. <operation name="Q_UNUSED_PAR" type="&lt;param type&gt;" visibility="0x03" properties="0x00">
  702. <documentation>/*! Helper macro to clearly mark unused parameters of functions. */</documentation>
  703. <!--${QEP-macros::Q_UNUSED_PAR::par_}-->
  704. <parameter name="par_" type="&lt;param type&gt;"/>
  705. <code>((void)(par_))</code>
  706. </operation>
  707. <!--${QEP-macros::Q_DIM}-->
  708. <operation name="Q_DIM" type="unsigned" visibility="0x03" properties="0x00">
  709. <documentation>/*! Helper macro to calculate static dimension of a 1-dim `array_`
  710. *
  711. * @param array_ 1-dimensional array
  712. * @returns the length of the array (number of elements it can hold)
  713. */</documentation>
  714. <!--${QEP-macros::Q_DIM::array_}-->
  715. <parameter name="array_" type="1-dimensional array"/>
  716. <code>(sizeof(array_) / sizeof((array_)[0U]))</code>
  717. </operation>
  718. <!--${QEP-macros::Q_UINT2PTR_CAST}-->
  719. <operation name="Q_UINT2PTR_CAST" type="" visibility="0x03" properties="0x00">
  720. <documentation>/*! Perform cast from unsigned integer `uint_` to pointer of type `type_`
  721. *
  722. * @details
  723. * This macro encapsulates the cast to (type_ *), which QP ports or
  724. * application might use to access embedded hardware registers.
  725. * Such uses can trigger PC-Lint &quot;Note 923: cast from int to pointer&quot;
  726. * and this macro helps to encapsulate this deviation.
  727. */</documentation>
  728. <!--${QEP-macros::Q_UINT2PTR_CAST::type_}-->
  729. <parameter name="type_" type=""/>
  730. <!--${QEP-macros::Q_UINT2PTR_CAST::uint_}-->
  731. <parameter name="uint_" type=""/>
  732. <code>((type_ *)(uint_))</code>
  733. </operation>
  734. <!--${QEP-macros::QEVT_INITIALIZER}-->
  735. <operation name="QEVT_INITIALIZER" type="" visibility="0x03" properties="0x00">
  736. <documentation>/*! Initializer of static constant QEvt instances
  737. *
  738. * @details
  739. * This macro encapsulates the ugly casting of enumerated signals
  740. * to QSignal and constants for QEvt.poolID and QEvt.refCtr_.
  741. */</documentation>
  742. <!--${QEP-macros::QEVT_INITIALIZER::sig_}-->
  743. <parameter name="sig_" type="QSignal"/>
  744. <code>{ (QSignal)(sig_), 0U, 0U }</code>
  745. </operation>
  746. <!--${QEP-macros::QM_ENTRY}-->
  747. <operation name="QM_ENTRY?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  748. <documentation>/*! Macro to call in a QM action-handler when it executes
  749. * an entry action. Applicable only to ::QMsm subclasses.
  750. */</documentation>
  751. <!--${QEP-macros::QM_ENTRY::state_}-->
  752. <parameter name="state_" type="QStateHandler"/>
  753. <code>\
  754. ((Q_HSM_UPCAST(me))-&gt;temp.obj = (state_), Q_RET_ENTRY)</code>
  755. </operation>
  756. <!--${QEP-macros::QM_ENTRY}-->
  757. <operation name="QM_ENTRY?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  758. <!--${QEP-macros::QM_ENTRY::dummy}-->
  759. <parameter name="dummy" type=""/>
  760. <code>(Q_RET_ENTRY)</code>
  761. </operation>
  762. <!--${QEP-macros::QM_EXIT}-->
  763. <operation name="QM_EXIT?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  764. <documentation>/*! Macro to call in a QM action-handler when it executes
  765. * an exit action. Applicable only to ::QMsm subclasses.
  766. */</documentation>
  767. <!--${QEP-macros::QM_EXIT::state_}-->
  768. <parameter name="state_" type="QStateHandler"/>
  769. <code>\
  770. ((Q_HSM_UPCAST(me))-&gt;temp.obj = (state_), Q_RET_EXIT)</code>
  771. </operation>
  772. <!--${QEP-macros::QM_EXIT}-->
  773. <operation name="QM_EXIT?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  774. <!--${QEP-macros::QM_EXIT::dummy}-->
  775. <parameter name="dummy" type=""/>
  776. <code>(Q_RET_EXIT)</code>
  777. </operation>
  778. <!--${QEP-macros::QM_SM_EXIT}-->
  779. <operation name="QM_SM_EXIT" type="void" visibility="0x03" properties="0x00">
  780. <documentation>/*! Macro to call in a QM submachine exit-handler.
  781. * Applicable only to subclasses of ::QMsm.
  782. */</documentation>
  783. <!--${QEP-macros::QM_SM_EXIT::state_}-->
  784. <parameter name="state_" type="QStateHandler"/>
  785. <code>\
  786. ((Q_HSM_UPCAST(me))-&gt;temp.obj = (state_), Q_RET_EXIT)</code>
  787. </operation>
  788. <!--${QEP-macros::QM_TRAN}-->
  789. <operation name="QM_TRAN" type="void" visibility="0x03" properties="0x00">
  790. <documentation>/*! Macro to call in a QM state-handler when it executes a regular
  791. * transition. Applicable only to ::QMsm subclasses.
  792. */</documentation>
  793. <!--${QEP-macros::QM_TRAN::tatbl_}-->
  794. <parameter name="tatbl_" type="QMTranActionTable const *"/>
  795. <code>((Q_HSM_UPCAST(me))-&gt;temp.tatbl \
  796. = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN)</code>
  797. </operation>
  798. <!--${QEP-macros::QM_TRAN_INIT}-->
  799. <operation name="QM_TRAN_INIT" type="void" visibility="0x03" properties="0x00">
  800. <documentation>/*! Macro to call in a QM state-handler when it executes an initial
  801. * transition. Applicable only to ::QMsm subclasses.
  802. */</documentation>
  803. <!--${QEP-macros::QM_TRAN_INIT::tatbl_}-->
  804. <parameter name="tatbl_" type="QMTranActionTable const *"/>
  805. <code>((Q_HSM_UPCAST(me))-&gt;temp.tatbl \
  806. = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN_INIT)</code>
  807. </operation>
  808. <!--${QEP-macros::QM_TRAN_HIST}-->
  809. <operation name="QM_TRAN_HIST" type="void" visibility="0x03" properties="0x00">
  810. <documentation>/*! Macro to call in a QM state-handler when it executes a transition
  811. * to history. Applicable only to ::QMsm subclasses.
  812. */</documentation>
  813. <!--${QEP-macros::QM_TRAN_HIST::history_}-->
  814. <parameter name="history_" type="QStateHandler"/>
  815. <!--${QEP-macros::QM_TRAN_HIST::tatbl_}-->
  816. <parameter name="tatbl_" type="QMTranActionTable const *"/>
  817. <code>\
  818. ((((Q_HSM_UPCAST(me))-&gt;state.obj = (history_)), \
  819. ((Q_HSM_UPCAST(me))-&gt;temp.tatbl = \
  820. (struct QMTranActTable const *)(tatbl_))), \
  821. Q_RET_TRAN_HIST)</code>
  822. </operation>
  823. <!--${QEP-macros::QM_TRAN_EP}-->
  824. <operation name="QM_TRAN_EP" type="void" visibility="0x03" properties="0x00">
  825. <documentation>/*! Macro to call in a QM state-handler when it executes a transition
  826. * to the submachine via an entry point.
  827. */</documentation>
  828. <!--${QEP-macros::QM_TRAN_EP::tatbl_}-->
  829. <parameter name="tatbl_" type="QMTranActionTable const *"/>
  830. <code>((Q_HSM_UPCAST(me))-&gt;temp.tatbl \
  831. = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN_EP)</code>
  832. </operation>
  833. <!--${QEP-macros::QM_TRAN_XP}-->
  834. <operation name="QM_TRAN_XP" type="void" visibility="0x03" properties="0x00">
  835. <documentation>/*! Macro to call in a QM state-handler when it executes a transition
  836. * to exit point. Applicable only to ::QMsm subclasses.
  837. */</documentation>
  838. <!--${QEP-macros::QM_TRAN_XP::xp_}-->
  839. <parameter name="xp_" type="QStateHandler"/>
  840. <!--${QEP-macros::QM_TRAN_XP::tatbl_}-->
  841. <parameter name="tatbl_" type="QMTranActionTable const *"/>
  842. <code>\
  843. ((((Q_HSM_UPCAST(me))-&gt;state.act = (xp_)), \
  844. ((Q_HSM_UPCAST(me))-&gt;temp.tatbl = \
  845. (struct QMTranActTable const *)(tatbl_))), \
  846. Q_RET_TRAN_XP)</code>
  847. </operation>
  848. <!--${QEP-macros::QM_HANDLED}-->
  849. <operation name="QM_HANDLED" type="" visibility="0x03" properties="0x00">
  850. <documentation>/*! Macro to call in a QM state-handler when it handled an event.
  851. * Applicable only to ::QMsm subclasses.
  852. */</documentation>
  853. <code>(Q_RET_HANDLED)</code>
  854. </operation>
  855. <!--${QEP-macros::QM_UNHANDLED}-->
  856. <operation name="QM_UNHANDLED" type="" visibility="0x03" properties="0x00">
  857. <documentation>/*! Macro to call in a QM state-handler when when it attempts to
  858. * handle an event but a guard condition evaluates to 'false' and there is
  859. * no other explicit way of handling the event. Applicable only to
  860. * ::QMsm subclasses.
  861. */</documentation>
  862. <code>(Q_RET_UNHANDLED)</code>
  863. </operation>
  864. <!--${QEP-macros::QM_SUPER}-->
  865. <operation name="QM_SUPER" type="" visibility="0x03" properties="0x00">
  866. <documentation>/*! Macro to call in a QM state-handler when it designates the
  867. * superstate to handle an event. Applicable only to QMSMs.
  868. */</documentation>
  869. <code>(Q_RET_SUPER)</code>
  870. </operation>
  871. <!--${QEP-macros::QM_SUPER_SUB}-->
  872. <operation name="QM_SUPER_SUB" type="" visibility="0x03" properties="0x00">
  873. <documentation>/*! Macro to call in a QM submachine-handler when it designates the
  874. * host state to handle an event. Applicable only to subclasses of ::QMsm.
  875. */</documentation>
  876. <!--${QEP-macros::QM_SUPER_SUB::host_}-->
  877. <parameter name="host_" type="QStateHandler"/>
  878. <code>\
  879. ((Q_HSM_UPCAST(me))-&gt;temp.obj = (host_), Q_RET_SUPER_SUB)</code>
  880. </operation>
  881. <!--${QEP-macros::QM_STATE_NULL}-->
  882. <attribute name="QM_STATE_NULL" type="" visibility="0x03" properties="0x00">
  883. <documentation>/*! Macro to provide strictly-typed zero-state to use for submachines.
  884. *! Applicable to subclasses of ::QMsm.
  885. */</documentation>
  886. <code>((QMState *)0)</code>
  887. </attribute>
  888. </package>
  889. <!--${QEP}-->
  890. <package name="QEP" stereotype="0x05">
  891. <!--${QEP::QP_versionStr[8]}-->
  892. <attribute name="QP_versionStr[8]" type="char const" visibility="0x00" properties="0x00">
  893. <documentation>/*! the current QP version number string in ROM, based on #QP_VERSION_STR */</documentation>
  894. <code>= QP_VERSION_STR;</code>
  895. </attribute>
  896. <!--${QEP::QSignal}-->
  897. <attribute name="QSignal? (Q_SIGNAL_SIZE == 2U)" type="typedef uint16_t" visibility="0x04" properties="0x00">
  898. <documentation>/*! ::QSignal represents the signal of an event
  899. *
  900. * @details
  901. * The relationship between an event and a signal is as follows. A signal
  902. * in UML is the specification of an asynchronous stimulus that triggers
  903. * reactions, and as such is an essential part of an event. (The signal
  904. * conveys the type of the occurrence--what happened?) However, an event
  905. * can also contain additional quantitative information about the
  906. * occurrence in form of event parameters.
  907. */</documentation>
  908. </attribute>
  909. <!--${QEP::QSignal}-->
  910. <attribute name="QSignal? (Q_SIGNAL_SIZE == 1U)" type="typedef uint8_t" visibility="0x04" properties="0x00"/>
  911. <!--${QEP::QSignal}-->
  912. <attribute name="QSignal? (Q_SIGNAL_SIZE == 4U)" type="typedef uint32_t" visibility="0x04" properties="0x00"/>
  913. <!--${QEP::QEvt}-->
  914. <class name="QEvt">
  915. <documentation>/*! @brief Event class
  916. * @class QEvt
  917. *
  918. * @details
  919. * ::QEvt represents events without parameters and serves as the base class
  920. * for derivation of events with parameters.
  921. *
  922. * @trace
  923. * @tr{RQP001}, @tr{RQP004}, @tr{AQP210}
  924. *
  925. * @usage
  926. * The following example illustrates how to add an event parameter by
  927. * derivation of the ::QEvt class. Please note that the ::QEvt member
  928. * super is defined as the FIRST member of the derived struct.
  929. * @include qep_qevt.c
  930. */</documentation>
  931. <!--${QEP::QEvt::sig}-->
  932. <attribute name="sig" type="QSignal" visibility="0x00" properties="0x00">
  933. <documentation>/*! Signal of the event.
  934. * @public @memberof QEvt
  935. *
  936. * @trace
  937. * @tr{RQP002}
  938. */</documentation>
  939. </attribute>
  940. <!--${QEP::QEvt::poolId_}-->
  941. <attribute name="poolId_" type="uint8_t" visibility="0x02" properties="0x00">
  942. <documentation>/*! Pool ID (==0 for immutable event)
  943. * @private @memberof QEvt
  944. *
  945. * @trace
  946. * @tr{RQP003}
  947. */</documentation>
  948. </attribute>
  949. <!--${QEP::QEvt::refCtr_}-->
  950. <attribute name="refCtr_" type="uint8_t volatile" visibility="0x02" properties="0x00">
  951. <documentation>/*! Reference counter (for mutable events)
  952. * @private @memberof QEvt
  953. *
  954. * @trace
  955. * @tr{RQP003}
  956. */</documentation>
  957. </attribute>
  958. <!--${QEP::QEvt::ctor}-->
  959. <operation name="ctor?def Q_EVT_CTOR" type="void" visibility="0x00" properties="0x00">
  960. <documentation>/*! Custom event constructor
  961. * @public @memberof QEvt
  962. *
  963. * @note
  964. * Available only when the macro #Q_EVT_CTOR is defined
  965. *
  966. * @trace
  967. * @tr{RQP005}
  968. */</documentation>
  969. <!--${QEP::QEvt::ctor::sig}-->
  970. <parameter name="sig" type="enum_t const"/>
  971. </operation>
  972. </class>
  973. <!--${QEP::QStateRet}-->
  974. <attribute name="QStateRet" type="enum" visibility="0x04" properties="0x00">
  975. <documentation>/*! All possible values returned from state/action handlers
  976. *
  977. * @note
  978. * The order matters for algorithmic correctness.
  979. */</documentation>
  980. <code>{
  981. /* unhandled and need to &quot;bubble up&quot; */
  982. Q_RET_SUPER, /*!&lt; event passed to superstate to handle */
  983. Q_RET_SUPER_SUB, /*!&lt; event passed to submachine superstate */
  984. Q_RET_UNHANDLED, /*!&lt; event unhandled due to a guard */
  985. /* handled and do not need to &quot;bubble up&quot; */
  986. Q_RET_HANDLED, /*!&lt; event handled (internal transition) */
  987. Q_RET_IGNORED, /*!&lt; event silently ignored (bubbled up to top) */
  988. /* entry/exit */
  989. Q_RET_ENTRY, /*!&lt; state entry action executed */
  990. Q_RET_EXIT, /*!&lt; state exit action executed */
  991. /* no side effects */
  992. Q_RET_NULL, /*!&lt; return value without any effect */
  993. /* transitions need to execute transition-action table in ::QMsm */
  994. Q_RET_TRAN, /*!&lt; regular transition */
  995. Q_RET_TRAN_INIT, /*!&lt; initial transition in a state or submachine */
  996. Q_RET_TRAN_EP, /*!&lt; entry-point transition into a submachine */
  997. /* transitions that additionally clobber me-&gt;state */
  998. Q_RET_TRAN_HIST, /*!&lt; transition to history of a given state */
  999. Q_RET_TRAN_XP /*!&lt; exit-point transition out of a submachine */
  1000. };</code>
  1001. </attribute>
  1002. <!--${QEP::QState}-->
  1003. <attribute name="QState" type="typedef enum QStateRet" visibility="0x04" properties="0x00">
  1004. <documentation>/*! Type returned from state-handler functions */</documentation>
  1005. </attribute>
  1006. <!--${QEP::QStateHandler}-->
  1007. <attribute name="QStateHandler" type="typedef QState (*" visibility="0x04" properties="0x00">
  1008. <documentation>/*! Pointer to a state-handler function. */</documentation>
  1009. <code>)(void * const me, QEvt const * const e);</code>
  1010. </attribute>
  1011. <!--${QEP::QActionHandler}-->
  1012. <attribute name="QActionHandler" type="typedef QState (*" visibility="0x04" properties="0x00">
  1013. <documentation>/*! Pointer to an action-handler function. */</documentation>
  1014. <code>)(void * const me);</code>
  1015. </attribute>
  1016. <!--${QEP::QXThread}-->
  1017. <attribute name="QXThread" type="struct" visibility="0x04" properties="0x00">
  1018. <documentation>/* forward declaration */</documentation>
  1019. </attribute>
  1020. <!--${QEP::QXThreadHandler}-->
  1021. <attribute name="QXThreadHandler" type="typedef void (*" visibility="0x04" properties="0x00">
  1022. <documentation>/*! Pointer to an eXthended thread handler function */</documentation>
  1023. <code>)(struct QXThread * const me);</code>
  1024. </attribute>
  1025. <!--${QEP::QMState}-->
  1026. <attribute name="QMState" type="typedef struct" visibility="0x04" properties="0x00">
  1027. <documentation>/*! @brief State object for the ::QMsm class (QM State Machine).
  1028. *
  1029. * @details
  1030. * This class groups together the attributes of a ::QMsm state, such as the
  1031. * parent state (state nesting), the associated state handler function and
  1032. * the exit action handler function. These attributes are used inside the
  1033. * QMsm_dispatch() and QMsm_init() functions.
  1034. *
  1035. * @trace
  1036. * @tr{RQP104}
  1037. *
  1038. * @attention
  1039. * The ::QMState class is only intended for the QM code generator and should
  1040. * not be used in hand-crafted code.
  1041. */</documentation>
  1042. <code>{
  1043. struct QMState const *superstate; /*!&lt; superstate of this state */
  1044. QStateHandler const stateHandler; /*!&lt; state handler function */
  1045. QActionHandler const entryAction; /*!&lt; entry action handler function */
  1046. QActionHandler const exitAction; /*!&lt; exit action handler function */
  1047. QActionHandler const initAction; /*!&lt; init action handler function */
  1048. } QMState;</code>
  1049. </attribute>
  1050. <!--${QEP::QMTranActTable}-->
  1051. <attribute name="QMTranActTable" type="typedef struct" visibility="0x04" properties="0x00">
  1052. <documentation>/*! @brief Transition-Action Table for the ::QMsm State Machine. */</documentation>
  1053. <code>{
  1054. QMState const *target; /*!&lt; target of the transition */
  1055. QActionHandler const act[1]; /*!&lt; array of actions */
  1056. } QMTranActTable;</code>
  1057. </attribute>
  1058. <!--${QEP::QHsmAttr}-->
  1059. <attribute name="QHsmAttr" type="union" visibility="0x04" properties="0x00">
  1060. <documentation>/*! @brief Attribute of for the ::QHsm class (Hierarchical State Machine).
  1061. *
  1062. * @details
  1063. * This union represents possible values stored in the 'state' and 'temp'
  1064. * attributes of the ::QHsm class.
  1065. */</documentation>
  1066. <code>{
  1067. QStateHandler fun; /*!&lt; @private pointer to a state-handler */
  1068. QActionHandler act; /*!&lt; @private pointer to an action-handler */
  1069. QXThreadHandler thr; /*!&lt; @private pointer to an thread-handler */
  1070. QMTranActTable const *tatbl; /*!&lt; @private transition-action table */
  1071. struct QMState const *obj; /*!&lt; @private pointer to QMState object */
  1072. };</code>
  1073. </attribute>
  1074. <!--${QEP::QReservedSig}-->
  1075. <attribute name="QReservedSig" type="enum" visibility="0x04" properties="0x00">
  1076. <documentation>/*! Reserved signals by the HSM-style state machine
  1077. * implementation strategy.
  1078. */</documentation>
  1079. <code>{
  1080. Q_EMPTY_SIG, /*!&lt; signal to execute the default case */
  1081. Q_ENTRY_SIG, /*!&lt; signal for coding entry actions */
  1082. Q_EXIT_SIG, /*!&lt; signal for coding exit actions */
  1083. Q_INIT_SIG, /*!&lt; signal for coding initial transitions */
  1084. Q_USER_SIG /*!&lt; offset for the user signals (QP Application) */
  1085. };</code>
  1086. </attribute>
  1087. <!--${QEP::QHsm}-->
  1088. <class name="QHsm">
  1089. <documentation>/*! @brief Hierarchical State Machine class
  1090. * @class QHsm
  1091. *
  1092. * @details
  1093. * ::QHsm represents a Hierarchical State Machine (HSM) with full support for
  1094. * hierarchical nesting of states, entry/exit actions, initial transitions,
  1095. * and transitions to history in any composite state. This class is designed
  1096. * for ease of manual coding of HSMs in C, but it is also supported by the
  1097. * QM modeling tool.&lt;br&gt;
  1098. *
  1099. * ::QHsm is also the base class for the QMsm state machine, which provides
  1100. * a superior efficiency, but requires the use of the QM modeling tool to
  1101. * generate code.
  1102. *
  1103. * @note
  1104. * ::QHsm is not intended to be instantiated directly, but rather serves as the
  1105. * abstract base class for derivation of state machines in the QP application.
  1106. *
  1107. * @trace
  1108. * @tr{RQP103}, @tr{AQP211}
  1109. *
  1110. * @usage
  1111. * The following example illustrates how to derive a state machine class
  1112. * from QHsm. Please note that the QHsm member `super` is defined as the
  1113. * FIRST member of the derived class.
  1114. * @include qep_qhsm.c
  1115. */</documentation>
  1116. <!--${QEP::QHsm::vptr}-->
  1117. <attribute name="vptr" type="struct QHsmVtable const *" visibility="0x02" properties="0x00">
  1118. <documentation>/*! Virtual pointer
  1119. * @private @memberof QHsm
  1120. *
  1121. * @trace
  1122. * @tr{RQP102}
  1123. */</documentation>
  1124. </attribute>
  1125. <!--${QEP::QHsm::state}-->
  1126. <attribute name="state" type="union QHsmAttr" visibility="0x01" properties="0x00">
  1127. <documentation>/*! Current active state (state-variable).
  1128. * @private @memberof QHsm
  1129. */</documentation>
  1130. </attribute>
  1131. <!--${QEP::QHsm::temp}-->
  1132. <attribute name="temp" type="union QHsmAttr" visibility="0x01" properties="0x00">
  1133. <documentation>/*! Temporary: target/act-table, etc.
  1134. * @private @memberof QHsm
  1135. */</documentation>
  1136. </attribute>
  1137. <!--${QEP::QHsm::isIn}-->
  1138. <operation name="isIn" type="bool" visibility="0x00" properties="0x00">
  1139. <documentation>/*! Tests if a given state is part of the current active state
  1140. * configuration in ::QHsm subclasses.
  1141. * @public @memberof QHsm
  1142. *
  1143. * @details
  1144. * Tests if a state machine derived from QHsm is-in a given state.
  1145. *
  1146. * @note For a HSM, to &quot;be in a state&quot; means also to be in a superstate of
  1147. * of the state.
  1148. *
  1149. * @param[in] me current instance pointer (see @ref oop)
  1150. * @param[in] state pointer to the state-handler function to be tested
  1151. *
  1152. * @returns
  1153. *'true' if the HSM &quot;is in&quot; the `state` and 'false' otherwise
  1154. *
  1155. * @precondition{qep_hsm,600}
  1156. * - the state configuration must be stable
  1157. *
  1158. * @trace
  1159. * @tr{RQP103}, @tr{RQP120S}
  1160. */
  1161. /*! @public @memberof QHsm */</documentation>
  1162. <!--${QEP::QHsm::isIn::state}-->
  1163. <parameter name="state" type="QStateHandler const"/>
  1164. <code>Q_REQUIRE_ID(600, me-&gt;temp.fun == me-&gt;state.fun);
  1165. bool inState = false; /* assume that this HSM is not in 'state' */
  1166. /* scan the state hierarchy bottom-up */
  1167. QState r;
  1168. do {
  1169. /* do the states match? */
  1170. if (me-&gt;temp.fun == state) {
  1171. inState = true; /* 'true' means that match found */
  1172. r = Q_RET_IGNORED; /* break out of the loop */
  1173. }
  1174. else {
  1175. r = QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1176. }
  1177. } while (r != Q_RET_IGNORED); /* QHsm_top() state not reached */
  1178. me-&gt;temp.fun = me-&gt;state.fun; /* restore the stable state configuration */
  1179. return inState; /* return the status */</code>
  1180. </operation>
  1181. <!--${QEP::QHsm::state}-->
  1182. <operation name="state" type="QStateHandler" visibility="0x00" properties="0x02">
  1183. <documentation>/*! Obtain the current active state from a HSM (read only).
  1184. * @public @memberof QHsm
  1185. *
  1186. * @param[in] me current instance pointer (see @ref oop)
  1187. *
  1188. * @returns the current active state of the QHsm class
  1189. *
  1190. * @note
  1191. * This function is used in QM for auto-generating code for state history.
  1192. */
  1193. /*! @public @memberof QHsm */</documentation>
  1194. <code>return me-&gt;state.fun;</code>
  1195. </operation>
  1196. <!--${QEP::QHsm::childState}-->
  1197. <operation name="childState" type="QStateHandler" visibility="0x00" properties="0x00">
  1198. <documentation>/*! Obtain the current active child state of a given parent in ::QHsm
  1199. * @public @memberof QHsm
  1200. *
  1201. * @details
  1202. * Finds the child state of the given `parent`, such that this child state
  1203. * is an ancestor of the currently active state. The main purpose of this
  1204. * function is to support **shallow history** transitions in state machines
  1205. * derived from QHsm.
  1206. *
  1207. * @param[in] me current instance pointer (see @ref oop)
  1208. * @param[in] parent pointer to the state-handler function
  1209. *
  1210. * @returns
  1211. * the child of a given `parent` state, which is an ancestor of the current
  1212. * active state. For the corner case when the currently active state is the
  1213. * given `parent` state, function returns the `parent` state.
  1214. *
  1215. * @postcondition{qep_hsm,890}
  1216. * - the child must be found
  1217. *
  1218. * @note
  1219. * this function is designed to be called during state transitions, so it
  1220. * does not necessarily start in a stable state configuration.
  1221. * However, the function establishes stable state configuration upon exit.
  1222. *
  1223. * @trace
  1224. * @tr{RQP103}, @tr{RQP120H}
  1225. */
  1226. /*! @public @memberof QHsm */</documentation>
  1227. <!--${QEP::QHsm::childState::parent}-->
  1228. <parameter name="parent" type="QStateHandler const"/>
  1229. <code>QStateHandler child = me-&gt;state.fun; /* start with the current state */
  1230. bool isFound = false; /* start with the child not found */
  1231. /* establish stable state configuration */
  1232. me-&gt;temp.fun = me-&gt;state.fun;
  1233. QState r;
  1234. do {
  1235. /* is this the parent of the current child? */
  1236. if (me-&gt;temp.fun == parent) {
  1237. isFound = true; /* child is found */
  1238. r = Q_RET_IGNORED; /* break out of the loop */
  1239. }
  1240. else {
  1241. child = me-&gt;temp.fun;
  1242. r = QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1243. }
  1244. } while (r != Q_RET_IGNORED); /* QHsm_top() state not reached */
  1245. me-&gt;temp.fun = me-&gt;state.fun; /* establish stable state configuration */
  1246. Q_ENSURE_ID(890, isFound);
  1247. #ifdef Q_NASSERT
  1248. Q_UNUSED_PAR(isFound);
  1249. #endif
  1250. return child; /* return the child */</code>
  1251. </operation>
  1252. <!--${QEP::QHsm::ctor}-->
  1253. <operation name="ctor" type="void" visibility="0x01" properties="0x00">
  1254. <documentation>/*! Protected &quot;constructor&quot; of ::QHsm
  1255. * @protected @memberof QHsm
  1256. *
  1257. * @details
  1258. * Performs the first step of HSM initialization by assigning the initial
  1259. * pseudostate to the currently active state of the state machine.
  1260. *
  1261. * @param[in,out] me current instance pointer (see @ref oop)
  1262. * @param[in] initial pointer to the top-most initial state-handler
  1263. * function in the derived state machine
  1264. *
  1265. * @note Must be called only by the constructors of the derived state
  1266. * machines.
  1267. *
  1268. * @note Must be called only ONCE before QHSM_INIT().
  1269. *
  1270. * @usage
  1271. * The following example illustrates how to invoke QHsm_ctor() in the
  1272. * &quot;constructor&quot; of a derived state machine:
  1273. * @include qep_qhsm_ctor.c
  1274. *
  1275. * @trace
  1276. * @tr{RQP103}
  1277. */
  1278. /*! @protected @memberof QHsm */</documentation>
  1279. <!--${QEP::QHsm::ctor::initial}-->
  1280. <parameter name="initial" type="QStateHandler const"/>
  1281. <code>static struct QHsmVtable const vtable = { /* QHsm virtual table */
  1282. &amp;QHsm_init_,
  1283. &amp;QHsm_dispatch_
  1284. #ifdef Q_SPY
  1285. ,&amp;QHsm_getStateHandler_
  1286. #endif
  1287. };
  1288. me-&gt;vptr = &amp;vtable;
  1289. me-&gt;state.fun = Q_STATE_CAST(&amp;QHsm_top);
  1290. me-&gt;temp.fun = initial;</code>
  1291. </operation>
  1292. <!--${QEP::QHsm::top}-->
  1293. <operation name="top" type="QState" visibility="0x01" properties="0x00">
  1294. <specifiers>const</specifiers>
  1295. <documentation>/*! The top-state of QHsm.
  1296. * @protected @memberof QHsm
  1297. *
  1298. * @details
  1299. * QHsm_top() is the ultimate root of state hierarchy in all HSMs derived
  1300. * from ::QHsm.
  1301. *
  1302. * @param[in] me current instance pointer (see @ref oop)
  1303. * @param[in] e pointer to the event to be dispatched to the FSM
  1304. *
  1305. * @returns
  1306. * Always returns ::Q_RET_IGNORED, which means that the top state ignores
  1307. * all events.
  1308. *
  1309. * @note The parameters to this state handler are not used. They are provided
  1310. * for conformance with the state-handler function signature ::QStateHandler.
  1311. *
  1312. * @trace
  1313. * @tr{RQP103}, @tr{RQP120T}
  1314. */
  1315. /*! @protected @memberof QHsm */</documentation>
  1316. <!--${QEP::QHsm::top::e}-->
  1317. <parameter name="e" type="QEvt const * const"/>
  1318. <code>Q_UNUSED_PAR(me);
  1319. Q_UNUSED_PAR(e);
  1320. return Q_RET_IGNORED; /* the top state ignores all events */</code>
  1321. </operation>
  1322. <!--${QEP::QHsm::init_}-->
  1323. <operation name="init_" type="void" visibility="0x01" properties="0x00">
  1324. <documentation>/*! Implementation of the top-most initial tran. in ::QHsm.
  1325. * @protected @memberof QHsm
  1326. *
  1327. * @details
  1328. * Executes the top-most initial transition in a HSM.
  1329. *
  1330. * @param[in,out] me current instance pointer (see @ref oop)
  1331. * @param[in] e pointer to an extra parameter (might be NULL)
  1332. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1333. *
  1334. * @precondition{qep_hsm,200}
  1335. * - the virtual pointer must be initialized,
  1336. * - the top-most initial transition must be initialized,
  1337. * - the initial transition must not be taken yet.
  1338. *
  1339. * @note Must be called only ONCE after the QHsm_ctor().
  1340. *
  1341. * @trace
  1342. * @tr{RQP103}, @tr{RQP120I}, @tr{RQP120D}
  1343. */
  1344. /*! @protected @memberof QHsm */</documentation>
  1345. <!--${QEP::QHsm::init_::e}-->
  1346. <parameter name="e" type="void const * const"/>
  1347. <!--${QEP::QHsm::init_::qs_id}-->
  1348. <parameter name="qs_id" type="uint_fast8_t const"/>
  1349. <code>#ifdef Q_SPY
  1350. if ((QS_priv_.flags &amp; 0x01U) == 0U) {
  1351. QS_priv_.flags |= 0x01U;
  1352. QS_FUN_DICTIONARY(&amp;QHsm_top);
  1353. }
  1354. #else
  1355. Q_UNUSED_PAR(qs_id);
  1356. #endif
  1357. QStateHandler t = me-&gt;state.fun;
  1358. Q_REQUIRE_ID(200, (me-&gt;vptr != (struct QHsmVtable *)0)
  1359. &amp;&amp; (me-&gt;temp.fun != Q_STATE_CAST(0))
  1360. &amp;&amp; (t == Q_STATE_CAST(&amp;QHsm_top)));
  1361. /* execute the top-most initial tran. */
  1362. QState r = (*me-&gt;temp.fun)(me, Q_EVT_CAST(QEvt));
  1363. /* the top-most initial transition must be taken */
  1364. Q_ASSERT_ID(210, r == Q_RET_TRAN);
  1365. QS_CRIT_STAT_
  1366. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  1367. QS_OBJ_PRE_(me); /* this state machine object */
  1368. QS_FUN_PRE_(t); /* the source state */
  1369. QS_FUN_PRE_(me-&gt;temp.fun); /* the target of the initial transition */
  1370. QS_END_PRE_()
  1371. /* drill down into the state hierarchy with initial transitions... */
  1372. do {
  1373. QStateHandler path[QHSM_MAX_NEST_DEPTH_]; /* tran entry path array */
  1374. int_fast8_t ip = 0; /* tran entry path index */
  1375. path[0] = me-&gt;temp.fun;
  1376. (void)QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1377. while (me-&gt;temp.fun != t) {
  1378. ++ip;
  1379. Q_ASSERT_ID(220, ip &lt; QHSM_MAX_NEST_DEPTH_);
  1380. path[ip] = me-&gt;temp.fun;
  1381. (void)QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1382. }
  1383. me-&gt;temp.fun = path[0];
  1384. /* nested initial transition, drill into the target hierarchy... */
  1385. do {
  1386. QHsm_state_entry_(me, path[ip], qs_id); /* enter path[ip] */
  1387. --ip;
  1388. } while (ip &gt;= 0);
  1389. t = path[0]; /* current state becomes the new source */
  1390. r = QHsm_reservedEvt_(me, t, Q_INIT_SIG); /* execute initial transition */
  1391. #ifdef Q_SPY
  1392. if (r == Q_RET_TRAN) {
  1393. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  1394. QS_OBJ_PRE_(me); /* this state machine object */
  1395. QS_FUN_PRE_(t); /* the source state */
  1396. QS_FUN_PRE_(me-&gt;temp.fun); /* target of the initial tran. */
  1397. QS_END_PRE_()
  1398. }
  1399. #endif /* Q_SPY */
  1400. } while (r == Q_RET_TRAN);
  1401. QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qs_id)
  1402. QS_TIME_PRE_(); /* time stamp */
  1403. QS_OBJ_PRE_(me); /* this state machine object */
  1404. QS_FUN_PRE_(t); /* the new active state */
  1405. QS_END_PRE_()
  1406. me-&gt;state.fun = t; /* change the current active state */
  1407. me-&gt;temp.fun = t; /* mark the configuration as stable */</code>
  1408. </operation>
  1409. <!--${QEP::QHsm::dispatch_}-->
  1410. <operation name="dispatch_" type="void" visibility="0x01" properties="0x00">
  1411. <documentation>/*! Implementation of dispatching events to a ::QHsm
  1412. * @protected @memberof QHsm
  1413. *
  1414. * @details
  1415. * Dispatches an event for processing to a hierarchical state machine (HSM).
  1416. * The processing of an event represents one run-to-completion (RTC) step.
  1417. *
  1418. * @param[in,out] me current instance pointer (see @ref oop)
  1419. * @param[in] e pointer to the event to be dispatched to the HSM
  1420. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1421. *
  1422. * @precondition{qep_hsm,400}
  1423. * - the current state must be initialized and
  1424. * - the state configuration must be stable
  1425. *
  1426. * @note
  1427. * This function should be called only via the virtual table (see
  1428. * QHSM_DISPATCH()) and should NOT be called directly in the applications.
  1429. *
  1430. * @trace
  1431. * @tr{RQP103}, @tr{RQP120A}, @tr{RQP120B}, @tr{RQP120C},
  1432. * @tr{RQP120D}, @tr{RQP120E}, @tr{RQP120E}, @tr{RQP120C},
  1433. * @tr{RQP120B}
  1434. */
  1435. /*! @protected @memberof QHsm */</documentation>
  1436. <!--${QEP::QHsm::dispatch_::e}-->
  1437. <parameter name="e" type="QEvt const * const"/>
  1438. <!--${QEP::QHsm::dispatch_::qs_id}-->
  1439. <parameter name="qs_id" type="uint_fast8_t const"/>
  1440. <code>#ifndef Q_SPY
  1441. Q_UNUSED_PAR(qs_id);
  1442. #endif
  1443. QStateHandler t = me-&gt;state.fun;
  1444. QS_CRIT_STAT_
  1445. Q_REQUIRE_ID(400, (t != Q_STATE_CAST(0))
  1446. &amp;&amp; (t == me-&gt;temp.fun));
  1447. QS_BEGIN_PRE_(QS_QEP_DISPATCH, qs_id)
  1448. QS_TIME_PRE_(); /* time stamp */
  1449. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  1450. QS_OBJ_PRE_(me); /* this state machine object */
  1451. QS_FUN_PRE_(t); /* the current state */
  1452. QS_END_PRE_()
  1453. QStateHandler s;
  1454. QState r;
  1455. /* process the event hierarchically... */
  1456. do {
  1457. s = me-&gt;temp.fun;
  1458. r = (*s)(me, e); /* invoke state handler s */
  1459. if (r == Q_RET_UNHANDLED) { /* unhandled due to a guard? */
  1460. QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qs_id)
  1461. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  1462. QS_OBJ_PRE_(me); /* this state machine object */
  1463. QS_FUN_PRE_(s); /* the current state */
  1464. QS_END_PRE_()
  1465. r = QHsm_reservedEvt_(me, s, Q_EMPTY_SIG); /* find superstate of s */
  1466. }
  1467. } while (r == Q_RET_SUPER);
  1468. /* regular transition taken? */
  1469. if (r &gt;= Q_RET_TRAN) {
  1470. QStateHandler path[QHSM_MAX_NEST_DEPTH_];
  1471. path[0] = me-&gt;temp.fun; /* save the target of the transition */
  1472. path[1] = t;
  1473. path[2] = s;
  1474. /* exit current state to transition source s... */
  1475. for (; t != s; t = me-&gt;temp.fun) {
  1476. /* exit from t handled? */
  1477. if (QHsm_state_exit_(me, t, qs_id)) {
  1478. /* find superstate of t */
  1479. (void)QHsm_reservedEvt_(me, t, Q_EMPTY_SIG);
  1480. }
  1481. }
  1482. int_fast8_t ip = QHsm_tran_(me, path, qs_id); /* the HSM transition */
  1483. #ifdef Q_SPY
  1484. if (r == Q_RET_TRAN_HIST) {
  1485. QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qs_id)
  1486. QS_OBJ_PRE_(me); /* this state machine object */
  1487. QS_FUN_PRE_(t); /* the source of the transition */
  1488. QS_FUN_PRE_(path[0]); /* the target of tran. to history */
  1489. QS_END_PRE_()
  1490. }
  1491. #endif /* Q_SPY */
  1492. /* execute state entry actions in the desired order... */
  1493. for (; ip &gt;= 0; --ip) {
  1494. QHsm_state_entry_(me, path[ip], qs_id); /* enter path[ip] */
  1495. }
  1496. t = path[0]; /* stick the target into register */
  1497. me-&gt;temp.fun = t; /* update the next state */
  1498. /* while nested initial transition... */
  1499. /*! @tr{RQP120I} */
  1500. while (QHsm_reservedEvt_(me, t, Q_INIT_SIG) == Q_RET_TRAN) {
  1501. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  1502. QS_OBJ_PRE_(me); /* this state machine object */
  1503. QS_FUN_PRE_(t); /* the source (pseudo)state */
  1504. QS_FUN_PRE_(me-&gt;temp.fun); /* the target of the tran. */
  1505. QS_END_PRE_()
  1506. ip = 0;
  1507. path[0] = me-&gt;temp.fun;
  1508. /* find superstate */
  1509. (void)QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1510. while (me-&gt;temp.fun != t) {
  1511. ++ip;
  1512. path[ip] = me-&gt;temp.fun;
  1513. /* find superstate */
  1514. (void)QHsm_reservedEvt_(me, me-&gt;temp.fun, Q_EMPTY_SIG);
  1515. }
  1516. me-&gt;temp.fun = path[0];
  1517. /* entry path must not overflow */
  1518. Q_ASSERT_ID(410, ip &lt; QHSM_MAX_NEST_DEPTH_);
  1519. /* retrace the entry path in reverse (correct) order... */
  1520. do {
  1521. QHsm_state_entry_(me, path[ip], qs_id); /* enter path[ip] */
  1522. --ip;
  1523. } while (ip &gt;= 0);
  1524. t = path[0]; /* current state becomes the new source */
  1525. }
  1526. QS_BEGIN_PRE_(QS_QEP_TRAN, qs_id)
  1527. QS_TIME_PRE_(); /* time stamp */
  1528. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  1529. QS_OBJ_PRE_(me); /* this state machine object */
  1530. QS_FUN_PRE_(s); /* the source of the transition */
  1531. QS_FUN_PRE_(t); /* the new active state */
  1532. QS_END_PRE_()
  1533. }
  1534. #ifdef Q_SPY
  1535. else if (r == Q_RET_HANDLED) {
  1536. QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qs_id)
  1537. QS_TIME_PRE_(); /* time stamp */
  1538. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  1539. QS_OBJ_PRE_(me); /* this state machine object */
  1540. QS_FUN_PRE_(s); /* the source state */
  1541. QS_END_PRE_()
  1542. }
  1543. else {
  1544. QS_BEGIN_PRE_(QS_QEP_IGNORED, qs_id)
  1545. QS_TIME_PRE_(); /* time stamp */
  1546. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  1547. QS_OBJ_PRE_(me); /* this state machine object */
  1548. QS_FUN_PRE_(me-&gt;state.fun); /* the current state */
  1549. QS_END_PRE_()
  1550. }
  1551. #endif /* Q_SPY */
  1552. me-&gt;state.fun = t; /* change the current active state */
  1553. me-&gt;temp.fun = t; /* mark the configuration as stable */</code>
  1554. </operation>
  1555. <!--${QEP::QHsm::getStateHandler_}-->
  1556. <operation name="getStateHandler_?def Q_SPY" type="QStateHandler" visibility="0x02" properties="0x00">
  1557. <documentation>/*! Implementation of getting the state handler in a ::QHsm subclass
  1558. * @private @memberof QHsm
  1559. */
  1560. /*! @private @memberof QHsm */</documentation>
  1561. <code>return me-&gt;state.fun;</code>
  1562. </operation>
  1563. <!--${QEP::QHsm::tran_}-->
  1564. <operation name="tran_" type="int_fast8_t" visibility="0x02" properties="0x00">
  1565. <documentation>/*! Helper function to execute transition sequence in a hierarchical state
  1566. * machine (HSM).
  1567. *
  1568. * @param[in,out] path array of pointers to state-handler functions
  1569. * to execute the entry actions
  1570. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1571. *
  1572. * @returns
  1573. * the depth of the entry path stored in the `path` parameter.
  1574. *
  1575. * @trace
  1576. * @tr{RQP103}, @tr{RQP120E}, @tr{RQP120F}
  1577. */
  1578. /*! @private @memberof QHsm */</documentation>
  1579. <!--${QEP::QHsm::tran_::path}-->
  1580. <parameter name="path" type="QStateHandler * const"/>
  1581. <!--${QEP::QHsm::tran_::qs_id}-->
  1582. <parameter name="qs_id" type="uint_fast8_t const"/>
  1583. <code>#ifndef Q_SPY
  1584. Q_UNUSED_PAR(qs_id);
  1585. #endif
  1586. int_fast8_t ip = -1; /* transition entry path index */
  1587. QStateHandler t = path[0];
  1588. QStateHandler const s = path[2];
  1589. /* (a) check source==target (transition to self)... */
  1590. if (s == t) {
  1591. (void)QHsm_state_exit_(me, s, qs_id); /* exit source */
  1592. ip = 0; /* enter the target */
  1593. }
  1594. else {
  1595. /* find superstate of target */
  1596. (void)QHsm_reservedEvt_(me, t, Q_EMPTY_SIG);
  1597. t = me-&gt;temp.fun;
  1598. /* (b) check source==target-&gt;super... */
  1599. if (s == t) {
  1600. ip = 0; /* enter the target */
  1601. }
  1602. else {
  1603. /* find superstate of src */
  1604. (void)QHsm_reservedEvt_(me, s, Q_EMPTY_SIG);
  1605. /* (c) check source-&gt;super==target-&gt;super... */
  1606. if (me-&gt;temp.fun == t) {
  1607. (void)QHsm_state_exit_(me, s, qs_id); /* exit source */
  1608. ip = 0; /* enter the target */
  1609. }
  1610. else {
  1611. /* (d) check source-&gt;super==target... */
  1612. if (me-&gt;temp.fun == path[0]) {
  1613. (void)QHsm_state_exit_(me, s, qs_id); /* exit source */
  1614. }
  1615. else {
  1616. /* (e) check rest of source==target-&gt;super-&gt;super..
  1617. * and store the entry path along the way
  1618. */
  1619. int_fast8_t iq = 0; /* indicate that LCA not found */
  1620. ip = 1; /* enter target and its superstate */
  1621. path[1] = t; /* save the superstate of target */
  1622. t = me-&gt;temp.fun; /* save source-&gt;super */
  1623. /* find target-&gt;super-&gt;super... */
  1624. QState r = QHsm_reservedEvt_(me, path[1], Q_EMPTY_SIG);
  1625. while (r == Q_RET_SUPER) {
  1626. ++ip;
  1627. path[ip] = me-&gt;temp.fun; /* store the entry path */
  1628. if (me-&gt;temp.fun == s) { /* is it the source? */
  1629. iq = 1; /* indicate that LCA found */
  1630. /* entry path must not overflow */
  1631. Q_ASSERT_ID(510,
  1632. ip &lt; QHSM_MAX_NEST_DEPTH_);
  1633. --ip; /* do not enter the source */
  1634. r = Q_RET_HANDLED; /* terminate loop */
  1635. }
  1636. /* it is not the source, keep going up */
  1637. else {
  1638. r = QHsm_reservedEvt_(me, me-&gt;temp.fun,
  1639. Q_EMPTY_SIG);
  1640. }
  1641. }
  1642. /* the LCA not found yet? */
  1643. if (iq == 0) {
  1644. /* entry path must not overflow */
  1645. Q_ASSERT_ID(520, ip &lt; QHSM_MAX_NEST_DEPTH_);
  1646. /* exit source */
  1647. (void)QHsm_state_exit_(me, s, qs_id);
  1648. /* (f) check the rest of source-&gt;super
  1649. * == target-&gt;super-&gt;super...
  1650. */
  1651. iq = ip;
  1652. r = Q_RET_IGNORED; /* LCA NOT found */
  1653. do {
  1654. if (t == path[iq]) { /* is this the LCA? */
  1655. r = Q_RET_HANDLED; /* LCA found */
  1656. ip = iq - 1; /* do not enter LCA */
  1657. iq = -1; /* cause termintion of the loop */
  1658. }
  1659. else {
  1660. --iq; /* try lower superstate of target */
  1661. }
  1662. } while (iq &gt;= 0);
  1663. /* LCA not found? */
  1664. if (r != Q_RET_HANDLED) {
  1665. /* (g) check each source-&gt;super-&gt;...
  1666. * for each target-&gt;super...
  1667. */
  1668. r = Q_RET_IGNORED; /* keep looping */
  1669. do {
  1670. /* exit from t handled? */
  1671. if (QHsm_state_exit_(me, t, qs_id)) {
  1672. /* find superstate of t */
  1673. (void)QHsm_reservedEvt_(me, t, Q_EMPTY_SIG);
  1674. }
  1675. t = me-&gt;temp.fun; /* set to super of t */
  1676. iq = ip;
  1677. do {
  1678. /* is this LCA? */
  1679. if (t == path[iq]) {
  1680. /* do not enter LCA */
  1681. ip = (int_fast8_t)(iq - 1);
  1682. iq = -1; /* break out of inner loop */
  1683. /* break out of outer loop */
  1684. r = Q_RET_HANDLED;
  1685. }
  1686. else {
  1687. --iq;
  1688. }
  1689. } while (iq &gt;= 0);
  1690. } while (r != Q_RET_HANDLED);
  1691. }
  1692. }
  1693. }
  1694. }
  1695. }
  1696. }
  1697. return ip;</code>
  1698. </operation>
  1699. <!--${QEP::QHsm::state_entry_}-->
  1700. <operation name="state_entry_" type="void" visibility="0x02" properties="0x00">
  1701. <documentation>/*! Helper function to execute entry into a given state in a
  1702. * hierarchical state machine (HSM).
  1703. * @private @memberof QHsm
  1704. *
  1705. * @param[in] state state handler function
  1706. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1707. */
  1708. /*! @private @memberof QHsm */</documentation>
  1709. <!--${QEP::QHsm::state_entry_::state}-->
  1710. <parameter name="state" type="QStateHandler const"/>
  1711. <!--${QEP::QHsm::state_entry_::qs_id}-->
  1712. <parameter name="qs_id" type="uint_fast8_t const"/>
  1713. <code>#ifdef Q_SPY
  1714. if ((*state)(me, &amp;l_reservedEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
  1715. QS_CRIT_STAT_
  1716. QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qs_id)
  1717. QS_OBJ_PRE_(me);
  1718. QS_FUN_PRE_(state);
  1719. QS_END_PRE_()
  1720. }
  1721. #else
  1722. Q_UNUSED_PAR(qs_id);
  1723. (void)(*state)(me, &amp;l_reservedEvt_[Q_ENTRY_SIG]);
  1724. #endif /* Q_SPY */</code>
  1725. </operation>
  1726. <!--${QEP::QHsm::state_exit_}-->
  1727. <operation name="state_exit_" type="bool" visibility="0x02" properties="0x00">
  1728. <documentation>/*! Helper function to execute exit from a given state in a
  1729. * hierarchical state machine (HSM).
  1730. * @private @memberof QHsm
  1731. *
  1732. * @param[in] state state handler function
  1733. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1734. *
  1735. * @returns
  1736. * 'true' if the exit action has been found in the state and
  1737. * 'flase' otherwise.
  1738. */
  1739. /*! @private @memberof QHsm */</documentation>
  1740. <!--${QEP::QHsm::state_exit_::state}-->
  1741. <parameter name="state" type="QStateHandler const"/>
  1742. <!--${QEP::QHsm::state_exit_::qs_id}-->
  1743. <parameter name="qs_id" type="uint_fast8_t const"/>
  1744. <code>#ifdef Q_SPY
  1745. bool isHandled;
  1746. if ((*state)(me, &amp;l_reservedEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
  1747. QS_CRIT_STAT_
  1748. QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qs_id)
  1749. QS_OBJ_PRE_(me);
  1750. QS_FUN_PRE_(state);
  1751. QS_END_PRE_()
  1752. isHandled = true;
  1753. }
  1754. else {
  1755. isHandled = false;
  1756. }
  1757. return isHandled;
  1758. #else
  1759. Q_UNUSED_PAR(qs_id);
  1760. return (*state)(me, &amp;l_reservedEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED;
  1761. #endif /* Q_SPY */</code>
  1762. </operation>
  1763. </class>
  1764. <!--${QEP::QHsmVtable}-->
  1765. <attribute name="QHsmVtable" type="struct" visibility="0x04" properties="0x00">
  1766. <documentation>/*! @brief Virtual table for the ::QHsm class.
  1767. *
  1768. * @trace
  1769. * @tr{RQP102}
  1770. */</documentation>
  1771. <code>{
  1772. /*! Triggers the top-most initial transition in the HSM. */
  1773. void (*init)(QHsm * const me, void const * const e,
  1774. uint_fast8_t const qs_id);
  1775. /*! Dispatches an event to the HSM. */
  1776. void (*dispatch)(QHsm * const me, QEvt const * const e,
  1777. uint_fast8_t const qs_id);
  1778. #ifdef Q_SPY
  1779. /*! Get the current state handler of the HSM. */
  1780. QStateHandler (*getStateHandler)(QHsm * const me);
  1781. #endif /* Q_SPY */
  1782. };</code>
  1783. </attribute>
  1784. <!--${QEP::QMsm}-->
  1785. <class name="QMsm" superclass="QEP::QHsm">
  1786. <documentation>/*! @brief QM state machine implementation strategy
  1787. * @class QMsm
  1788. * @extends QHsm
  1789. *
  1790. * @details
  1791. * QMsm (QM State Machine) provides a more efficient state machine
  1792. * implementation strategy than ::QHsm, but requires the use of the QM
  1793. * modeling tool, but are the fastest and need the least run-time
  1794. * support (the smallest event-processor taking up the least code space).
  1795. *
  1796. * @note
  1797. * QMsm is not intended to be instantiated directly, but rather serves
  1798. * as the abstrace base class for derivation of state machines in the
  1799. * application code.
  1800. *
  1801. * @trace
  1802. * @tr{RQP104}
  1803. *
  1804. * @usage
  1805. * The following example illustrates how to derive a state machine class
  1806. * from QMsm. Please note that the QMsm member `super` is defined
  1807. * as the *first* member of the derived struct.
  1808. * @include qep_qmsm.c
  1809. */</documentation>
  1810. <!--${QEP::QMsm::isInState}-->
  1811. <operation name="isInState" type="bool" visibility="0x00" properties="0x00">
  1812. <specifiers>const</specifiers>
  1813. <documentation>/*! Tests if a given state is part of the current active state
  1814. * configuration in a MSM.
  1815. * @public @memberof QMsm
  1816. *
  1817. * @details
  1818. * Tests if a state machine derived from QMsm is-in a given state.
  1819. *
  1820. * @note
  1821. * For a MSM, to &quot;be-in&quot; a state means also to &quot;be-in&quot; a superstate of
  1822. * of the state.
  1823. *
  1824. * @param[in] me current instance pointer (see @ref oop)
  1825. * @param[in] state pointer to the QMState object that corresponds to the
  1826. * tested state.
  1827. * @returns
  1828. * 'true' if the MSM &quot;is in&quot; the `state` and 'false' otherwise
  1829. */
  1830. /*! @public @memberof QMsm */</documentation>
  1831. <!--${QEP::QMsm::isInState::state}-->
  1832. <parameter name="state" type="QMState const * const"/>
  1833. <code>bool inState = false; /* assume that this MSM is not in 'state' */
  1834. for (QMState const *s = me-&gt;super.state.obj;
  1835. s != (QMState *)0;
  1836. s = s-&gt;superstate)
  1837. {
  1838. if (s == state) {
  1839. inState = true; /* match found, return 'true' */
  1840. break;
  1841. }
  1842. }
  1843. return inState;</code>
  1844. </operation>
  1845. <!--${QEP::QMsm::stateObj}-->
  1846. <operation name="stateObj" type="QMState const *" visibility="0x00" properties="0x01">
  1847. <documentation>/*! Obtain the current active state from a MSM (read only)
  1848. * @public @memberof QMsm
  1849. *
  1850. * @param[in] me current instance pointer (see @ref oop)
  1851. *
  1852. * @returns the current active state-object
  1853. *
  1854. * @note
  1855. * This function is used in QM for auto-generating code for state history
  1856. */
  1857. /*! @public @memberof QMsm */</documentation>
  1858. <!--${QEP::QMsm::stateObj::me}-->
  1859. <parameter name="me" type="QHsm const * const"/>
  1860. <code>return me-&gt;state.obj;</code>
  1861. </operation>
  1862. <!--${QEP::QMsm::childStateObj}-->
  1863. <operation name="childStateObj" type="QMState const *" visibility="0x00" properties="0x01">
  1864. <documentation>/*! Obtain the current active child state of a given parent in ::QMsm
  1865. * @public @memberof QMsm
  1866. *
  1867. * @details
  1868. * Finds the child state of the given @c parent, such that this child state
  1869. * is an ancestor of the currently active state. The main purpose of this
  1870. * function is to support **shallow history** transitions in state machines
  1871. * derived from QMsm.
  1872. *
  1873. * @param[in] me current instance pointer (see @ref oop)
  1874. * @param[in] parent pointer to the state-handler object
  1875. *
  1876. * @returns
  1877. * the child of a given @c parent state, which is an ancestor of
  1878. * the currently active state. For the corner case when the currently active
  1879. * state is the given @c parent state, function returns the @c parent state.
  1880. *
  1881. * @postcondition{qep_msm,890}
  1882. * - the child must be found
  1883. *
  1884. * @sa QMsm_childStateObj()
  1885. */
  1886. /*! @public @memberof QMsm */</documentation>
  1887. <!--${QEP::QMsm::childStateObj::me}-->
  1888. <parameter name="me" type="QHsm const * const"/>
  1889. <!--${QEP::QMsm::childStateObj::parent}-->
  1890. <parameter name="parent" type="QMState const * const"/>
  1891. <code>QMState const *child = me-&gt;state.obj;
  1892. bool isFound = false; /* start with the child not found */
  1893. QMState const *s;
  1894. for (s = me-&gt;state.obj; s != (QMState *)0; s = s-&gt;superstate) {
  1895. if (s == parent) {
  1896. isFound = true; /* child is found */
  1897. break;
  1898. }
  1899. else {
  1900. child = s;
  1901. }
  1902. }
  1903. if (!isFound) { /* still not found? */
  1904. for (s = me-&gt;temp.obj; s != (QMState *)0; s = s-&gt;superstate) {
  1905. if (s == parent) {
  1906. isFound = true; /* child is found */
  1907. break;
  1908. }
  1909. else {
  1910. child = s;
  1911. }
  1912. }
  1913. }
  1914. Q_ENSURE_ID(890, isFound);
  1915. #ifdef Q_NASSERT
  1916. Q_UNUSED_PAR(isFound);
  1917. #endif
  1918. return child; /* return the child */</code>
  1919. </operation>
  1920. <!--${QEP::QMsm::ctor}-->
  1921. <operation name="ctor" type="void" visibility="0x01" properties="0x00">
  1922. <documentation>/*! Constructor of ::QMsm
  1923. * @protected @memberof QMsm
  1924. *
  1925. * @details
  1926. * Performs the first step of QMsm initialization by assigning the initial
  1927. * pseudostate to the currently active state of the state machine.
  1928. *
  1929. * @param[in,out] me current instance pointer (see @ref oop)
  1930. * @param[in] initial the top-most initial transition for the MSM.
  1931. *
  1932. * @note
  1933. * Must be called only ONCE before QHSM_INIT().
  1934. *
  1935. * @note
  1936. * QMsm inherits QHsm, so by the @ref oop convention it should call the
  1937. * constructor of the superclass, i.e., QHsm_ctor(). However, this would pull
  1938. * in the QHsmVtable, which in turn will pull in the code for QHsm_init_() and
  1939. * QHsm_dispatch_() implemetations. To avoid this code size penalty, in case
  1940. * ::QHsm is not used in a given project, the QMsm_ctor() performs direct
  1941. * intitialization of the Vtable, which avoids pulling in the code for QMsm.
  1942. *
  1943. * @usage
  1944. * The following example illustrates how to invoke QMsm_ctor() in the
  1945. * &quot;constructor&quot; of a derived state machine:
  1946. * @include qep_qmsm_ctor.c
  1947. */
  1948. /*! @protected @memberof QMsm */</documentation>
  1949. <!--${QEP::QMsm::ctor::initial}-->
  1950. <parameter name="initial" type="QStateHandler const"/>
  1951. <code>static struct QHsmVtable const vtable = { /* QHsm virtual table */
  1952. &amp;QMsm_init_,
  1953. &amp;QMsm_dispatch_
  1954. #ifdef Q_SPY
  1955. ,&amp;QMsm_getStateHandler_
  1956. #endif
  1957. };
  1958. /* do not call the QHsm_ctor() here */
  1959. me-&gt;super.vptr = &amp;vtable;
  1960. me-&gt;super.state.obj = &amp;l_msm_top_s; /* the current state (top) */
  1961. me-&gt;super.temp.fun = initial; /* the initial transition handler */</code>
  1962. </operation>
  1963. <!--${QEP::QMsm::init_}-->
  1964. <operation name="init_" type="void" visibility="0x00" properties="0x01">
  1965. <documentation>/*! Implementation of the top-most initial tran. in ::QMsm.
  1966. * @private @memberof QMsm
  1967. *
  1968. * @details
  1969. * Executes the top-most initial transition in a MSM.
  1970. *
  1971. * @param[in,out] me current instance pointer (see @ref oop)
  1972. * @param[in] e pointer to an extra parameter (might be NULL)
  1973. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  1974. *
  1975. * @precondition{qep_msm,200}
  1976. * - the virtual pointer must be initialized,
  1977. * - the top-most initial transition must be initialized,
  1978. * - the initial transition must not be taken yet.
  1979. *
  1980. * @note
  1981. * This function should be called only via the virtual table (see
  1982. * QHSM_INIT()) and should NOT be called directly in the applications.
  1983. */
  1984. /*! @private @memberof QMsm */</documentation>
  1985. <!--${QEP::QMsm::init_::me}-->
  1986. <parameter name="me" type="QHsm * const"/>
  1987. <!--${QEP::QMsm::init_::e}-->
  1988. <parameter name="e" type="void const * const"/>
  1989. <!--${QEP::QMsm::init_::qs_id}-->
  1990. <parameter name="qs_id" type="uint_fast8_t const"/>
  1991. <code>#ifndef Q_SPY
  1992. Q_UNUSED_PAR(qs_id);
  1993. #endif
  1994. Q_REQUIRE_ID(200, (me-&gt;vptr != (struct QHsmVtable *)0)
  1995. &amp;&amp; (me-&gt;temp.fun != Q_STATE_CAST(0))
  1996. &amp;&amp; (me-&gt;state.obj == &amp;l_msm_top_s));
  1997. /* execute the top-most initial tran. */
  1998. QState r = (*me-&gt;temp.fun)(me, Q_EVT_CAST(QEvt));
  1999. /* the top-most initial transition must be taken */
  2000. Q_ASSERT_ID(210, r == Q_RET_TRAN_INIT);
  2001. QS_CRIT_STAT_
  2002. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  2003. QS_OBJ_PRE_(me); /* this state machine object */
  2004. QS_FUN_PRE_(me-&gt;state.obj-&gt;stateHandler); /* source state */
  2005. QS_FUN_PRE_(me-&gt;temp.tatbl-&gt;target-&gt;stateHandler); /* target state */
  2006. QS_END_PRE_()
  2007. /* set state to the last tran. target */
  2008. me-&gt;state.obj = me-&gt;temp.tatbl-&gt;target;
  2009. /* drill down into the state hierarchy with initial transitions... */
  2010. /* execute the tran. table */
  2011. do {
  2012. r = QMsm_execTatbl_(me, me-&gt;temp.tatbl, qs_id);
  2013. } while (r &gt;= Q_RET_TRAN_INIT);
  2014. QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qs_id)
  2015. QS_TIME_PRE_(); /* time stamp */
  2016. QS_OBJ_PRE_(me); /* this state machine object */
  2017. QS_FUN_PRE_(me-&gt;state.obj-&gt;stateHandler); /* the new current state */
  2018. QS_END_PRE_()</code>
  2019. </operation>
  2020. <!--${QEP::QMsm::dispatch_}-->
  2021. <operation name="dispatch_" type="void" visibility="0x02" properties="0x01">
  2022. <documentation>/*! Implementation of dispatching events to a ::QMsm
  2023. * @private @memberof QMsm
  2024. *
  2025. * @details
  2026. * Dispatches an event for processing to a meta state machine (MSM).
  2027. * The processing of an event represents one run-to-completion (RTC) step.
  2028. *
  2029. * @param[in,out] me current instance pointer (see @ref oop)
  2030. * @param[in] e pointer to the event to be dispatched to the MSM
  2031. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  2032. *
  2033. * @precondition{qep_msm,300}
  2034. * - current state must be initialized
  2035. *
  2036. * @note
  2037. * This function should be called only via the virtual table (see
  2038. * QHSM_DISPATCH()) and should NOT be called directly in the applications.
  2039. */
  2040. /*! @private @memberof QMsm */</documentation>
  2041. <!--${QEP::QMsm::dispatch_::me}-->
  2042. <parameter name="me" type="QHsm * const"/>
  2043. <!--${QEP::QMsm::dispatch_::e}-->
  2044. <parameter name="e" type="QEvt const * const"/>
  2045. <!--${QEP::QMsm::dispatch_::qs_id}-->
  2046. <parameter name="qs_id" type="uint_fast8_t const"/>
  2047. <code>#ifndef Q_SPY
  2048. Q_UNUSED_PAR(qs_id);
  2049. #endif
  2050. QMState const *s = me-&gt;state.obj; /* store the current state */
  2051. QMState const *t = s;
  2052. Q_REQUIRE_ID(300, s != (QMState *)0);
  2053. QS_CRIT_STAT_
  2054. QS_BEGIN_PRE_(QS_QEP_DISPATCH, qs_id)
  2055. QS_TIME_PRE_(); /* time stamp */
  2056. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  2057. QS_OBJ_PRE_(me); /* this state machine object */
  2058. QS_FUN_PRE_(s-&gt;stateHandler); /* the current state handler */
  2059. QS_END_PRE_()
  2060. /* scan the state hierarchy up to the top state... */
  2061. QState r;
  2062. do {
  2063. r = (*t-&gt;stateHandler)(me, e); /* call state handler function */
  2064. /* event handled? (the most frequent case) */
  2065. if (r &gt;= Q_RET_HANDLED) {
  2066. break; /* done scanning the state hierarchy */
  2067. }
  2068. /* event unhandled and passed to the superstate? */
  2069. else if (r == Q_RET_SUPER) {
  2070. t = t-&gt;superstate; /* advance to the superstate */
  2071. }
  2072. /* event unhandled and passed to a submachine superstate? */
  2073. else if (r == Q_RET_SUPER_SUB) {
  2074. t = me-&gt;temp.obj; /* current host state of the submachie */
  2075. }
  2076. /* event unhandled due to a guard? */
  2077. else if (r == Q_RET_UNHANDLED) {
  2078. QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qs_id)
  2079. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  2080. QS_OBJ_PRE_(me); /* this state machine object */
  2081. QS_FUN_PRE_(t-&gt;stateHandler); /* the current state */
  2082. QS_END_PRE_()
  2083. t = t-&gt;superstate; /* advance to the superstate */
  2084. }
  2085. else {
  2086. /* no other return value should be produced */
  2087. Q_ERROR_ID(310);
  2088. }
  2089. } while (t != (QMState *)0);
  2090. /* any kind of transition taken? */
  2091. if (r &gt;= Q_RET_TRAN) {
  2092. #ifdef Q_SPY
  2093. QMState const * const ts = t; /* transition source for QS tracing */
  2094. /* the transition source state must not be NULL */
  2095. Q_ASSERT_ID(320, ts != (QMState *)0);
  2096. #endif /* Q_SPY */
  2097. do {
  2098. /* save the transition-action table before it gets clobbered */
  2099. struct QMTranActTable const * const tatbl = me-&gt;temp.tatbl;
  2100. union QHsmAttr tmp; /* temporary to save intermediate values */
  2101. /* was TRAN, TRAN_INIT, or TRAN_EP taken? */
  2102. if (r &lt;= Q_RET_TRAN_EP) {
  2103. me-&gt;temp.obj = (QMState *)0; /* clear */
  2104. QMsm_exitToTranSource_(me, s, t, qs_id);
  2105. r = QMsm_execTatbl_(me, tatbl, qs_id);
  2106. s = me-&gt;state.obj;
  2107. }
  2108. /* was a transition segment to history taken? */
  2109. else if (r == Q_RET_TRAN_HIST) {
  2110. tmp.obj = me-&gt;state.obj; /* save history */
  2111. me-&gt;state.obj = s; /* restore the original state */
  2112. QMsm_exitToTranSource_(me, s, t, qs_id);
  2113. (void)QMsm_execTatbl_(me, tatbl, qs_id);
  2114. r = QMsm_enterHistory_(me, tmp.obj, qs_id);
  2115. s = me-&gt;state.obj;
  2116. }
  2117. /* was a transition segment to an exit point taken? */
  2118. else if (r == Q_RET_TRAN_XP) {
  2119. tmp.act = me-&gt;state.act; /* save XP action */
  2120. me-&gt;state.obj = s; /* restore the original state */
  2121. r = (*tmp.act)(me); /* execute the XP action */
  2122. if (r == Q_RET_TRAN) { /* XP -&gt; TRAN ? */
  2123. tmp.tatbl = me-&gt;temp.tatbl; /* save me-&gt;temp */
  2124. QMsm_exitToTranSource_(me, s, t, qs_id);
  2125. /* take the tran-to-XP segment inside submachine */
  2126. (void)QMsm_execTatbl_(me, tatbl, qs_id);
  2127. s = me-&gt;state.obj;
  2128. #ifdef Q_SPY
  2129. me-&gt;temp.tatbl = tmp.tatbl; /* restore me-&gt;temp */
  2130. #endif /* Q_SPY */
  2131. }
  2132. else if (r == Q_RET_TRAN_HIST) { /* XP -&gt; HIST ? */
  2133. tmp.obj = me-&gt;state.obj; /* save the history */
  2134. me-&gt;state.obj = s; /* restore the original state */
  2135. s = me-&gt;temp.obj; /* save me-&gt;temp */
  2136. QMsm_exitToTranSource_(me, me-&gt;state.obj, t, qs_id);
  2137. /* take the tran-to-XP segment inside submachine */
  2138. (void)QMsm_execTatbl_(me, tatbl, qs_id);
  2139. #ifdef Q_SPY
  2140. me-&gt;temp.obj = s; /* restore me-&gt;temp */
  2141. #endif /* Q_SPY */
  2142. s = me-&gt;state.obj;
  2143. me-&gt;state.obj = tmp.obj; /* restore the history */
  2144. }
  2145. else {
  2146. /* TRAN_XP must NOT be followed by any other tran type */
  2147. Q_ASSERT_ID(330, r &lt; Q_RET_TRAN);
  2148. }
  2149. }
  2150. else {
  2151. /* no other return value should be produced */
  2152. Q_ERROR_ID(340);
  2153. }
  2154. t = s; /* set target to the current state */
  2155. } while (r &gt;= Q_RET_TRAN);
  2156. QS_BEGIN_PRE_(QS_QEP_TRAN, qs_id)
  2157. QS_TIME_PRE_(); /* time stamp */
  2158. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  2159. QS_OBJ_PRE_(me); /* this state machine object */
  2160. QS_FUN_PRE_(ts-&gt;stateHandler); /* the transition source */
  2161. QS_FUN_PRE_(s-&gt;stateHandler); /* the new active state */
  2162. QS_END_PRE_()
  2163. }
  2164. #ifdef Q_SPY
  2165. /* was the event handled? */
  2166. else if (r == Q_RET_HANDLED) {
  2167. /* internal tran. source can't be NULL */
  2168. Q_ASSERT_ID(340, t != (QMState *)0);
  2169. QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qs_id)
  2170. QS_TIME_PRE_(); /* time stamp */
  2171. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  2172. QS_OBJ_PRE_(me); /* this state machine object */
  2173. QS_FUN_PRE_(t-&gt;stateHandler); /* the source state */
  2174. QS_END_PRE_()
  2175. }
  2176. /* event bubbled to the 'top' state? */
  2177. else if (t == (QMState *)0) {
  2178. QS_BEGIN_PRE_(QS_QEP_IGNORED, qs_id)
  2179. QS_TIME_PRE_(); /* time stamp */
  2180. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  2181. QS_OBJ_PRE_(me); /* this state machine object */
  2182. QS_FUN_PRE_(s-&gt;stateHandler); /* the current state */
  2183. QS_END_PRE_()
  2184. }
  2185. #endif /* Q_SPY */
  2186. else {
  2187. /* empty */
  2188. }</code>
  2189. </operation>
  2190. <!--${QEP::QMsm::getStateHandler_}-->
  2191. <operation name="getStateHandler_?def Q_SPY" type="QStateHandler" visibility="0x00" properties="0x01">
  2192. <documentation>/*! Implementation of getting the state handler in a ::QMsm subclass
  2193. * @public @memberof QMsm
  2194. */
  2195. /*! @public @memberof QMsm */</documentation>
  2196. <!--${QEP::QMsm::getStateHandler_::me}-->
  2197. <parameter name="me" type="QHsm * const"/>
  2198. <code>return me-&gt;state.obj-&gt;stateHandler;</code>
  2199. </operation>
  2200. <!--${QEP::QMsm::execTatbl_}-->
  2201. <operation name="execTatbl_" type="QState" visibility="0x02" properties="0x01">
  2202. <documentation>/*! Execute transition-action table
  2203. * @private @memberof QMsm
  2204. *
  2205. * @details
  2206. * Helper function to execute transition sequence in a transition-action table.
  2207. *
  2208. * @param[in,out] me current instance pointer (see @ref oop)
  2209. * @param[in] tatbl pointer to the transition-action table
  2210. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  2211. *
  2212. * @returns
  2213. * status of the last action from the transition-action table.
  2214. *
  2215. * @note
  2216. * This function is for internal use inside the QEP event processor and
  2217. * should **not** be called directly from the applications.
  2218. */
  2219. /*! @private @memberof QMsm */</documentation>
  2220. <!--${QEP::QMsm::execTatbl_::me}-->
  2221. <parameter name="me" type="QHsm * const"/>
  2222. <!--${QEP::QMsm::execTatbl_::tatbl}-->
  2223. <parameter name="tatbl" type="QMTranActTable const * const"/>
  2224. <!--${QEP::QMsm::execTatbl_::qs_id}-->
  2225. <parameter name="qs_id" type="uint_fast8_t const"/>
  2226. <code>#ifndef Q_SPY
  2227. Q_UNUSED_PAR(qs_id);
  2228. #endif
  2229. QState r = Q_RET_NULL;
  2230. QS_CRIT_STAT_
  2231. /*! @pre the transition-action table pointer must not be NULL */
  2232. Q_REQUIRE_ID(400, tatbl != (struct QMTranActTable *)0);
  2233. for (QActionHandler const *a = &amp;tatbl-&gt;act[0];
  2234. *a != Q_ACTION_CAST(0);
  2235. ++a)
  2236. {
  2237. r = (*(*a))(me); /* call the action through the 'a' pointer */
  2238. #ifdef Q_SPY
  2239. if (r == Q_RET_ENTRY) {
  2240. QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qs_id)
  2241. QS_OBJ_PRE_(me); /* this state machine object */
  2242. QS_FUN_PRE_(me-&gt;temp.obj-&gt;stateHandler);/*entered state */
  2243. QS_END_PRE_()
  2244. }
  2245. else if (r == Q_RET_EXIT) {
  2246. QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qs_id)
  2247. QS_OBJ_PRE_(me); /* this state machine object */
  2248. QS_FUN_PRE_(me-&gt;temp.obj-&gt;stateHandler); /* exited state */
  2249. QS_END_PRE_()
  2250. }
  2251. else if (r == Q_RET_TRAN_INIT) {
  2252. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  2253. QS_OBJ_PRE_(me); /* this state machine object */
  2254. QS_FUN_PRE_(tatbl-&gt;target-&gt;stateHandler); /* source */
  2255. QS_FUN_PRE_(me-&gt;temp.tatbl-&gt;target-&gt;stateHandler);/* target */
  2256. QS_END_PRE_()
  2257. }
  2258. else if (r == Q_RET_TRAN_EP) {
  2259. QS_BEGIN_PRE_(QS_QEP_TRAN_EP, qs_id)
  2260. QS_OBJ_PRE_(me); /* this state machine object */
  2261. QS_FUN_PRE_(tatbl-&gt;target-&gt;stateHandler); /* source */
  2262. QS_FUN_PRE_(me-&gt;temp.tatbl-&gt;target-&gt;stateHandler);/* target */
  2263. QS_END_PRE_()
  2264. }
  2265. else if (r == Q_RET_TRAN_XP) {
  2266. QS_BEGIN_PRE_(QS_QEP_TRAN_XP, qs_id)
  2267. QS_OBJ_PRE_(me); /* this state machine object */
  2268. QS_FUN_PRE_(tatbl-&gt;target-&gt;stateHandler); /* source */
  2269. QS_FUN_PRE_(me-&gt;temp.tatbl-&gt;target-&gt;stateHandler);/* target */
  2270. QS_END_PRE_()
  2271. }
  2272. else {
  2273. /* empty */
  2274. }
  2275. #endif /* Q_SPY */
  2276. }
  2277. me-&gt;state.obj = (r &gt;= Q_RET_TRAN)
  2278. ? me-&gt;temp.tatbl-&gt;target
  2279. : tatbl-&gt;target;
  2280. return r;</code>
  2281. </operation>
  2282. <!--${QEP::QMsm::exitToTranSource_}-->
  2283. <operation name="exitToTranSource_" type="void" visibility="0x02" properties="0x01">
  2284. <documentation>/*! Exit the current state up to the explicit transition source
  2285. * @private @memberof QMsm
  2286. *
  2287. * @details
  2288. * Static helper function to exit the current state configuration to the
  2289. * transition source, which in a hierarchical state machine might be a
  2290. * superstate of the current state.
  2291. *
  2292. * @param[in,out] me current instance pointer (see @ref oop)
  2293. * @param[in] cs pointer to the current state
  2294. * @param[in] ts pointer to the transition source state
  2295. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  2296. */
  2297. /*! @private @memberof QMsm */</documentation>
  2298. <!--${QEP::QMsm::exitToTranSource~::me}-->
  2299. <parameter name="me" type="QHsm * const"/>
  2300. <!--${QEP::QMsm::exitToTranSource~::cs}-->
  2301. <parameter name="cs" type="QMState const * const"/>
  2302. <!--${QEP::QMsm::exitToTranSource~::ts}-->
  2303. <parameter name="ts" type="QMState const * const"/>
  2304. <!--${QEP::QMsm::exitToTranSource~::qs_id}-->
  2305. <parameter name="qs_id" type="uint_fast8_t const"/>
  2306. <code>#ifndef Q_SPY
  2307. Q_UNUSED_PAR(qs_id);
  2308. #endif
  2309. /* exit states from the current state to the tran. source state */
  2310. QMState const *s = cs;
  2311. while (s != ts) {
  2312. /* exit action provided in state 's'? */
  2313. if (s-&gt;exitAction != Q_ACTION_CAST(0)) {
  2314. QS_CRIT_STAT_
  2315. (void)(*s-&gt;exitAction)(me); /* execute the exit action */
  2316. QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qs_id)
  2317. QS_OBJ_PRE_(me); /* this state machine object */
  2318. QS_FUN_PRE_(s-&gt;stateHandler); /* the exited state handler */
  2319. QS_END_PRE_()
  2320. }
  2321. s = s-&gt;superstate; /* advance to the superstate */
  2322. if (s == (QMState *)0) { /* reached the top of a submachine? */
  2323. s = me-&gt;temp.obj; /* the superstate from QM_SM_EXIT() */
  2324. Q_ASSERT_ID(510, s != (QMState *)0); /* must be valid */
  2325. }
  2326. }</code>
  2327. </operation>
  2328. <!--${QEP::QMsm::enterHistory_}-->
  2329. <operation name="enterHistory_" type="QState" visibility="0x02" properties="0x01">
  2330. <documentation>/*! Enter history of a composite state
  2331. * @private @memberof QMsm
  2332. *
  2333. * @details
  2334. * Static helper function to execute the segment of transition to history
  2335. * after entering the composite state and
  2336. *
  2337. * @param[in,out] me current instance pointer (see @ref oop)
  2338. * @param[in] hist pointer to the history substate
  2339. * @param[in] qs_id QS-id of this state machine (for QS local filter)
  2340. *
  2341. * @returns
  2342. * #Q_RET_TRAN_INIT, if an initial transition has been executed in the last
  2343. * entered state or #Q_RET_NULL if no such transition was taken.
  2344. */
  2345. /*! @private @memberof QMsm */</documentation>
  2346. <!--${QEP::QMsm::enterHistory_::me}-->
  2347. <parameter name="me" type="QHsm * const"/>
  2348. <!--${QEP::QMsm::enterHistory_::hist}-->
  2349. <parameter name="hist" type="QMState const *const"/>
  2350. <!--${QEP::QMsm::enterHistory_::qs_id}-->
  2351. <parameter name="qs_id" type="uint_fast8_t const"/>
  2352. <code>#ifndef Q_SPY
  2353. Q_UNUSED_PAR(qs_id);
  2354. #endif
  2355. QMState const *s = hist;
  2356. QMState const *ts = me-&gt;state.obj; /* transition source */
  2357. QMState const *epath[QMSM_MAX_ENTRY_DEPTH_];
  2358. QS_CRIT_STAT_
  2359. QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qs_id)
  2360. QS_OBJ_PRE_(me); /* this state machine object */
  2361. QS_FUN_PRE_(ts-&gt;stateHandler); /* source state handler */
  2362. QS_FUN_PRE_(hist-&gt;stateHandler); /* target state handler */
  2363. QS_END_PRE_()
  2364. int_fast8_t i = 0; /* transition entry path index */
  2365. while (s != ts) {
  2366. if (s-&gt;entryAction != Q_ACTION_CAST(0)) {
  2367. Q_ASSERT_ID(620, i &lt; QMSM_MAX_ENTRY_DEPTH_);
  2368. epath[i] = s;
  2369. ++i;
  2370. }
  2371. s = s-&gt;superstate;
  2372. if (s == (QMState *)0) {
  2373. ts = s; /* force exit from the for-loop */
  2374. }
  2375. }
  2376. /* retrace the entry path in reverse (desired) order... */
  2377. while (i &gt; 0) {
  2378. --i;
  2379. (void)(*epath[i]-&gt;entryAction)(me); /* run entry action in epath[i] */
  2380. QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qs_id)
  2381. QS_OBJ_PRE_(me);
  2382. QS_FUN_PRE_(epath[i]-&gt;stateHandler); /* entered state handler */
  2383. QS_END_PRE_()
  2384. }
  2385. me-&gt;state.obj = hist; /* set current state to the transition target */
  2386. /* initial tran. present? */
  2387. QState r;
  2388. if (hist-&gt;initAction != Q_ACTION_CAST(0)) {
  2389. r = (*hist-&gt;initAction)(me); /* execute the transition action */
  2390. }
  2391. else {
  2392. r = Q_RET_NULL;
  2393. }
  2394. return r;</code>
  2395. </operation>
  2396. </class>
  2397. </package>
  2398. <!--${QF-config}-->
  2399. <package name="QF-config" stereotype="0x02">
  2400. <!--${QF-config::QF_MAX_ACTIVE}-->
  2401. <attribute name="QF_MAX_ACTIVE?ndef QF_MAX_ACTIVE" type="unsigned" visibility="0x03" properties="0x00">
  2402. <documentation>/*! Maximum number of active objects (configurable value in qf_port.h)
  2403. * Valid values: [1U..64U]; default 32U
  2404. */</documentation>
  2405. <code>32U</code>
  2406. </attribute>
  2407. <!--${QF-config::QF_MAX_ACTIVE exceeds the maximu~}-->
  2408. <attribute name="QF_MAX_ACTIVE exceeds the maximum of 64U? (QF_MAX_ACTIVE &gt; 64U)" type="#error" visibility="0x04" properties="0x00"/>
  2409. <!--${QF-config::QF_MAX_TICK_RATE}-->
  2410. <attribute name="QF_MAX_TICK_RATE?ndef QF_MAX_TICK_RATE" type="unsigned" visibility="0x03" properties="0x00">
  2411. <documentation>/*! Maximum number of clock rates (configurable value in qf_port.h)
  2412. * Valid values: [0U..15U]; default 1U
  2413. */</documentation>
  2414. <code>1U</code>
  2415. </attribute>
  2416. <!--${QF-config::QF_MAX_TICK_RATE exceeds the max~}-->
  2417. <attribute name="QF_MAX_TICK_RATE exceeds the maximum of 15U? (QF_MAX_TICK_RATE &gt; 15U)" type="#error" visibility="0x04" properties="0x00"/>
  2418. <!--${QF-config::QF_MAX_EPOOL}-->
  2419. <attribute name="QF_MAX_EPOOL?ndef QF_MAX_EPOOL" type="unsigned" visibility="0x03" properties="0x00">
  2420. <documentation>/*! Maximum number of event pools (configurable value in qf_port.h)
  2421. * Valid values: [0U..15U]; default 3U
  2422. *
  2423. * @note
  2424. * #QF_MAX_EPOOL set to zero means that dynamic events are NOT configured
  2425. * and should not be used in the application.
  2426. */</documentation>
  2427. <code>3U</code>
  2428. </attribute>
  2429. <!--${QF-config::QF_MAX_EPOOL exceeds the maximum~}-->
  2430. <attribute name="QF_MAX_EPOOL exceeds the maximum of 15U? (QF_MAX_EPOOL &gt; 15U)" type="#error" visibility="0x04" properties="0x00"/>
  2431. <!--${QF-config::QF_TIMEEVT_CTR_SIZE}-->
  2432. <attribute name="QF_TIMEEVT_CTR_SIZE?ndef QF_TIMEEVT_CTR_SIZE" type="unsigned" visibility="0x03" properties="0x00">
  2433. <documentation>/*! Size of the QTimeEvt counter (configurable value in qf_port.h)
  2434. * Valid values: 1U, 2U, or 4U; default 4U
  2435. */</documentation>
  2436. <code>4U</code>
  2437. </attribute>
  2438. <!--${QF-config::QF_TIMEEVT_CTR_SIZE defined inco~}-->
  2439. <attribute name="QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U? (QF_TIMEEVT_CTR_SIZE != 1U) &amp;&amp; (QF_TIMEEVT_CTR_SIZE != 2U) &amp;&amp; (QF_TIMEEVT_CTR_SIZE != 4U)" type="#error" visibility="0x04" properties="0x00"/>
  2440. <!--${QF-config::QF_EVENT_SIZ_SIZE}-->
  2441. <attribute name="QF_EVENT_SIZ_SIZE?ndef QF_EVENT_SIZ_SIZE" type="unsigned" visibility="0x03" properties="0x00">
  2442. <documentation>/*! Size of the event-size (configurable value in qf_port.h)
  2443. * Valid values: 1U, 2U, or 4U; default 2U
  2444. */</documentation>
  2445. <code>2U</code>
  2446. </attribute>
  2447. <!--${QF-config::QF_EVENT_SIZ_SIZE defined incorr~}-->
  2448. <attribute name="QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U? (QF_EVENT_SIZ_SIZE != 1U) &amp;&amp; (QF_EVENT_SIZ_SIZE != 2U) &amp;&amp; (QF_EVENT_SIZ_SIZE != 4U)" type="#error" visibility="0x04" properties="0x00"/>
  2449. </package>
  2450. <!--${QF-types}-->
  2451. <package name="QF-types" stereotype="0x02">
  2452. <!--${QF-types::QPSetBits}-->
  2453. <attribute name="QPSetBits? (8U &lt; QF_MAX_ACTIVE) &amp;&amp; (QF_MAX_ACTIVE &lt;= 16U)" type="typedef uint16_t" visibility="0x04" properties="0x00">
  2454. <documentation>/*! bitmask for the internal representation of QPSet elements */</documentation>
  2455. </attribute>
  2456. <!--${QF-types::QPSetBits}-->
  2457. <attribute name="QPSetBits? (16 &lt; QF_MAX_ACTIVE)" type="typedef uint32_t" visibility="0x04" properties="0x00"/>
  2458. <!--${QF-types::QPSetBits}-->
  2459. <attribute name="QPSetBits? (QF_MAX_ACTIVE &lt;= 8U)" type="typedef uint8_t" visibility="0x04" properties="0x00"/>
  2460. <!--${QF-types::QTimeEvtCtr}-->
  2461. <attribute name="QTimeEvtCtr? (QF_TIMEEVT_CTR_SIZE == 2U)" type="typedef uint16_t" visibility="0x04" properties="0x00">
  2462. <documentation>/*! Data type to store the block-size defined based on the macro
  2463. * #QF_TIMEEVT_CTR_SIZE.
  2464. *
  2465. * @details
  2466. * The dynamic range of this data type determines the maximum block
  2467. * size that can be managed by the pool.
  2468. */</documentation>
  2469. </attribute>
  2470. <!--${QF-types::QTimeEvtCtr}-->
  2471. <attribute name="QTimeEvtCtr? (QF_TIMEEVT_CTR_SIZE == 4U)" type="typedef uint32_t" visibility="0x04" properties="0x00"/>
  2472. <!--${QF-types::QTimeEvtCtr}-->
  2473. <attribute name="QTimeEvtCtr? (QF_TIMEEVT_CTR_SIZE == 1U)" type="typedef uint8_t" visibility="0x04" properties="0x00"/>
  2474. <!--${QF-types::QF_LOG2}-->
  2475. <operation name="QF_LOG2?ndef QF_LOG2" type="uint_fast8_t" visibility="0x00" properties="0x00">
  2476. <specifiers>const</specifiers>
  2477. <documentation>/*! Log-base-2 calculation when hardware acceleration
  2478. * is NOT provided (#QF_LOG2 not defined).
  2479. * @static @private @memberof QF
  2480. */
  2481. /*! @static @private @memberof QF */</documentation>
  2482. <!--${QF-types::QF_LOG2::x}-->
  2483. <parameter name="x" type="QPSetBits"/>
  2484. <code>static uint8_t const log2LUT[16] = {
  2485. 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U,
  2486. 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U
  2487. };
  2488. uint_fast8_t n = 0U;
  2489. QPSetBits t;
  2490. #if (QF_MAX_ACTIVE &gt; 16U)
  2491. t = (QPSetBits)(x &gt;&gt; 16U);
  2492. if (t != 0U) {
  2493. n += 16U;
  2494. x = t;
  2495. }
  2496. #endif
  2497. #if (QF_MAX_ACTIVE &gt; 8U)
  2498. t = (x &gt;&gt; 8U);
  2499. if (t != 0U) {
  2500. n += 8U;
  2501. x = t;
  2502. }
  2503. #endif
  2504. t = (x &gt;&gt; 4U);
  2505. if (t != 0U) {
  2506. n += 4U;
  2507. x = t;
  2508. }
  2509. return n + log2LUT[x];</code>
  2510. </operation>
  2511. <!--${QF-types::QPrioSpec}-->
  2512. <attribute name="QPrioSpec" type="typedef uint16_t" visibility="0x04" properties="0x00">
  2513. <documentation>/*! Priority specification for Active Objects in QP
  2514. *
  2515. * @details
  2516. * Active Object priorities in QP are integer numbers in the range
  2517. * [1..#QF_MAX_ACTIVE], whereas the special priority number 0 is reserved
  2518. * for the lowest-priority idle thread. The QP framework uses the *direct*
  2519. * priority numbering, in which higher numerical values denote higher urgency.
  2520. * For example, an AO with priority 32 has higher urgency than an AO with
  2521. * priority 23.
  2522. *
  2523. * ::QPrioSpec allows an application developer to assign **two**
  2524. * priorities to a given AO (see also Q_PRIO()):
  2525. *
  2526. * 1. The &quot;QF-priority&quot;, which resides in the least-significant byte
  2527. * of the ::QPrioSpec data type. The &quot;QF-priority&quot; must be **unique**
  2528. * for each thread in the system and higher numerical values represent
  2529. * higher urgency (direct pirority numbering).
  2530. *
  2531. * 2. The &quot;preemption-threshold&quot; priority, which resides in the most-
  2532. * significant byte of the ::QPrioSpec data type. The second priority
  2533. * cannot be lower than the &quot;QF-priority&quot;, but does NOT need to be
  2534. * unuque.
  2535. *
  2536. * In the QP native preemptive kernels, like QK and QXK, the &quot;preemption-
  2537. * threshold&quot; priority is used as to implement the &quot;preemption-threshold
  2538. * scheduling&quot; (PTS). It determines the conditions under which a given
  2539. * thread can be *preempted* by other threads. Specifically, a given
  2540. * thread can be preempted only by another thread with a *higher*
  2541. * priority than the &quot;preemption-threshold&quot; of the original thread.
  2542. *
  2543. * ![QF-priority and preemption-threshold relations](qp-prio.png)
  2544. *
  2545. * @note
  2546. * For backwards-compatibility, ::QPrioSpec data type might contain only
  2547. * the &quot;QF-priority&quot; component (and the &quot;preemption-threshold&quot; component
  2548. * left at zero). In that case, the &quot;preemption-threshold&quot; will be assumed
  2549. * to be the same as the &quot;QF-priority&quot;. This corresponds exactly to the
  2550. * previous semantics of AO priority.
  2551. *
  2552. * @remark
  2553. * When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
  2554. * operating systems, sthe second priority can have different meaning,
  2555. * depending on the specific RTOS/GPOS used.
  2556. */</documentation>
  2557. </attribute>
  2558. <!--${QF-types::QSchedStatus}-->
  2559. <attribute name="QSchedStatus" type="typedef uint_fast16_t" visibility="0x04" properties="0x00">
  2560. <documentation>/*! The scheduler lock status used in some real-time kernels */</documentation>
  2561. </attribute>
  2562. <!--${QF-types::QPSet}-->
  2563. <class name="QPSet">
  2564. <documentation>/*! @brief Priority Set of up to #QF_MAX_ACTIVE elements
  2565. * @class QPSet
  2566. *
  2567. * @details
  2568. * The priority set represents the set of active objects that are ready to
  2569. * run and need to be considered by the scheduling algorithm. The set is
  2570. * capable of storing up to #QF_MAX_ACTIVE priority levels, which can be
  2571. * configured in the rage 1..64, inclusive.
  2572. */</documentation>
  2573. <!--${QF-types::QPSet::bits}-->
  2574. <attribute name="bits? (QF_MAX_ACTIVE &lt;= 32)" type="QPSetBits volatile" visibility="0x00" properties="0x00">
  2575. <documentation>/*! bitmask with a bit for each element */</documentation>
  2576. </attribute>
  2577. <!--${QF-types::QPSet::bits[2]}-->
  2578. <attribute name="bits[2]? (32 &lt; QF_MAX_ACTIVE)" type="QPSetBits volatile" visibility="0x00" properties="0x00">
  2579. <documentation>/*! bitmasks with a bit for each element */</documentation>
  2580. </attribute>
  2581. <!--${QF-types::QPSet::setEmpty}-->
  2582. <operation name="setEmpty" type="void" visibility="0x00" properties="0x02">
  2583. <documentation>/*! Make the priority set empty */</documentation>
  2584. <code>#if (QF_MAX_ACTIVE &lt;= 32)
  2585. me-&gt;bits = 0U;
  2586. #else
  2587. me-&gt;bits[0] = 0U;
  2588. me-&gt;bits[1] = 0U;
  2589. #endif</code>
  2590. </operation>
  2591. <!--${QF-types::QPSet::isEmpty}-->
  2592. <operation name="isEmpty" type="bool" visibility="0x00" properties="0x02">
  2593. <specifiers>const</specifiers>
  2594. <documentation>/*! Return 'true' if the priority set is empty */</documentation>
  2595. <code>#if (QF_MAX_ACTIVE &lt;= 32)
  2596. return (me-&gt;bits == 0U);
  2597. #else
  2598. return (me-&gt;bits[0] == 0U) ? (me-&gt;bits[1] == 0U) : false;
  2599. #endif</code>
  2600. </operation>
  2601. <!--${QF-types::QPSet::notEmpty}-->
  2602. <operation name="notEmpty" type="bool" visibility="0x00" properties="0x02">
  2603. <specifiers>const</specifiers>
  2604. <documentation>/*! Return 'true' if the priority set is NOT empty */</documentation>
  2605. <code>#if (QF_MAX_ACTIVE &lt;= 32)
  2606. return (me-&gt;bits != 0U);
  2607. #else
  2608. return (me-&gt;bits[0] != 0U) ? true : (me-&gt;bits[1] != 0U);
  2609. #endif</code>
  2610. </operation>
  2611. <!--${QF-types::QPSet::hasElement}-->
  2612. <operation name="hasElement" type="bool" visibility="0x00" properties="0x02">
  2613. <specifiers>const</specifiers>
  2614. <documentation>/*! Return 'true' if the priority set has the element n. */</documentation>
  2615. <!--${QF-types::QPSet::hasElement::n}-->
  2616. <parameter name="n" type="uint_fast8_t const"/>
  2617. <code>#if (QF_MAX_ACTIVE &lt;= 32U)
  2618. return (me-&gt;bits &amp; (1U &lt;&lt; (n - 1U))) != 0U;
  2619. #else
  2620. return (n &lt;= 32U)
  2621. ? ((me-&gt;bits[0] &amp; ((uint32_t)1U &lt;&lt; (n - 1U))) != 0U)
  2622. : ((me-&gt;bits[1] &amp; ((uint32_t)1U &lt;&lt; (n - 33U))) != 0U);
  2623. #endif</code>
  2624. </operation>
  2625. <!--${QF-types::QPSet::insert}-->
  2626. <operation name="insert" type="void" visibility="0x00" properties="0x02">
  2627. <documentation>/*! insert element `n` into the set (n = 1..::QF_MAX_ACTIVE) */</documentation>
  2628. <!--${QF-types::QPSet::insert::n}-->
  2629. <parameter name="n" type="uint_fast8_t const"/>
  2630. <code>#if (QF_MAX_ACTIVE &lt;= 32U)
  2631. me-&gt;bits = (me-&gt;bits | (1U &lt;&lt; (n - 1U)));
  2632. #else
  2633. if (n &lt;= 32U) {
  2634. me-&gt;bits[0] = (me-&gt;bits[0] | ((uint32_t)1U &lt;&lt; (n - 1U)));
  2635. }
  2636. else {
  2637. me-&gt;bits[1] = (me-&gt;bits[1] | ((uint32_t)1U &lt;&lt; (n - 33U)));
  2638. }
  2639. #endif</code>
  2640. </operation>
  2641. <!--${QF-types::QPSet::remove}-->
  2642. <operation name="remove" type="void" visibility="0x00" properties="0x02">
  2643. <documentation>/*! Remove element `n` from the set (n = 1U..::QF_MAX_ACTIVE) */</documentation>
  2644. <!--${QF-types::QPSet::remove::n}-->
  2645. <parameter name="n" type="uint_fast8_t const"/>
  2646. <code>#if (QF_MAX_ACTIVE &lt;= 32U)
  2647. me-&gt;bits = (me-&gt;bits &amp;
  2648. (QPSetBits)(~((QPSetBits)1U &lt;&lt; (n - 1U))));
  2649. #else
  2650. if (n &lt;= 32U) {
  2651. (me-&gt;bits[0] = (me-&gt;bits[0] &amp; ~((uint32_t)1U &lt;&lt; (n - 1U))));
  2652. }
  2653. else {
  2654. (me-&gt;bits[1] = (me-&gt;bits[1] &amp; ~((uint32_t)1U &lt;&lt; (n - 33U))));
  2655. }
  2656. #endif</code>
  2657. </operation>
  2658. <!--${QF-types::QPSet::findMax}-->
  2659. <operation name="findMax" type="uint_fast8_t" visibility="0x00" properties="0x02">
  2660. <specifiers>const</specifiers>
  2661. <documentation>/*! Find the maximum element in the set, returns zero if the set is empty */</documentation>
  2662. <code>#if (QF_MAX_ACTIVE &lt;= 32)
  2663. return QF_LOG2(me-&gt;bits);
  2664. #else
  2665. return (me-&gt;bits[1] != 0U)
  2666. ? (QF_LOG2(me-&gt;bits[1]) + 32U)
  2667. : (QF_LOG2(me-&gt;bits[0]));
  2668. #endif</code>
  2669. </operation>
  2670. </class>
  2671. <!--${QF-types::QSubscrList}-->
  2672. <attribute name="QSubscrList" type="typedef QPSet" visibility="0x04" properties="0x00">
  2673. <documentation>/*! Subscriber List (for publish-subscribe)
  2674. *
  2675. * @details
  2676. * This data type represents a set of Active Objects that subscribe to
  2677. * a given signal. The set is represented as priority-set, where each
  2678. * bit corresponds to the unique QF-priority of an AO (see ::QPrioSpec).
  2679. */</documentation>
  2680. </attribute>
  2681. </package>
  2682. <!--${QF-macros}-->
  2683. <package name="QF-macros" stereotype="0x02">
  2684. <!--${QF-macros::QF_NO_MARGIN}-->
  2685. <attribute name="QF_NO_MARGIN" type="uint_fast16_t" visibility="0x03" properties="0x00">
  2686. <documentation>/*! Special value of margin that causes asserting failure in case
  2687. * event allocation or event posting fails
  2688. */</documentation>
  2689. <code>((uint_fast16_t)0xFFFFU)</code>
  2690. </attribute>
  2691. <!--${QF-macros::Q_PRIO}-->
  2692. <operation name="Q_PRIO" type="QPrioSpec" visibility="0x03" properties="0x00">
  2693. <documentation>/*! Create a ::QPrioSpec object to specify priorty of an AO or a thread */</documentation>
  2694. <!--${QF-macros::Q_PRIO::prio_}-->
  2695. <parameter name="prio_" type="uint8_t"/>
  2696. <!--${QF-macros::Q_PRIO::pthre_}-->
  2697. <parameter name="pthre_" type="uint8_t"/>
  2698. <code>((QPrioSpec)((prio_) | ((pthre_) &lt;&lt; 8U)))</code>
  2699. </operation>
  2700. <!--${QF-macros::Q_NEW}-->
  2701. <operation name="Q_NEW?ndef Q_EVT_CTOR" type="void" visibility="0x03" properties="0x00">
  2702. <documentation>/*! Allocate a dynamic event (case when ::QEvt is a POD)
  2703. *
  2704. * @details
  2705. * The macro calls the internal QF function QF::newX_() with
  2706. * margin == ::QF_NO_MARGIN, which causes an assertion when the event
  2707. * cannot be successfully allocated.
  2708. *
  2709. * @param[in] evtT_ event type (class name) of the event to allocate
  2710. * @param[in] sig_ signal to assign to the newly allocated event
  2711. *
  2712. * @returns a valid event pointer cast to the type `evtT_`.
  2713. *
  2714. * @note
  2715. * If #Q_EVT_CTOR is defined, the Q_NEW() macro becomes variadic and
  2716. * takes all the arguments needed by the constructor of the event
  2717. * class being allocated. The constructor is then called by means
  2718. * of the placement-new operator.
  2719. *
  2720. * @usage
  2721. * The following example illustrates dynamic allocation of an event:
  2722. * @include qf_post.c
  2723. */</documentation>
  2724. <!--${QF-macros::Q_NEW::evtT_}-->
  2725. <parameter name="evtT_" type="&lt;event class&gt;"/>
  2726. <!--${QF-macros::Q_NEW::sig_}-->
  2727. <parameter name="sig_" type="QSignal"/>
  2728. <code>((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  2729. QF_NO_MARGIN, (enum_t)(sig_)))</code>
  2730. </operation>
  2731. <!--${QF-macros::Q_NEW}-->
  2732. <operation name="Q_NEW?def Q_EVT_CTOR" type="void" visibility="0x03" properties="0x00">
  2733. <documentation>/*! Asserting allocate a dynamic event
  2734. * (case when ::QEvt is not a POD)
  2735. */</documentation>
  2736. <!--${QF-macros::Q_NEW::evtT_}-->
  2737. <parameter name="evtT_" type="&lt;event class&gt;"/>
  2738. <!--${QF-macros::Q_NEW::sig_}-->
  2739. <parameter name="sig_" type="QSignal"/>
  2740. <!--${QF-macros::Q_NEW::...}-->
  2741. <parameter name="..." type="__VA_ARGS__"/>
  2742. <code>\
  2743. (evtT_##_ctor((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  2744. QF_NO_MARGIN, (sig_)), (enum_t)(sig_), ##__VA_ARGS__))</code>
  2745. </operation>
  2746. <!--${QF-macros::Q_NEW_X}-->
  2747. <operation name="Q_NEW_X?ndef Q_EVT_CTOR" type="void" visibility="0x03" properties="0x00">
  2748. <documentation>/*! Non-asserting allocate a dynamic event (case when ::QEvt is a POD).
  2749. *
  2750. * @details
  2751. * This macro allocates a new event and sets the pointer `e_`, while
  2752. * leaving at least `margin_` of events still available in the pool
  2753. *
  2754. * @param[out] e_ pointer to the newly allocated event
  2755. * @param[in] evtT_ event type (class name) of the event to allocate
  2756. * @param[in] margin_ number of events that must remain available
  2757. * in the given pool after this allocation. The
  2758. * special value ::QF_NO_MARGIN causes asserting
  2759. * failure in case event allocation fails.
  2760. * @param[in] sig_ signal to assign to the newly allocated event
  2761. *
  2762. * @returns an event pointer cast to the type `evtT_` or NULL if the
  2763. * event cannot be allocated with the specified `margin`.
  2764. *
  2765. * @note
  2766. * If #Q_EVT_CTOR is defined, the Q_NEW_X() macro becomes variadic and
  2767. * takes all the arguments needed by the constructor of the event
  2768. * class being allocated. The constructor is then called by means
  2769. * of the placement-new operator.
  2770. *
  2771. * @usage
  2772. * The following example illustrates dynamic allocation of an event:
  2773. * @include qf_postx.c
  2774. */</documentation>
  2775. <!--${QF-macros::Q_NEW_X::e_}-->
  2776. <parameter name="e_" type="&lt;QEvt *&gt;"/>
  2777. <!--${QF-macros::Q_NEW_X::evtT_}-->
  2778. <parameter name="evtT_" type="&lt;event class&gt;"/>
  2779. <!--${QF-macros::Q_NEW_X::margin_}-->
  2780. <parameter name="margin_" type="uint16_t"/>
  2781. <!--${QF-macros::Q_NEW_X::sig_}-->
  2782. <parameter name="sig_" type="QSignal"/>
  2783. <code>((e_) = \
  2784. (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  2785. (margin_), (enum_t)(sig_)))</code>
  2786. </operation>
  2787. <!--${QF-macros::Q_NEW_X}-->
  2788. <operation name="Q_NEW_X?def Q_EVT_CTOR" type="void" visibility="0x03" properties="0x00">
  2789. <documentation>/*! Non-asserting allocate a dynamic event
  2790. * (case when ::QEvt is not a POD)
  2791. */</documentation>
  2792. <!--${QF-macros::Q_NEW_X::e_}-->
  2793. <parameter name="e_" type="&lt;QEvt *&gt;"/>
  2794. <!--${QF-macros::Q_NEW_X::evtT_}-->
  2795. <parameter name="evtT_" type="&lt;event class&gt;"/>
  2796. <!--${QF-macros::Q_NEW_X::margin_}-->
  2797. <parameter name="margin_" type="uint16_t"/>
  2798. <!--${QF-macros::Q_NEW_X::sig_}-->
  2799. <parameter name="sig_" type="QSignal"/>
  2800. <!--${QF-macros::Q_NEW_X::...}-->
  2801. <parameter name="..." type="__VA_ARGS__"/>
  2802. <code>do { \
  2803. (e_) = (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  2804. (margin_), (enum_t)(sig_));\
  2805. if ((e_) != (evtT_ *)0) { \
  2806. evtT_##_ctor((e_), (enum_t)(sig_), ##__VA_ARGS__); \
  2807. } \
  2808. } while (false)</code>
  2809. </operation>
  2810. <!--${QF-macros::Q_NEW_REF}-->
  2811. <operation name="Q_NEW_REF" type="void" visibility="0x03" properties="0x00">
  2812. <documentation>/*! Create a new reference of the current event `e`
  2813. *
  2814. * @details
  2815. * The current event processed by an active object is available only for
  2816. * the duration of the run-to-completion (RTC) step. After that step, the
  2817. * current event is no longer available and the framework might recycle
  2818. * (garbage-collect) the event. The macro Q_NEW_REF() explicitly creates
  2819. * a new reference to the current event that can be stored and used beyond
  2820. * the current RTC step, until the reference is explicitly recycled by
  2821. * means of the macro Q_DELETE_REF().
  2822. *
  2823. * @param[in,out] evtRef_ event reference to create
  2824. * @param[in] evtT_ event type (class name) of the event reference
  2825. *
  2826. * @usage
  2827. * The example **defer** in the directory `examples/win32/defer` illustrates
  2828. * the use of Q_NEW_REF()
  2829. *
  2830. * @sa Q_DELETE_REF()
  2831. */</documentation>
  2832. <!--${QF-macros::Q_NEW_REF::evtRef_}-->
  2833. <parameter name="evtRef_" type="&lt;event class&gt;"/>
  2834. <!--${QF-macros::Q_NEW_REF::evtT_}-->
  2835. <parameter name="evtT_" type="&lt;event class&gt;"/>
  2836. <code>\
  2837. ((evtRef_) = (evtT_ const *)QF_newRef_(e, (evtRef_)))</code>
  2838. </operation>
  2839. <!--${QF-macros::Q_DELETE_REF}-->
  2840. <operation name="Q_DELETE_REF" type="void" visibility="0x03" properties="0x00">
  2841. <documentation>/*! Delete the event reference
  2842. *
  2843. * @details
  2844. * Every event reference created with the macro Q_NEW_REF() needs to be
  2845. * eventually deleted by means of the macro Q_DELETE_REF() to avoid leaking
  2846. * the event.
  2847. *
  2848. * @param[in,out] evtRef_ event reference to delete
  2849. *
  2850. * @usage
  2851. * The example **defer** in the directory `examples/win32/defer` illustrates
  2852. * the use of Q_DELETE_REF()
  2853. *
  2854. * @sa Q_NEW_REF()
  2855. */</documentation>
  2856. <!--${QF-macros::Q_DELETE_REF::evtRef_}-->
  2857. <parameter name="evtRef_" type="&lt;event class&gt;"/>
  2858. <code>do { \
  2859. QF_deleteRef_((evtRef_)); \
  2860. (evtRef_) = (void *)0; \
  2861. } while (false)</code>
  2862. </operation>
  2863. <!--${QF-macros::QACTIVE_START}-->
  2864. <operation name="QACTIVE_START" type="void" visibility="0x03" properties="0x00">
  2865. <documentation>/*! Virtual call to start an active object.
  2866. *
  2867. * @details
  2868. * Starts execution of the AO and registers the AO with the framework.
  2869. *
  2870. * @param[in,out] me_ current instance pointer (see @ref oop)
  2871. * @param[in] prioSpec_ priority specification for the Active Object
  2872. * @param[in] qSto_ pointer to the storage for the ring buffer of the
  2873. * event queue (used only with the built-in ::QEQueue)
  2874. * @param[in] qLen_ length of the event queue (in events)
  2875. * @param[in] stkSto_ pointer to the stack storage (used only when
  2876. * per-AO stack is needed)
  2877. * @param[in] stkSize_ stack size (in bytes)
  2878. * @param[in] par_ pointer to the additional port-specific parameter(s)
  2879. * (might be NULL).
  2880. * @usage
  2881. * @include qf_start.c
  2882. */</documentation>
  2883. <!--${QF-macros::QACTIVE_START::me_}-->
  2884. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  2885. <!--${QF-macros::QACTIVE_START::prioSpec_}-->
  2886. <parameter name="prioSpec_" type="QPrioSpec"/>
  2887. <!--${QF-macros::QACTIVE_START::qSto_}-->
  2888. <parameter name="qSto_" type="QEvt const * *"/>
  2889. <!--${QF-macros::QACTIVE_START::qLen_}-->
  2890. <parameter name="qLen_" type="uint_fast16_t"/>
  2891. <!--${QF-macros::QACTIVE_START::stkSto_}-->
  2892. <parameter name="stkSto_" type="void *"/>
  2893. <!--${QF-macros::QACTIVE_START::stkSize_}-->
  2894. <parameter name="stkSize_" type="uint_fast16_t"/>
  2895. <!--${QF-macros::QACTIVE_START::par_}-->
  2896. <parameter name="par_" type="void const *"/>
  2897. <code>do { \
  2898. Q_ASSERT((Q_HSM_UPCAST(me_))-&gt;vptr); \
  2899. (*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;start)( \
  2900. (QActive *)(me_), (prioSpec_), \
  2901. (qSto_), (qLen_), (stkSto_), (stkSize_), (par_)); \
  2902. } while (false)</code>
  2903. </operation>
  2904. <!--${QF-macros::QACTIVE_POST}-->
  2905. <operation name="QACTIVE_POST?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  2906. <documentation>/*! Invoke the direct event posting facility QActive_post_()
  2907. *
  2908. * @details
  2909. * This macro asserts if the queue overflows and cannot accept the event.
  2910. *
  2911. * @param[in,out] me_ current instance pointer (see @ref oop)
  2912. * @param[in] e_ pointer to the event to post
  2913. * @param[in] sender_ pointer to the sender object.
  2914. *
  2915. * @note
  2916. * The `sendedr_` parameter is actually only used when QS tracing
  2917. * is enabled (macro #Q_SPY is defined). When QS software tracing is
  2918. * disenabled, the QACTIVE_POST() macro does not pass the `sender_`
  2919. * parameter, so the overhead of passing this extra parameter is entirely
  2920. * avoided.
  2921. *
  2922. * @note the pointer to the sender object is not necessarily a pointer
  2923. * to an active object. In fact, if QACTIVE_POST() is called from an
  2924. * interrupt or other context, you can create a unique object just to
  2925. * unambiguously identify the sender of the event.
  2926. *
  2927. * @sa QActive_post_()
  2928. */</documentation>
  2929. <!--${QF-macros::QACTIVE_POST::me_}-->
  2930. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  2931. <!--${QF-macros::QACTIVE_POST::e_}-->
  2932. <parameter name="e_" type="QEvt const *"/>
  2933. <!--${QF-macros::QACTIVE_POST::sender_}-->
  2934. <parameter name="sender_" type="&lt;sender *&gt;"/>
  2935. <code>\
  2936. ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;post)(\
  2937. (me_), (e_), QF_NO_MARGIN, (sender_)))</code>
  2938. </operation>
  2939. <!--${QF-macros::QACTIVE_POST}-->
  2940. <operation name="QACTIVE_POST?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  2941. <!--${QF-macros::QACTIVE_POST::me_}-->
  2942. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  2943. <!--${QF-macros::QACTIVE_POST::e_}-->
  2944. <parameter name="e_" type="QEvt const *"/>
  2945. <!--${QF-macros::QACTIVE_POST::dummy}-->
  2946. <parameter name="dummy" type=""/>
  2947. <code>\
  2948. ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;post)(\
  2949. (me_), (e_), QF_NO_MARGIN, (void *)0))</code>
  2950. </operation>
  2951. <!--${QF-macros::QACTIVE_POST_X}-->
  2952. <operation name="QACTIVE_POST_X?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  2953. <documentation>/*! Invoke the direct event posting facility QActive_post_()
  2954. * without delivery guarantee
  2955. *
  2956. * @details
  2957. * This macro does not assert if the queue overflows and cannot accept
  2958. * the event with the specified margin of free slots remaining.
  2959. *
  2960. * @param[in,out] me_ current instance pointer (see @ref oop)
  2961. * @param[in] e_ pointer to the event to post
  2962. * @param[in] margin_ the minimum free slots in the queue, which
  2963. * must still be available after posting the event.
  2964. * The special value ::QF_NO_MARGIN causes
  2965. * asserting failure in case event posting fails.
  2966. * @param[in] sender_ pointer to the sender object.
  2967. *
  2968. * @returns
  2969. * 'true' if the posting succeeded, and 'false' if the posting
  2970. * failed due to insufficient margin of free entries available in
  2971. * the queue.
  2972. *
  2973. * @note
  2974. * The `sender_` parameter is actually only used when QS tracing
  2975. * is enabled (macro #Q_SPY is defined). When QS software tracing is
  2976. * disabled, the POST_X() macro does not pass the `sender_` parameter,
  2977. * so the overhead of passing this extra parameter is entirely avoided.
  2978. *
  2979. * @note
  2980. * The pointer to the sender object is not necessarily a pointer
  2981. * to an active object. In fact, if POST_X() is called from an
  2982. * interrupt or other context, you can create a unique object just to
  2983. * unambiguously identify the sender of the event.
  2984. *
  2985. * @usage
  2986. * @include qf_postx.c
  2987. */</documentation>
  2988. <!--${QF-macros::QACTIVE_POST_X::me_}-->
  2989. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  2990. <!--${QF-macros::QACTIVE_POST_X::e_}-->
  2991. <parameter name="e_" type="QEvt const *"/>
  2992. <!--${QF-macros::QACTIVE_POST_X::margin_}-->
  2993. <parameter name="margin_" type="uint16_t"/>
  2994. <!--${QF-macros::QACTIVE_POST_X::sender_}-->
  2995. <parameter name="sender_" type="&lt;sender *&gt;"/>
  2996. <code>\
  2997. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;post)((me_),\
  2998. (e_), (margin_), (sender_)))</code>
  2999. </operation>
  3000. <!--${QF-macros::QACTIVE_POST_X}-->
  3001. <operation name="QACTIVE_POST_X?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  3002. <!--${QF-macros::QACTIVE_POST_X::me_}-->
  3003. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  3004. <!--${QF-macros::QACTIVE_POST_X::e_}-->
  3005. <parameter name="e_" type="QEvt const *"/>
  3006. <!--${QF-macros::QACTIVE_POST_X::margin_}-->
  3007. <parameter name="margin_" type="uint16_t"/>
  3008. <!--${QF-macros::QACTIVE_POST_X::dummy}-->
  3009. <parameter name="dummy" type=""/>
  3010. <code>\
  3011. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;post)((me_),\
  3012. (e_), (margin_), (void *)0))</code>
  3013. </operation>
  3014. <!--${QF-macros::QACTIVE_POST_LIFO}-->
  3015. <operation name="QACTIVE_POST_LIFO" type="void" visibility="0x03" properties="0x00">
  3016. <documentation>/*! Virtual call to post an event to an active object using the
  3017. * Last-In-First-Out (LIFO) policy.
  3018. *
  3019. * @param[in,out] me_ current instance pointer (see @ref oop)
  3020. * @param[in] e_ pointer to the event to post
  3021. */
  3022. </documentation>
  3023. <!--${QF-macros::QACTIVE_POST_LIF~::me_}-->
  3024. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  3025. <!--${QF-macros::QACTIVE_POST_LIF~::e_}-->
  3026. <parameter name="e_" type="QEvt const *"/>
  3027. <code>\
  3028. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))-&gt;vptr))-&gt;postLIFO)( \
  3029. (me_), (e_)))</code>
  3030. </operation>
  3031. <!--${QF-macros::QACTIVE_PUBLISH}-->
  3032. <operation name="QACTIVE_PUBLISH?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  3033. <documentation>/*! Publish an event to all subscriber Active Objects.
  3034. *
  3035. * @details
  3036. * If #Q_SPY is defined, this macro calls QActive_publish_() with
  3037. * the `sender_` parameter to identify the publisher of the event.
  3038. * Otherwise, `sender_` is not used.
  3039. *
  3040. * @param[in] e_ pointer to the posted event
  3041. * @param[in] sender_ pointer to the sender object (actually used
  3042. * only when #Q_SPY is defined)
  3043. *
  3044. * @note
  3045. * The pointer to the `sender_` object is not necessarily a pointer
  3046. * to an active object. In fact, if QACTIVE_PUBLISH() is called from an
  3047. * interrupt or other context, you can create a unique object just to
  3048. * unambiguously identify the sender of the event.
  3049. *
  3050. * @sa QActive_publish_()
  3051. */</documentation>
  3052. <!--${QF-macros::QACTIVE_PUBLISH::e_}-->
  3053. <parameter name="e_" type="QEvt const *"/>
  3054. <!--${QF-macros::QACTIVE_PUBLISH::sender_}-->
  3055. <parameter name="sender_" type="&lt;void const *&gt;"/>
  3056. <code>\
  3057. (QActive_publish_((e_), (void const *)(sender_), (sender_)-&gt;prio))</code>
  3058. </operation>
  3059. <!--${QF-macros::QACTIVE_PUBLISH}-->
  3060. <operation name="QACTIVE_PUBLISH?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  3061. <!--${QF-macros::QACTIVE_PUBLISH::e_}-->
  3062. <parameter name="e_" type="QEvt const *"/>
  3063. <!--${QF-macros::QACTIVE_PUBLISH::dummy}-->
  3064. <parameter name="dummy" type=""/>
  3065. <code>(QActive_publish_((e_), (void *)0, 0U))</code>
  3066. </operation>
  3067. <!--${QF-macros::QTIMEEVT_TICK_X}-->
  3068. <operation name="QTIMEEVT_TICK_X?def Q_SPY" type="void" visibility="0x03" properties="0x00">
  3069. <documentation>/*! Invoke the system clock tick processing QTimeEvt_tick_()
  3070. *
  3071. * @details
  3072. * This macro is the recommended way of invoking clock tick processing,
  3073. * because it provides the vital information for software tracing and
  3074. * avoids any overhead when the tracing is disabled.
  3075. *
  3076. * @param[in] tickRate_ clock tick rate to be serviced through this call
  3077. * @param[in] sender_ pointer to the sender object. This parameter
  3078. * is actually only used when QS software tracing is enabled
  3079. * (macro #Q_SPY is defined)
  3080. * @note
  3081. * When QS software tracing is disabled, the macro calls QTimeEvt_tick_()
  3082. * without the `sender` parameter, so the overhead of passing this
  3083. * extra parameter is entirely avoided.
  3084. *
  3085. * @note
  3086. * The pointer to the sender object is not necessarily a pointer
  3087. * to an active object. In fact, when QTIMEEVT_TICK_X() is called from
  3088. * an interrupt, you would create a unique object just to unambiguously
  3089. * identify the ISR as the sender of the time events.
  3090. *
  3091. * @sa QTimeEvt_tick_()
  3092. */</documentation>
  3093. <!--${QF-macros::QTIMEEVT_TICK_X::tickRate_}-->
  3094. <parameter name="tickRate_" type="uint8_t"/>
  3095. <!--${QF-macros::QTIMEEVT_TICK_X::sender_}-->
  3096. <parameter name="sender_" type="&lt;sender *&gt;"/>
  3097. <code>\
  3098. (QTimeEvt_tick_((tickRate_), (sender_)))</code>
  3099. </operation>
  3100. <!--${QF-macros::QTIMEEVT_TICK_X}-->
  3101. <operation name="QTIMEEVT_TICK_X?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
  3102. <!--${QF-macros::QTIMEEVT_TICK_X::tickRate_}-->
  3103. <parameter name="tickRate_" type="uint8_t"/>
  3104. <!--${QF-macros::QTIMEEVT_TICK_X::dummy}-->
  3105. <parameter name="dummy" type=""/>
  3106. <code>\
  3107. (QTimeEvt_tick_((tickRate_), (void *)0))</code>
  3108. </operation>
  3109. <!--${QF-macros::QTIMEEVT_TICK}-->
  3110. <operation name="QTIMEEVT_TICK" type="void" visibility="0x03" properties="0x00">
  3111. <documentation>/*! Invoke the system clock tick processing
  3112. * for tick rate 0
  3113. */</documentation>
  3114. <!--${QF-macros::QTIMEEVT_TICK::sender_}-->
  3115. <parameter name="sender_" type="&lt;sender *&gt;"/>
  3116. <code>QTIMEEVT_TICK_X(0U, (sender_))</code>
  3117. </operation>
  3118. <!--${QF-macros::QF_CRIT_EXIT_NOP}-->
  3119. <operation name="QF_CRIT_EXIT_NOP?ndef QF_CRIT_EXIT_NOP" type="void" visibility="0x03" properties="0x00">
  3120. <documentation>/*! No-operation for exiting a critical section
  3121. *
  3122. * @details
  3123. * In some QF ports the critical section exit takes effect only on the
  3124. * next machine instruction. If this next instruction is another entry
  3125. * to a critical section, the critical section won't be really exited,
  3126. * but rather the two adjecent critical sections would be merged.
  3127. * The QF_CRIT_EXIT_NOP() macro contains minimal code required to
  3128. * prevent such merging of critical sections in such merging of
  3129. * critical sections in QF ports, in which it can occur.
  3130. */</documentation>
  3131. <code>((void)0)</code>
  3132. </operation>
  3133. <!--${QF-macros::QF_TICK_X}-->
  3134. <operation name="QF_TICK_X" type="void" visibility="0x03" properties="0x00">
  3135. <documentation>/*! Invoke the system clock tick processing
  3136. *
  3137. * @deprecated
  3138. * superseded by QTIMEEVT_TICK_X()
  3139. */</documentation>
  3140. <!--${QF-macros::QF_TICK_X::tickRate_}-->
  3141. <parameter name="tickRate_" type="uint8_t"/>
  3142. <!--${QF-macros::QF_TICK_X::sender_}-->
  3143. <parameter name="sender_" type="&lt;sender *&gt;"/>
  3144. <code>QTIMEEVT_TICK_X((tickRate_), (sender_))</code>
  3145. </operation>
  3146. <!--${QF-macros::QF_TICK}-->
  3147. <operation name="QF_TICK" type="void" visibility="0x03" properties="0x00">
  3148. <documentation>/*! Invoke the system clock tick processing for tick rate 0
  3149. *
  3150. * @deprecated
  3151. * superseded by QTIMEEVT_TICK()
  3152. */</documentation>
  3153. <!--${QF-macros::QF_TICK::sender_}-->
  3154. <parameter name="sender_" type="&lt;sender *&gt;"/>
  3155. <code>QTIMEEVT_TICK(sender_)</code>
  3156. </operation>
  3157. <!--${QF-macros::QF_PUBLISH}-->
  3158. <operation name="QF_PUBLISH" type="void" visibility="0x03" properties="0x00">
  3159. <documentation>/*! Publish an event to all subscriber Active Objects.
  3160. *
  3161. * @deprecated
  3162. * superseded by QACTIVE_PUBLISH()
  3163. */</documentation>
  3164. <!--${QF-macros::QF_PUBLISH::e_}-->
  3165. <parameter name="e_" type="QEvt const *"/>
  3166. <!--${QF-macros::QF_PUBLISH::sender_}-->
  3167. <parameter name="sender_" type="&lt;void const *&gt;"/>
  3168. <code>QACTIVE_PUBLISH((e_), (sender_))</code>
  3169. </operation>
  3170. </package>
  3171. <!--${QF}-->
  3172. <package name="QF" stereotype="0x05">
  3173. <!--${QF::QActive}-->
  3174. <class name="QActive" superclass="QEP::QHsm">
  3175. <documentation>/*! @brief Active object class (based on the QHsm implementation strategy)
  3176. * @class QActive
  3177. * @extends QHsm
  3178. *
  3179. * @details
  3180. * Active objects are encapsulated tasks (each containing an event queue and
  3181. * a state machine) that communicate with one another asynchronously by
  3182. * sending and receiving events. Within an active object, events are
  3183. * processed in a run-to-completion (RTC) fashion, while QF encapsulates
  3184. * all the details of thread-safe event exchange and queuing.&lt;br&gt;
  3185. *
  3186. * QActive represents an active object that uses the QHsm-style
  3187. * implementation strategy for state machines. This strategy is tailored
  3188. * to manual coding, but it is also supported by the QM modeling tool.
  3189. * The resulting code is slower than in the ::QMsm-style implementation
  3190. * strategy.
  3191. *
  3192. * @note
  3193. * QActive is not intended to be instantiated directly, but rather serves
  3194. * as the abstract base class for derivation of active objects in the
  3195. * applications.
  3196. *
  3197. * @sa QMActive
  3198. *
  3199. * @usage
  3200. * The following example illustrates how to derive an active object from
  3201. * QActive.
  3202. * @include qf_qactive.c
  3203. */</documentation>
  3204. <!--${QF::QActive::eQueue}-->
  3205. <attribute name="eQueue?def QF_EQUEUE_TYPE" type="QF_EQUEUE_TYPE" visibility="0x02" properties="0x00">
  3206. <documentation>/*! OS-dependent event-queue type
  3207. * @private @memberof QActive
  3208. *
  3209. * @details
  3210. * The type of the queue depends on the underlying operating system or
  3211. * a kernel. Many kernels support &quot;message queues&quot; that can be adapted
  3212. * to deliver QF events to the active object. Alternatively, QF provides
  3213. * a native event queue implementation that can be used as well.
  3214. *
  3215. * @note
  3216. * The native QF event queue is configured by defining the macro
  3217. * #QF_EQUEUE_TYPE as ::QEQueue.
  3218. */</documentation>
  3219. </attribute>
  3220. <!--${QF::QActive::osObject}-->
  3221. <attribute name="osObject?def QF_OS_OBJECT_TYPE" type="QF_OS_OBJECT_TYPE" visibility="0x02" properties="0x00">
  3222. <documentation>/*! OS-dependent per-thread object
  3223. * @private @memberof QActive
  3224. *
  3225. * @details
  3226. * This data might be used in various ways, depending on the QF port.
  3227. * In some ports me-&gt;osObject is used to block the calling thread when
  3228. * the native QF queue is empty. In other QF ports the OS-dependent
  3229. * object might be used differently.
  3230. */</documentation>
  3231. </attribute>
  3232. <!--${QF::QActive::thread}-->
  3233. <attribute name="thread?def QF_THREAD_TYPE" type="QF_THREAD_TYPE" visibility="0x02" properties="0x00">
  3234. <documentation>/*! OS-dependent representation of the thread of the active object
  3235. * @private @memberof QActive
  3236. *
  3237. * @details
  3238. * This data might be used in various ways, depending on the QF port.
  3239. * In some ports me-&gt;thread is used store the thread handle. In other ports
  3240. * me-&gt;thread can be a pointer to the Thread-Local-Storage (TLS).
  3241. */</documentation>
  3242. </attribute>
  3243. <!--${QF::QActive::prio}-->
  3244. <attribute name="prio" type="uint8_t" visibility="0x00" properties="0x00">
  3245. <documentation>/*! QF-priority [1..#QF_MAX_ACTIVE] of this AO.
  3246. * @private @memberof QActive
  3247. * @sa ::QPrioSpec
  3248. */</documentation>
  3249. </attribute>
  3250. <!--${QF::QActive::pthre}-->
  3251. <attribute name="pthre" type="uint8_t" visibility="0x00" properties="0x00">
  3252. <documentation>/*! preemption-threshold [1..#QF_MAX_ACTIVE] of this AO.
  3253. * @private @memberof QActive
  3254. * @sa ::QPrioSpec
  3255. */</documentation>
  3256. </attribute>
  3257. <!--${QF::QActive::active_[QF_MAX_ACTIVE + 1U]}-->
  3258. <attribute name="active_[QF_MAX_ACTIVE + 1U]" type="QActive *" visibility="0x00" properties="0x01">
  3259. <documentation>/*! Internal array of registered active objects
  3260. * @static @private @memberof QActive
  3261. */</documentation>
  3262. </attribute>
  3263. <!--${QF::QActive::subscrList_}-->
  3264. <attribute name="subscrList_" type="QSubscrList *" visibility="0x00" properties="0x01">
  3265. <documentation>/*! pointer to the array of all subscriber AOs for a given event signal.
  3266. * @static @private @memberof QActive
  3267. */</documentation>
  3268. </attribute>
  3269. <!--${QF::QActive::maxPubSignal_}-->
  3270. <attribute name="maxPubSignal_" type="enum_t" visibility="0x00" properties="0x01">
  3271. <documentation>/*! The maximum published signal (the size of the subscrList_ array)
  3272. * @static @private @memberof QActive
  3273. */</documentation>
  3274. </attribute>
  3275. <!--${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]}-->
  3276. <attribute name="registry_[QF_MAX_ACTIVE + 1U]" type="QActive *" visibility="0x02" properties="0x01">
  3277. <documentation>/*! Internal array of registered active objects
  3278. * @static @private @memberof QActive
  3279. */</documentation>
  3280. </attribute>
  3281. <!--${QF::QActive::ctor}-->
  3282. <operation name="ctor" type="void" visibility="0x01" properties="0x00">
  3283. <documentation>/*! ::QActive constructor (abstract base class)
  3284. * @protected @memberof QActive
  3285. *
  3286. * @param[in,out] me current instance pointer (see @ref oop)
  3287. * @param[in] initial pointer to the top-most initial state-handler
  3288. * function in the derived active object
  3289. * @sa QHsm_ctor()
  3290. */
  3291. /*! @protected @memberof QActive */</documentation>
  3292. <!--${QF::QActive::ctor::initial}-->
  3293. <parameter name="initial" type="QStateHandler const"/>
  3294. <code>static QActiveVtable const vtable = { /* QActive virtual table */
  3295. { &amp;QHsm_init_,
  3296. &amp;QHsm_dispatch_
  3297. #ifdef Q_SPY
  3298. ,&amp;QHsm_getStateHandler_
  3299. #endif
  3300. },
  3301. &amp;QActive_start_,
  3302. &amp;QActive_post_,
  3303. &amp;QActive_postLIFO_
  3304. };
  3305. /* clear the whole QActive object, so that the framework can start
  3306. * correctly even if the startup code fails to clear the uninitialized
  3307. * data (as is required by the C Standard).
  3308. */
  3309. QF_bzero(me, sizeof(*me));
  3310. QHsm_ctor(&amp;me-&gt;super, initial); /* explicitly call superclass' ctor */
  3311. me-&gt;super.vptr = &amp;vtable.super; /* hook the vptr to QActive vtable */</code>
  3312. </operation>
  3313. <!--${QF::QActive::start_}-->
  3314. <operation name="start_" type="void" visibility="0x02" properties="0x00">
  3315. <documentation>/*! Starts execution of an active object and registers the object
  3316. * with the framework
  3317. * @private @memberof QActive
  3318. *
  3319. * @details
  3320. * Starts execution of the AO and registers the AO with the framework.
  3321. *
  3322. * @param[in,out] me current instance pointer (see @ref oop)
  3323. * @param[in] prioSpec priority specification for the AO (See ::QPrioSpec)
  3324. * @param[in] qSto pointer to the storage for the ring buffer of the
  3325. * event queue
  3326. * @param[in] qLen length of the event queue [# ::QEvt* pointers]
  3327. * @param[in] stkSto pointer to the stack storage (might be NULL)
  3328. * @param[in] stkSize stack size [bytes]
  3329. * @param[in] par pointer to an extra parameter (might be NULL)
  3330. *
  3331. * @usage
  3332. * The following example shows starting an AO when a per-task stack
  3333. * is needed:
  3334. * @include qf_start.c
  3335. */
  3336. /*! @private @memberof QActive */</documentation>
  3337. <!--${QF::QActive::start_::prioSpec}-->
  3338. <parameter name="prioSpec" type="QPrioSpec const"/>
  3339. <!--${QF::QActive::start_::qSto}-->
  3340. <parameter name="qSto" type="QEvt const * * const"/>
  3341. <!--${QF::QActive::start_::qLen}-->
  3342. <parameter name="qLen" type="uint_fast16_t const"/>
  3343. <!--${QF::QActive::start_::stkSto}-->
  3344. <parameter name="stkSto" type="void * const"/>
  3345. <!--${QF::QActive::start_::stkSize}-->
  3346. <parameter name="stkSize" type="uint_fast16_t const"/>
  3347. <!--${QF::QActive::start_::par}-->
  3348. <parameter name="par" type="void const * const"/>
  3349. </operation>
  3350. <!--${QF::QActive::stop}-->
  3351. <operation name="stop?def QF_ACTIVE_STOP" type="void" visibility="0x01" properties="0x00">
  3352. <documentation>/*! Stops execution of an active object and removes it from the
  3353. * framework's supervision
  3354. * @protected @memberof QActive
  3355. *
  3356. * @param[in,out] me current instance pointer (see @ref oop)
  3357. *
  3358. * @attention
  3359. * QActive_stop() must be called only from the AO that is about
  3360. * to stop its execution. By that time, any pointers or references
  3361. * to the AO are considered invalid (dangling) and it becomes
  3362. * illegal for the rest of the application to post events to the AO.
  3363. */
  3364. /*! @protected @memberof QActive */</documentation>
  3365. </operation>
  3366. <!--${QF::QActive::post_}-->
  3367. <operation name="post_" type="bool" visibility="0x02" properties="0x00">
  3368. <documentation>/*! Posts an event `e` directly to the event queue of the active object
  3369. * using the First-In-First-Out (FIFO) policy.
  3370. * @private @memberof QActive
  3371. *
  3372. * @details
  3373. * Direct event posting is the simplest asynchronous communication
  3374. * method available in QF.
  3375. *
  3376. * @param[in,out] me current instance pointer (see @ref oop)
  3377. * @param[in] e pointer to the event to be posted
  3378. * @param[in] margin number of required free slots in the queue
  3379. * after posting the event or ::QF_NO_MARGIN.
  3380. * @param[in] sender pointer to a sender object (used in QS only)
  3381. *
  3382. * @returns
  3383. * 'true' (success) if the posting succeeded (with the provided margin)
  3384. * and 'false' (failure) when the posting fails.
  3385. *
  3386. * @precondition{qf_actq,100}
  3387. * - event pointer must be valid
  3388. *
  3389. * @postcondition{qf_actq,190}
  3390. * - the event must be posted if (`margin` == ::QF_NO_MARGIN)
  3391. *
  3392. * @attention
  3393. * For `margin` == ::QF_NO_MARGIN, this function will assert internally
  3394. * if the event posting fails. In that case, it is unnecessary to check
  3395. * the retrun value from this function.
  3396. *
  3397. * @note
  3398. * This function might be implemented differently in various QP/C++
  3399. * ports. The provided implementation assumes that the ::QEQueue
  3400. * class is used for the ::QActive event queue.
  3401. *
  3402. * @sa
  3403. * QActive_postLIFO()
  3404. *
  3405. * @usage
  3406. * @include qf_post.c
  3407. */
  3408. /*! @private @memberof QActive */</documentation>
  3409. <!--${QF::QActive::post_::e}-->
  3410. <parameter name="e" type="QEvt const * const"/>
  3411. <!--${QF::QActive::post_::margin}-->
  3412. <parameter name="margin" type="uint_fast16_t const"/>
  3413. <!--${QF::QActive::post_::sender}-->
  3414. <parameter name="sender" type="void const * const"/>
  3415. <code>#ifndef Q_SPY
  3416. Q_UNUSED_PAR(sender);
  3417. #endif
  3418. Q_REQUIRE_ID(100, e != (QEvt *)0);
  3419. QF_CRIT_STAT_
  3420. QF_CRIT_E_();
  3421. QEQueueCtr nFree = me-&gt;eQueue.nFree; /* get volatile into temporary */
  3422. /* test-probe#1 for faking queue overflow */
  3423. QS_TEST_PROBE_DEF(&amp;QActive_post_)
  3424. QS_TEST_PROBE_ID(1,
  3425. nFree = 0U;
  3426. )
  3427. bool status;
  3428. if (margin == QF_NO_MARGIN) {
  3429. if (nFree &gt; 0U) {
  3430. status = true; /* can post */
  3431. }
  3432. else {
  3433. status = false; /* cannot post */
  3434. Q_ERROR_CRIT_(190); /* must be able to post the event */
  3435. }
  3436. }
  3437. else if (nFree &gt; (QEQueueCtr)margin) {
  3438. status = true; /* can post */
  3439. }
  3440. else {
  3441. status = false; /* cannot post, but don't assert */
  3442. }
  3443. /* is it a dynamic event? */
  3444. if (e-&gt;poolId_ != 0U) {
  3445. QEvt_refCtr_inc_(e); /* increment the reference counter */
  3446. }
  3447. if (status) { /* can post the event? */
  3448. --nFree; /* one free entry just used up */
  3449. me-&gt;eQueue.nFree = nFree; /* update the original */
  3450. if (me-&gt;eQueue.nMin &gt; nFree) {
  3451. me-&gt;eQueue.nMin = nFree; /* increase minimum so far */
  3452. }
  3453. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST, me-&gt;prio)
  3454. QS_TIME_PRE_(); /* timestamp */
  3455. QS_OBJ_PRE_(sender); /* the sender object */
  3456. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  3457. QS_OBJ_PRE_(me); /* this active object (recipient) */
  3458. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  3459. QS_EQC_PRE_(nFree); /* number of free entries */
  3460. QS_EQC_PRE_(me-&gt;eQueue.nMin); /* min number of free entries */
  3461. QS_END_NOCRIT_PRE_()
  3462. #ifdef Q_UTEST
  3463. /* callback to examine the posted event under the same conditions
  3464. * as producing the #QS_QF_ACTIVE_POST trace record, which are:
  3465. * the local filter for this AO ('me-&gt;prio') is set
  3466. */
  3467. if (QS_LOC_CHECK_(me-&gt;prio)) {
  3468. /* callback to examine the posted event */
  3469. QS_onTestPost(sender, me, e, status);
  3470. }
  3471. #endif
  3472. /* empty queue? */
  3473. if (me-&gt;eQueue.frontEvt == (QEvt *)0) {
  3474. me-&gt;eQueue.frontEvt = e; /* deliver event directly */
  3475. QACTIVE_EQUEUE_SIGNAL_(me); /* signal the event queue */
  3476. }
  3477. /* queue is not empty, insert event into the ring-buffer */
  3478. else {
  3479. /* insert event into the ring buffer (FIFO) */
  3480. me-&gt;eQueue.ring[me-&gt;eQueue.head] = e;
  3481. if (me-&gt;eQueue.head == 0U) { /* need to wrap head? */
  3482. me-&gt;eQueue.head = me-&gt;eQueue.end; /* wrap around */
  3483. }
  3484. --me-&gt;eQueue.head; /* advance the head (counter clockwise) */
  3485. }
  3486. QF_CRIT_X_();
  3487. }
  3488. else { /* cannot post the event */
  3489. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, me-&gt;prio)
  3490. QS_TIME_PRE_(); /* timestamp */
  3491. QS_OBJ_PRE_(sender); /* the sender object */
  3492. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  3493. QS_OBJ_PRE_(me); /* this active object (recipient) */
  3494. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  3495. QS_EQC_PRE_(nFree); /* number of free entries */
  3496. QS_EQC_PRE_(margin); /* margin requested */
  3497. QS_END_NOCRIT_PRE_()
  3498. #ifdef Q_UTEST
  3499. /* callback to examine the posted event under the same conditions
  3500. * as producing the #QS_QF_ACTIVE_POST trace record, which are:
  3501. * the local filter for this AO ('me-&gt;prio') is set
  3502. */
  3503. if (QS_LOC_CHECK_(me-&gt;prio)) {
  3504. QS_onTestPost(sender, me, e, status);
  3505. }
  3506. #endif
  3507. QF_CRIT_X_();
  3508. #if (QF_MAX_EPOOL &gt; 0U)
  3509. QF_gc(e); /* recycle the event to avoid a leak */
  3510. #endif
  3511. }
  3512. return status;</code>
  3513. </operation>
  3514. <!--${QF::QActive::postLIFO_}-->
  3515. <operation name="postLIFO_" type="void" visibility="0x02" properties="0x00">
  3516. <documentation>/*! Posts an event `e` directly to the event queue of the active object
  3517. * using the Last-In-First-Out (LIFO) policy.
  3518. * @private @memberof QActive
  3519. *
  3520. * @details
  3521. * The LIFO policy should be used only for self-posting and with caution,
  3522. * because it alters order of events in the queue.
  3523. *
  3524. * @param[in,out] me current instance pointer (see @ref oop)
  3525. * @param[in] e pointer to the event to be posted
  3526. *
  3527. * @precondition{qf_actq,200}
  3528. * - the queue must be able to accept the event (cannot overflow)
  3529. *
  3530. * @note
  3531. * This function might be implemented differently in various QP/C++
  3532. * ports. The provided implementation assumes that the ::QEQueue
  3533. * class is used for the QActive event queue.
  3534. *
  3535. * @sa
  3536. * QActive_post()
  3537. */
  3538. /*! @private @memberof QActive */</documentation>
  3539. <!--${QF::QActive::postLIFO_::e}-->
  3540. <parameter name="e" type="QEvt const * const"/>
  3541. <code>QF_CRIT_STAT_
  3542. QF_CRIT_E_();
  3543. QEQueueCtr nFree = me-&gt;eQueue.nFree; /* get volatile into temporary */
  3544. /* test-probe#1 for faking queue overflow */
  3545. QS_TEST_PROBE_DEF(&amp;QActive_postLIFO_)
  3546. QS_TEST_PROBE_ID(1,
  3547. nFree = 0U;
  3548. )
  3549. Q_REQUIRE_CRIT_(200, nFree != 0U);
  3550. /* is it a dynamic event? */
  3551. if (e-&gt;poolId_ != 0U) {
  3552. QEvt_refCtr_inc_(e); /* increment the reference counter */
  3553. }
  3554. --nFree; /* one free entry just used up */
  3555. me-&gt;eQueue.nFree = nFree; /* update the original */
  3556. if (me-&gt;eQueue.nMin &gt; nFree) {
  3557. me-&gt;eQueue.nMin = nFree; /* update minimum so far */
  3558. }
  3559. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_LIFO, me-&gt;prio)
  3560. QS_TIME_PRE_(); /* timestamp */
  3561. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  3562. QS_OBJ_PRE_(me); /* this active object */
  3563. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_);/* pool Id &amp; ref Count */
  3564. QS_EQC_PRE_(nFree); /* # free entries */
  3565. QS_EQC_PRE_(me-&gt;eQueue.nMin); /* min number of free entries */
  3566. QS_END_NOCRIT_PRE_()
  3567. #ifdef Q_UTEST
  3568. /* callback to examine the posted event under the same conditions
  3569. * as producing the #QS_QF_ACTIVE_POST trace record, which are:
  3570. * the local filter for this AO ('me-&gt;prio') is set
  3571. */
  3572. if (QS_LOC_CHECK_(me-&gt;prio)) {
  3573. QS_onTestPost((QActive *)0, me, e, true);
  3574. }
  3575. #endif
  3576. QEvt const * const frontEvt = me-&gt;eQueue.frontEvt;
  3577. me-&gt;eQueue.frontEvt = e; /* deliver the event directly to the front */
  3578. /* was the queue empty? */
  3579. if (frontEvt == (QEvt *)0) {
  3580. QACTIVE_EQUEUE_SIGNAL_(me); /* signal the event queue */
  3581. }
  3582. /* queue was not empty, leave the event in the ring-buffer */
  3583. else {
  3584. ++me-&gt;eQueue.tail;
  3585. /* need to wrap the tail? */
  3586. if (me-&gt;eQueue.tail == me-&gt;eQueue.end) {
  3587. me-&gt;eQueue.tail = 0U; /* wrap around */
  3588. }
  3589. me-&gt;eQueue.ring[me-&gt;eQueue.tail] = frontEvt;
  3590. }
  3591. QF_CRIT_X_();</code>
  3592. </operation>
  3593. <!--${QF::QActive::get_}-->
  3594. <operation name="get_" type="QEvt const *" visibility="0x02" properties="0x00">
  3595. <documentation>/*! Get an event from the event queue of an active object
  3596. * @private @memberof QActive
  3597. *
  3598. * @details
  3599. * The behavior of this function depends on the kernel used in the
  3600. * QF port. For built-in kernels (Vanilla or QK) the function can be
  3601. * called only when the queue is not empty, so it doesn't block. For
  3602. * a blocking kernel/OS the function can block and wait for delivery
  3603. * of an event.
  3604. *
  3605. * @param[in,out] me current instance pointer (see @ref oop)
  3606. *
  3607. * @returns
  3608. * A pointer to the received event. The returned pointer is guaranteed
  3609. * to be valid (can't be NULL).
  3610. *
  3611. * @note
  3612. * This function might be implemented differently in various QP/C++
  3613. * ports. The provided implementation assumes that the ::QEQueue
  3614. * class is used for the QActive event queue.
  3615. */
  3616. /*! @private @memberof QActive */</documentation>
  3617. <code>QF_CRIT_STAT_
  3618. QF_CRIT_E_();
  3619. QACTIVE_EQUEUE_WAIT_(me); /* wait for event to arrive directly */
  3620. /* always remove event from the front */
  3621. QEvt const * const e = me-&gt;eQueue.frontEvt;
  3622. QEQueueCtr const nFree = me-&gt;eQueue.nFree + 1U; /* get volatile into tmp */
  3623. me-&gt;eQueue.nFree = nFree; /* update the number of free */
  3624. /* any events in the ring buffer? */
  3625. if (nFree &lt;= me-&gt;eQueue.end) {
  3626. /* remove event from the tail */
  3627. me-&gt;eQueue.frontEvt = me-&gt;eQueue.ring[me-&gt;eQueue.tail];
  3628. if (me-&gt;eQueue.tail == 0U) { /* need to wrap the tail? */
  3629. me-&gt;eQueue.tail = me-&gt;eQueue.end; /* wrap around */
  3630. }
  3631. --me-&gt;eQueue.tail;
  3632. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_GET, me-&gt;prio)
  3633. QS_TIME_PRE_(); /* timestamp */
  3634. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  3635. QS_OBJ_PRE_(me); /* this active object */
  3636. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  3637. QS_EQC_PRE_(nFree); /* # free entries */
  3638. QS_END_NOCRIT_PRE_()
  3639. }
  3640. else {
  3641. me-&gt;eQueue.frontEvt = (QEvt *)0; /* queue becomes empty */
  3642. /* all entries in the queue must be free (+1 for fronEvt) */
  3643. Q_ASSERT_CRIT_(310, nFree == (me-&gt;eQueue.end + 1U));
  3644. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_GET_LAST, me-&gt;prio)
  3645. QS_TIME_PRE_(); /* timestamp */
  3646. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  3647. QS_OBJ_PRE_(me); /* this active object */
  3648. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  3649. QS_END_NOCRIT_PRE_()
  3650. }
  3651. QF_CRIT_X_();
  3652. return e;</code>
  3653. </operation>
  3654. <!--${QF::QActive::subscribe}-->
  3655. <operation name="subscribe" type="void" visibility="0x00" properties="0x00">
  3656. <specifiers>const</specifiers>
  3657. <documentation>/*! Subscribes for delivery of signal `sig` to the active object
  3658. * @public @memberof QActive
  3659. *
  3660. * @details
  3661. * This function is part of the Publish-Subscribe event delivery
  3662. * mechanism available in QF. Subscribing to an event means that the
  3663. * framework will start posting all published events with a given signal
  3664. * `sig` to the event queue of the active object.
  3665. *
  3666. * @param[in,out] me current instance pointer (see @ref oop)
  3667. * @param[in] sig event signal to subscribe
  3668. *
  3669. * @precondition{qf_ps,300}
  3670. * - signal must be in range of subscribe scignals
  3671. * - subscriber AO priority must be in range
  3672. * - the AO must be registered (started)
  3673. *
  3674. * The following example shows how the Table active object subscribes
  3675. * to three signals in the initial transition:
  3676. * @include qf_subscribe.cpp
  3677. *
  3678. * @sa
  3679. * QActive_publish_(), QActive_unsubscribe(), and
  3680. * QActive_unsubscribeAll()
  3681. */
  3682. /*! @public @memberof QActive */</documentation>
  3683. <!--${QF::QActive::subscribe::sig}-->
  3684. <parameter name="sig" type="enum_t const"/>
  3685. <code>uint_fast8_t const p = (uint_fast8_t)me-&gt;prio;
  3686. Q_REQUIRE_ID(300, ((enum_t)Q_USER_SIG &lt;= sig)
  3687. &amp;&amp; (sig &lt; QActive_maxPubSignal_)
  3688. &amp;&amp; (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
  3689. &amp;&amp; (QActive_registry_[p] == me));
  3690. QF_CRIT_STAT_
  3691. QF_CRIT_E_();
  3692. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_SUBSCRIBE, me-&gt;prio)
  3693. QS_TIME_PRE_(); /* timestamp */
  3694. QS_SIG_PRE_(sig); /* the signal of this event */
  3695. QS_OBJ_PRE_(me); /* this active object */
  3696. QS_END_NOCRIT_PRE_()
  3697. /* set the priority bit */
  3698. QPSet_insert(&amp;QActive_subscrList_[sig], p);
  3699. QF_CRIT_X_();</code>
  3700. </operation>
  3701. <!--${QF::QActive::unsubscribe}-->
  3702. <operation name="unsubscribe" type="void" visibility="0x00" properties="0x00">
  3703. <specifiers>const</specifiers>
  3704. <documentation>/*! Unsubscribes from the delivery of signal `sig` to the active object
  3705. * @public @memberof QActive
  3706. *
  3707. * @details
  3708. * This function is part of the Publish-Subscribe event delivery
  3709. * mechanism available in QF. Un-subscribing from an event means that
  3710. * the framework will stop posting published events with a given signal
  3711. * `sig` to the event queue of the active object.
  3712. *
  3713. * @param[in,out] me current instance pointer (see @ref oop)
  3714. * @param[in] sig event signal to unsubscribe
  3715. *
  3716. * @precondition{qf_ps,400}
  3717. * - signal must be in range of subscribe scignals
  3718. * - subscriber AO priority must be in range
  3719. * - the AO must be registered (started)
  3720. *
  3721. * @note
  3722. * Due to the latency of event queues, an active object should NOT
  3723. * assume that a given signal `sig` will never be dispatched to the
  3724. * state machine of the active object after un-subscribing from that
  3725. * signal. The event might be already in the queue, or just about to
  3726. * be posted and the un-subscribe operation will not flush such events.
  3727. *
  3728. * @note
  3729. * Un-subscribing from a signal that has never been subscribed in the
  3730. * first place is considered an error and QF will raise an assertion.
  3731. *
  3732. * @sa
  3733. * QActive_publish_(), QActive_subscribe(), and
  3734. * QActive_unsubscribeAll()
  3735. */
  3736. /*! @public @memberof QActive */</documentation>
  3737. <!--${QF::QActive::unsubscribe::sig}-->
  3738. <parameter name="sig" type="enum_t const"/>
  3739. <code>uint_fast8_t const p = (uint_fast8_t)me-&gt;prio;
  3740. Q_REQUIRE_ID(400, ((enum_t)Q_USER_SIG &lt;= sig)
  3741. &amp;&amp; (sig &lt; QActive_maxPubSignal_)
  3742. &amp;&amp; (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
  3743. &amp;&amp; (QActive_registry_[p] == me));
  3744. QF_CRIT_STAT_
  3745. QF_CRIT_E_();
  3746. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, me-&gt;prio)
  3747. QS_TIME_PRE_(); /* timestamp */
  3748. QS_SIG_PRE_(sig); /* the signal of this event */
  3749. QS_OBJ_PRE_(me); /* this active object */
  3750. QS_END_NOCRIT_PRE_()
  3751. /* clear priority bit */
  3752. QPSet_remove(&amp;QActive_subscrList_[sig], p);
  3753. QF_CRIT_X_();</code>
  3754. </operation>
  3755. <!--${QF::QActive::unsubscribeAll}-->
  3756. <operation name="unsubscribeAll" type="void" visibility="0x00" properties="0x00">
  3757. <specifiers>const</specifiers>
  3758. <documentation>/*! Unsubscribes from the delivery of all signals to the active object
  3759. * @public @memberof QActive
  3760. *
  3761. * @details
  3762. * This function is part of the Publish-Subscribe event delivery
  3763. * mechanism available in QF. Un-subscribing from all events means that
  3764. * the framework will stop posting any published events to the event
  3765. * queue of the active object.
  3766. *
  3767. * @param[in,out] me current instance pointer (see @ref oop)
  3768. *
  3769. * @precondition{qf_ps,500}
  3770. * - subscriber AO priority must be in range
  3771. * - the AO must be registered (started)
  3772. *
  3773. * @note
  3774. * Due to the latency of event queues, an active object should NOT
  3775. * assume that no events will ever be dispatched to the state machine of
  3776. * the active object after un-subscribing from all events.
  3777. * The events might be already in the queue, or just about to be posted
  3778. * and the un-subscribe operation will not flush such events. Also, the
  3779. * alternative event-delivery mechanisms, such as direct event posting or
  3780. * time events, can be still delivered to the event queue of the active
  3781. * object.
  3782. *
  3783. * @sa
  3784. * QActive_publish_(), QActive_subscribe(), and QActive_unsubscribe()
  3785. */
  3786. /*! @public @memberof QActive */</documentation>
  3787. <code>uint_fast8_t const p = (uint_fast8_t)me-&gt;prio;
  3788. Q_REQUIRE_ID(500, (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
  3789. &amp;&amp; (QActive_registry_[p] == me));
  3790. for (enum_t sig = (enum_t)Q_USER_SIG; sig &lt; QActive_maxPubSignal_; ++sig) {
  3791. QF_CRIT_STAT_
  3792. QF_CRIT_E_();
  3793. if (QPSet_hasElement(&amp;QActive_subscrList_[sig], p)) {
  3794. QPSet_remove(&amp;QActive_subscrList_[sig], p);
  3795. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, me-&gt;prio)
  3796. QS_TIME_PRE_(); /* timestamp */
  3797. QS_SIG_PRE_(sig); /* the signal of this event */
  3798. QS_OBJ_PRE_(me); /* this active object */
  3799. QS_END_NOCRIT_PRE_()
  3800. }
  3801. QF_CRIT_X_();
  3802. /* prevent merging critical sections */
  3803. QF_CRIT_EXIT_NOP();
  3804. }</code>
  3805. </operation>
  3806. <!--${QF::QActive::psInit}-->
  3807. <operation name="psInit" type="void" visibility="0x00" properties="0x01">
  3808. <documentation>/*! Publish event to all subscribers of a given signal `e-&gt;sig`
  3809. * @static @public @memberof QActive
  3810. *
  3811. * @details
  3812. * This function posts (using the FIFO policy) the event @a e to **all**
  3813. * active objects that have subscribed to the signal @a e-&gt;sig, which is
  3814. * called _multicasting_. The multicasting performed in this function is
  3815. * very efficient based on reference-counting inside the published event
  3816. * (&quot;zero-copy&quot; event multicasting). This function is designed to be
  3817. * callable from any part of the system, including ISRs, device drivers,
  3818. * and active objects.
  3819. *
  3820. * @note
  3821. * To avoid any unexpected re-ordering of events posted into AO queues,
  3822. * the event multicasting is performed with scheduler **locked**.
  3823. * However, the scheduler is locked only up to the priority level of
  3824. * the highest-priority subscriber, so any AOs of even higher priority,
  3825. * which did not subscribe to this event are *not* affected.
  3826. */
  3827. /*! @static @public @memberof QActive */</documentation>
  3828. <!--${QF::QActive::psInit::subscrSto}-->
  3829. <parameter name="subscrSto" type="QSubscrList * const"/>
  3830. <!--${QF::QActive::psInit::maxSignal}-->
  3831. <parameter name="maxSignal" type="enum_t const"/>
  3832. <code>QActive_subscrList_ = subscrSto;
  3833. QActive_maxPubSignal_ = maxSignal;
  3834. /* zero the subscriber list, so that the framework can start correctly
  3835. * even if the startup code fails to clear the uninitialized data
  3836. * (as is required by the C Standard).
  3837. */
  3838. QF_bzero(subscrSto, (uint_fast16_t)maxSignal * sizeof(QSubscrList));</code>
  3839. </operation>
  3840. <!--${QF::QActive::publish_}-->
  3841. <operation name="publish_" type="void" visibility="0x02" properties="0x01">
  3842. <documentation>/*! Publish event to all subscribers of a given signal `e-&gt;sig`
  3843. * @static @private @memberof QActive
  3844. *
  3845. * @details
  3846. * This function posts (using the FIFO policy) the event @a e to **all**
  3847. * active objects that have subscribed to the signal @a e-&gt;sig, which is
  3848. * called _multicasting_. The multicasting performed in this function is
  3849. * very efficient based on reference-counting inside the published event
  3850. * (&quot;zero-copy&quot; event multicasting). This function is designed to be
  3851. * callable from any part of the system, including ISRs, device drivers,
  3852. * and active objects.
  3853. *
  3854. * @precondition{qf_ps,200}
  3855. * - the published signal must be within the configured range
  3856. *
  3857. * @note
  3858. * To avoid any unexpected re-ordering of events posted into AO queues,
  3859. * the event multicasting is performed with scheduler **locked**.
  3860. * However, the scheduler is locked only up to the priority level of
  3861. * the highest-priority subscriber, so any AOs of even higher priority,
  3862. * which did not subscribe to this event are *not* affected.
  3863. */
  3864. /*! @static @private @memberof QActive */</documentation>
  3865. <!--${QF::QActive::publish_::e}-->
  3866. <parameter name="e" type="QEvt const * const"/>
  3867. <!--${QF::QActive::publish_::sender}-->
  3868. <parameter name="sender" type="void const * const"/>
  3869. <!--${QF::QActive::publish_::qs_id}-->
  3870. <parameter name="qs_id" type="uint_fast8_t const"/>
  3871. <code>#ifndef Q_SPY
  3872. Q_UNUSED_PAR(sender);
  3873. Q_UNUSED_PAR(qs_id);
  3874. #endif
  3875. Q_REQUIRE_ID(200, e-&gt;sig &lt; (QSignal)QActive_maxPubSignal_);
  3876. QF_CRIT_STAT_
  3877. QF_CRIT_E_();
  3878. QS_BEGIN_NOCRIT_PRE_(QS_QF_PUBLISH, qs_id)
  3879. QS_TIME_PRE_(); /* the timestamp */
  3880. QS_OBJ_PRE_(sender); /* the sender object */
  3881. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  3882. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_);/* pool Id &amp; ref Count */
  3883. QS_END_NOCRIT_PRE_()
  3884. /* is it a dynamic event? */
  3885. if (e-&gt;poolId_ != 0U) {
  3886. /* NOTE: The reference counter of a dynamic event is incremented to
  3887. * prevent premature recycling of the event while the multicasting
  3888. * is still in progress. At the end of the function, the garbage
  3889. * collector step (QF_gc()) decrements the reference counter and
  3890. * recycles the event if the counter drops to zero. This covers the
  3891. * case when the event was published without any subscribers.
  3892. */
  3893. QEvt_refCtr_inc_(e);
  3894. }
  3895. /* make a local, modifiable copy of the subscriber list */
  3896. QPSet subscrList = QActive_subscrList_[e-&gt;sig];
  3897. QF_CRIT_X_();
  3898. if (QPSet_notEmpty(&amp;subscrList)) { /* any subscribers? */
  3899. /* the highest-prio subscriber */
  3900. uint_fast8_t p = QPSet_findMax(&amp;subscrList);
  3901. QActive *a = QActive_registry_[p];
  3902. QF_SCHED_STAT_
  3903. QF_SCHED_LOCK_(a-&gt;prio); /* lock the scheduler up to AO's prio */
  3904. do { /* loop over all subscribers */
  3905. /* the prio of the AO must be registered with the framework */
  3906. Q_ASSERT_ID(210, a != (QActive *)0);
  3907. /* QACTIVE_POST() asserts internally if the queue overflows */
  3908. QACTIVE_POST(a, e, sender);
  3909. QPSet_remove(&amp;subscrList, p); /* remove the handled subscriber */
  3910. if (QPSet_notEmpty(&amp;subscrList)) { /* still more subscribers? */
  3911. /* highest-prio subscriber */
  3912. p = QPSet_findMax(&amp;subscrList);
  3913. a = QActive_registry_[p];
  3914. }
  3915. else {
  3916. p = 0U; /* no more subscribers */
  3917. }
  3918. } while (p != 0U);
  3919. QF_SCHED_UNLOCK_(); /* unlock the scheduler */
  3920. }
  3921. /* The following garbage collection step decrements the reference counter
  3922. * and recycles the event if the counter drops to zero. This covers both
  3923. * cases when the event was published with or without any subscribers.
  3924. */
  3925. #if (QF_MAX_EPOOL &gt; 0U)
  3926. QF_gc(e); /* recycle the event to avoid a leak */
  3927. #endif</code>
  3928. </operation>
  3929. <!--${QF::QActive::defer}-->
  3930. <operation name="defer" type="bool" visibility="0x01" properties="0x00">
  3931. <specifiers>const</specifiers>
  3932. <documentation>/*! Defer an event to a given separate event queue
  3933. * @protected @memberof QActive
  3934. *
  3935. * @details
  3936. * This function is part of the event deferral support. An active object
  3937. * uses this function to defer an event `e` to the QF-supported native
  3938. * event queue `eq`. QF correctly accounts for another outstanding
  3939. * reference to the event and will not recycle the event at the end of
  3940. * the RTC step. Later, the active object might recall one event at a
  3941. * time from the event queue.
  3942. *
  3943. * @param[in] eq pointer to a &quot;raw&quot; thread-safe queue to recall
  3944. * an event from.
  3945. * @param[in] e pointer to the event to be deferred
  3946. *
  3947. * @returns
  3948. * 'true' (success) when the event could be deferred and 'false'
  3949. * (failure) if event deferral failed due to overflowing the queue.
  3950. *
  3951. * An active object can use multiple event queues to defer events of
  3952. * different kinds.
  3953. *
  3954. * @sa
  3955. * QActive_recall(), ::QEQueue, QActive_flushDeferred()
  3956. */
  3957. /*! @protected @memberof QActive */</documentation>
  3958. <!--${QF::QActive::defer::eq}-->
  3959. <parameter name="eq" type="QEQueue * const"/>
  3960. <!--${QF::QActive::defer::e}-->
  3961. <parameter name="e" type="QEvt const * const"/>
  3962. <code>bool const status = QEQueue_post(eq, e, 0U, me-&gt;prio);
  3963. QS_CRIT_STAT_
  3964. QS_BEGIN_PRE_(QS_QF_ACTIVE_DEFER, me-&gt;prio)
  3965. QS_TIME_PRE_(); /* time stamp */
  3966. QS_OBJ_PRE_(me); /* this active object */
  3967. QS_OBJ_PRE_(eq); /* the deferred queue */
  3968. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  3969. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  3970. QS_END_PRE_()
  3971. return status;</code>
  3972. </operation>
  3973. <!--${QF::QActive::recall}-->
  3974. <operation name="recall" type="bool" visibility="0x01" properties="0x00">
  3975. <documentation>/*! Recall a deferred event from a given event queue
  3976. * @protected @memberof QActive
  3977. *
  3978. * @details
  3979. * This function is part of the event deferral support. An active object
  3980. * uses this function to recall a deferred event from a given QF
  3981. * event queue. Recalling an event means that it is removed from the
  3982. * deferred event queue `eq` and posted (LIFO) to the event queue of
  3983. * the active object.
  3984. *
  3985. * @param[in] eq pointer to a &quot;raw&quot; thread-safe queue to recall
  3986. * an event from.
  3987. *
  3988. * @returns
  3989. * 'true' if an event has been recalled and 'false' if not.
  3990. *
  3991. * @note
  3992. * An active object can use multiple event queues to defer events of
  3993. * different kinds.
  3994. *
  3995. * @sa
  3996. * QActive_recall(), QActive_postLIFO_(), ::QEQueue
  3997. */
  3998. /*! @protected @memberof QActive */</documentation>
  3999. <!--${QF::QActive::recall::eq}-->
  4000. <parameter name="eq" type="QEQueue * const"/>
  4001. <code>QEvt const * const e = QEQueue_get(eq, me-&gt;prio);
  4002. bool recalled;
  4003. /* event available? */
  4004. if (e != (QEvt *)0) {
  4005. QF_CRIT_STAT_
  4006. QACTIVE_POST_LIFO(me, e); /* post it to the front of the AO's queue */
  4007. QF_CRIT_E_();
  4008. /* is it a dynamic event? */
  4009. if (e-&gt;poolId_ != 0U) {
  4010. /* after posting to the AO's queue the event must be referenced
  4011. * at least twice: once in the deferred event queue (eq-&gt;get()
  4012. * did NOT decrement the reference counter) and once in the
  4013. * AO's event queue.
  4014. */
  4015. Q_ASSERT_CRIT_(210, e-&gt;refCtr_ &gt;= 2U);
  4016. /* we need to decrement the reference counter once, to account
  4017. * for removing the event from the deferred event queue.
  4018. */
  4019. QEvt_refCtr_dec_(e); /* decrement the reference counter */
  4020. }
  4021. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_RECALL, me-&gt;prio)
  4022. QS_TIME_PRE_(); /* time stamp */
  4023. QS_OBJ_PRE_(me); /* this active object */
  4024. QS_OBJ_PRE_(eq); /* the deferred queue */
  4025. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  4026. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  4027. QS_END_NOCRIT_PRE_()
  4028. QF_CRIT_X_();
  4029. recalled = true;
  4030. }
  4031. else {
  4032. QS_CRIT_STAT_
  4033. QS_BEGIN_PRE_(QS_QF_ACTIVE_RECALL_ATTEMPT, me-&gt;prio)
  4034. QS_TIME_PRE_(); /* time stamp */
  4035. QS_OBJ_PRE_(me); /* this active object */
  4036. QS_OBJ_PRE_(eq); /* the deferred queue */
  4037. QS_END_PRE_()
  4038. recalled = false;
  4039. }
  4040. return recalled;</code>
  4041. </operation>
  4042. <!--${QF::QActive::flushDeferred}-->
  4043. <operation name="flushDeferred" type="uint_fast16_t" visibility="0x01" properties="0x00">
  4044. <specifiers>const</specifiers>
  4045. <documentation>/*! Flush the specified deferred queue 'eq'
  4046. * @protected @memberof QActive
  4047. *
  4048. * @details
  4049. * This function is part of the event deferral support. An active object
  4050. * can use this function to flush a given QF event queue. The function
  4051. * makes sure that the events are not leaked.
  4052. *
  4053. * @param[in] eq pointer to a &quot;raw&quot; thread-safe queue to flush.
  4054. *
  4055. * @returns
  4056. * the number of events actually flushed from the queue.
  4057. *
  4058. * @sa
  4059. * QActive_defer(), QActive_recall(), ::QEQueue
  4060. */
  4061. /*! @protected @memberof QActive */</documentation>
  4062. <!--${QF::QActive::flushDeferred::eq}-->
  4063. <parameter name="eq" type="QEQueue * const"/>
  4064. <code>uint_fast16_t n = 0U;
  4065. for (QEvt const *e = QEQueue_get(eq, me-&gt;prio);
  4066. e != (QEvt *)0;
  4067. e = QEQueue_get(eq, me-&gt;prio))
  4068. {
  4069. ++n; /* count the flushed event */
  4070. #if (QF_MAX_EPOOL &gt; 0U)
  4071. QF_gc(e); /* garbage collect */
  4072. #endif
  4073. }
  4074. return n;</code>
  4075. </operation>
  4076. <!--${QF::QActive::setAttr}-->
  4077. <operation name="setAttr" type="void" visibility="0x00" properties="0x00">
  4078. <documentation>/*! Generic setting of additional attributes (useful in QP ports)
  4079. * @public @memberof QActive
  4080. */
  4081. /*! @public @memberof QActive */</documentation>
  4082. <!--${QF::QActive::setAttr::attr1}-->
  4083. <parameter name="attr1" type="uint32_t"/>
  4084. <!--${QF::QActive::setAttr::attr2}-->
  4085. <parameter name="attr2" type="void const *"/>
  4086. </operation>
  4087. <!--${QF::QActive::thread_}-->
  4088. <operation name="thread_" type="void" visibility="0x02" properties="0x01">
  4089. <documentation>/*! Thread routine for executing an active object `act`
  4090. * @static @private @memberof QActive
  4091. */
  4092. /*! @static @private @memberof QActive */</documentation>
  4093. <!--${QF::QActive::thread_::act}-->
  4094. <parameter name="act" type="QActive *"/>
  4095. </operation>
  4096. <!--${QF::QActive::register_}-->
  4097. <operation name="register_" type="void" visibility="0x01" properties="0x00">
  4098. <documentation>/*! Register this active object to be managed by the framework
  4099. * @protected @memberof QActive
  4100. *
  4101. * @details
  4102. * This function adds a given active object to the active objects
  4103. * managed by the QF framework. It should not be called by the
  4104. * application directly, only through the function QActive::start().
  4105. *
  4106. * @param[in,out] me current instance pointer (see @ref oop)
  4107. *
  4108. * @precondition{qf_qact,100}
  4109. * - the &quot;QF-priority&quot; of the AO must be in range (must be set
  4110. * before calling QActive_register_())
  4111. * - the &quot;QF-priority&quot; must not be already in use (unique priority)
  4112. * - the &quot;QF-priority&quot; must not exceed the &quot;preemption-threshold&quot;
  4113. *
  4114. * @postcondition{qf_qact,190}
  4115. * - the preceding pre-thre must not exceed the preemption-threshold
  4116. * - the preemption-threshold must not exceed the next pre-thre
  4117. *
  4118. * @sa QActive_unregister_()
  4119. */
  4120. /*! @protected @memberof QActive */</documentation>
  4121. <code>if (me-&gt;pthre == 0U) { /* preemption-threshold not defined? */
  4122. me-&gt;pthre = me-&gt;prio; /* apply the default */
  4123. }
  4124. #ifndef Q_NASSERT
  4125. Q_REQUIRE_ID(100, (0U &lt; me-&gt;prio) &amp;&amp; (me-&gt;prio &lt;= QF_MAX_ACTIVE)
  4126. &amp;&amp; (QActive_registry_[me-&gt;prio] == (QActive *)0)
  4127. &amp;&amp; (me-&gt;prio &lt;= me-&gt;pthre));
  4128. uint8_t prev_thre = me-&gt;pthre;
  4129. uint8_t next_thre = me-&gt;pthre;
  4130. uint_fast8_t p;
  4131. for (p = (uint_fast8_t)me-&gt;prio - 1U; p &gt; 0U; --p) {
  4132. if (QActive_registry_[p] != (QActive *)0) {
  4133. prev_thre = QActive_registry_[p]-&gt;pthre;
  4134. break;
  4135. }
  4136. }
  4137. for (p = (uint_fast8_t)me-&gt;prio + 1U; p &lt;= QF_MAX_ACTIVE; ++p) {
  4138. if (QActive_registry_[p] != (QActive *)0) {
  4139. next_thre = QActive_registry_[p]-&gt;pthre;
  4140. break;
  4141. }
  4142. }
  4143. Q_ENSURE_ID(190, (prev_thre &lt;= me-&gt;pthre) &amp;&amp; (me-&gt;pthre &lt;= next_thre));
  4144. #endif // Q_NASSERT
  4145. QF_CRIT_STAT_
  4146. QF_CRIT_E_();
  4147. /* register the AO at the &quot;QF-priority&quot; */
  4148. QActive_registry_[me-&gt;prio] = me;
  4149. QF_CRIT_X_();</code>
  4150. </operation>
  4151. <!--${QF::QActive::unregister_}-->
  4152. <operation name="unregister_" type="void" visibility="0x01" properties="0x00">
  4153. <documentation>/*! Un-register the active object from the framework
  4154. * @protected @memberof QActive
  4155. *
  4156. * @details
  4157. * This function un-registers a given active object from the active objects
  4158. * managed by the QF framework. It should not be called by the QP ports.
  4159. *
  4160. * @param[in] me pointer to the active object to remove from the
  4161. * framework.
  4162. *
  4163. * @precondition{qf_qact,200}
  4164. * - the priority of the active object must not be zero and cannot
  4165. * exceed the maximum #QF_MAX_ACTIVE
  4166. * - the priority of the AO must be already registered.
  4167. *
  4168. * @note
  4169. * The active object that is removed from the framework can no longer
  4170. * participate in any event exchange.
  4171. *
  4172. * @sa QActive_register_()
  4173. */
  4174. /*! @protected @memberof QActive */</documentation>
  4175. <code>uint_fast8_t const p = (uint_fast8_t)me-&gt;prio;
  4176. Q_REQUIRE_ID(200, (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE)
  4177. &amp;&amp; (QActive_registry_[p] == me));
  4178. QF_CRIT_STAT_
  4179. QF_CRIT_E_();
  4180. QActive_registry_[p] = (QActive *)0; /* free-up the priority level */
  4181. me-&gt;super.state.fun = Q_STATE_CAST(0); /* invalidate the state */
  4182. QF_CRIT_X_();</code>
  4183. </operation>
  4184. <!--${QF::QActive::postFromISR_}-->
  4185. <operation name="postFromISR_?def QF_ISR_API" type="bool" visibility="0x02" properties="0x00">
  4186. <documentation>/*! the &quot;FromISR&quot; variant used in the QP port to &quot;FreeRTOS&quot;
  4187. * @private @memberof QActive
  4188. */
  4189. /*! @private @memberof QActive */</documentation>
  4190. <!--${QF::QActive::postFromISR_::e}-->
  4191. <parameter name="e" type="QEvt const * const"/>
  4192. <!--${QF::QActive::postFromISR_::margin}-->
  4193. <parameter name="margin" type="uint_fast16_t const"/>
  4194. <!--${QF::QActive::postFromISR_::par}-->
  4195. <parameter name="par" type="void *"/>
  4196. <!--${QF::QActive::postFromISR_::sender}-->
  4197. <parameter name="sender" type="void const * const"/>
  4198. </operation>
  4199. <!--${QF::QActive::publishFromISR_}-->
  4200. <operation name="publishFromISR_?def QF_ISR_API" type="void" visibility="0x00" properties="0x01">
  4201. <documentation>/*! the &quot;FromISR&quot; variant used in the QP port to &quot;FreeRTOS&quot;
  4202. * @static @private @memberof QActive
  4203. */
  4204. /*! @static @private @memberof QActive */</documentation>
  4205. <!--${QF::QActive::publishFromISR_::e}-->
  4206. <parameter name="e" type="QEvt const *"/>
  4207. <!--${QF::QActive::publishFromISR_::par}-->
  4208. <parameter name="par" type="void *"/>
  4209. <!--${QF::QActive::publishFromISR_::sender}-->
  4210. <parameter name="sender" type="void const *"/>
  4211. </operation>
  4212. </class>
  4213. <!--${QF::QActiveVtable}-->
  4214. <attribute name="QActiveVtable" type="typedef struct" visibility="0x04" properties="0x00">
  4215. <documentation>/*! @brief Virtual table for the QActive class */</documentation>
  4216. <code>{
  4217. struct QHsmVtable super; /*!&lt; @protected inherits ::QHsmVtable */
  4218. /*! @private virtual function to start the AO/thread
  4219. * @sa QACTIVE_START()
  4220. */
  4221. void (*start)(QActive * const me, QPrioSpec prio,
  4222. QEvt const * * const qSto, uint_fast16_t const qLen,
  4223. void * const stkSto, uint_fast16_t const stkSize,
  4224. void const * const par);
  4225. /*! @private virtual function to asynchronously post (FIFO)
  4226. * an event to the AO
  4227. * @sa QACTIVE_POST() and QACTIVE_POST_X()
  4228. */
  4229. bool (*post)(QActive * const me, QEvt const * const e,
  4230. uint_fast16_t const margin, void const * const sender);
  4231. /*! @private virtual function to asynchronously post (LIFO)
  4232. * an event to the AO
  4233. * @sa QACTIVE_POST_LIFO()
  4234. */
  4235. void (*postLIFO)(QActive * const me, QEvt const * const e);
  4236. } QActiveVtable;</code>
  4237. </attribute>
  4238. <!--${QF::QMActive}-->
  4239. <class name="QMActive" superclass="QF::QActive">
  4240. <documentation>/*! @brief Active object class (based on QMsm implementation strategy)
  4241. * @class QMActive
  4242. * @extends QActive
  4243. *
  4244. * @details
  4245. * ::QMActive represents an active object that uses the ::QMsm style state
  4246. * machine implementation strategy. This strategy requires the use of the
  4247. * QM modeling tool to generate state machine code automatically, but the
  4248. * code is faster than in the ::QHsm style implementation strategy and needs
  4249. * less run-time support (smaller event-processor).
  4250. *
  4251. * @note
  4252. * ::QMActive is not intended to be instantiated directly, but rather serves
  4253. * as the base class for derivation of active objects in the application.
  4254. *
  4255. * @trace
  4256. * @tr{AQP214}
  4257. *
  4258. * @usage
  4259. * The following example illustrates how to derive an active object from
  4260. * ::QMActive. Please note that the ::QActive member @c super is defined as
  4261. * the **first** member of the derived struct (see @ref oop).
  4262. * @include qf_qmactive.c
  4263. */</documentation>
  4264. <!--${QF::QMActive::ctor}-->
  4265. <operation name="ctor" type="void" visibility="0x01" properties="0x00">
  4266. <documentation>/*! Constructor of ::QMActive class.
  4267. * @protected @memberof QMActive
  4268. *
  4269. * @details
  4270. * Performs the first step of active object initialization by assigning
  4271. * the virtual pointer and calling the superclass constructor.
  4272. *
  4273. * @param[in,out] me current instance pointer (see @ref oop)
  4274. * @param[in] initial pointer to the event to be dispatched to the MSM
  4275. *
  4276. * @note Must be called only ONCE before QHSM_INIT().
  4277. *
  4278. * @sa QHsm_ctor()
  4279. */
  4280. /*! @protected @memberof QMActive */</documentation>
  4281. <!--${QF::QMActive::ctor::initial}-->
  4282. <parameter name="initial" type="QStateHandler const"/>
  4283. <code>static QMActiveVtable const vtable = { /* QMActive virtual table */
  4284. { &amp;QMsm_init_,
  4285. &amp;QMsm_dispatch_
  4286. #ifdef Q_SPY
  4287. ,&amp;QMsm_getStateHandler_
  4288. #endif
  4289. },
  4290. &amp;QActive_start_,
  4291. &amp;QActive_post_,
  4292. &amp;QActive_postLIFO_
  4293. };
  4294. /* clear the whole QMActive object, so that the framework can start
  4295. * correctly even if the startup code fails to clear the uninitialized
  4296. * data (as is required by the C Standard).
  4297. */
  4298. QF_bzero(me, sizeof(*me));
  4299. /*!
  4300. * @note
  4301. * ::QMActive inherits ::QActive, so by the @ref oop convention
  4302. * it should call the constructor of the superclass, i.e., QActive_ctor().
  4303. * However, this would pull in the QActiveVtable, which in turn will pull
  4304. * in the code for QHsm_init_() and QHsm_dispatch_() implemetations,
  4305. * which is expensive. To avoid this code size penalty, in case QHsm is
  4306. * not used in a given project, the call to QMsm_ctor() avoids pulling
  4307. * in the code for QHsm.
  4308. */
  4309. QMsm_ctor(QMSM_CAST_(&amp;me-&gt;super.super), initial);
  4310. me-&gt;super.super.vptr = &amp;vtable.super; /* hook vptr to QMActive vtable */</code>
  4311. </operation>
  4312. </class>
  4313. <!--${QF::QMActiveVtable}-->
  4314. <attribute name="QMActiveVtable" type="typedef QActiveVtable" visibility="0x04" properties="0x00">
  4315. <documentation>/*! @brief Virtual Table for the ::QMActive class (inherited
  4316. * from ::QActiveVtable)
  4317. *
  4318. * @note
  4319. * ::QMActive inherits ::QActive exactly, without adding any new virtual
  4320. * functions and therefore, ::QMActiveVtable is typedef'ed as ::QActiveVtable.
  4321. */</documentation>
  4322. </attribute>
  4323. <!--${QF::QTimeEvt}-->
  4324. <class name="QTimeEvt" superclass="QEP::QEvt">
  4325. <documentation>/*! @brief Time Event class
  4326. * @class QTimeEvt
  4327. * @extends QEvt
  4328. *
  4329. * @details
  4330. * Time events are special QF events equipped with the notion of time passage.
  4331. * The basic usage model of the time events is as follows. An active object
  4332. * allocates one or more ::QTimeEvt objects (provides the storage for them).
  4333. * When the active object needs to arrange for a timeout, it arms one of its
  4334. * time events to fire either just once (one-shot) or periodically. Each time
  4335. * event times out independently from the others, so a QF application can make
  4336. * multiple parallel timeout requests (from the same or different active
  4337. * objects). When QF detects that the appropriate moment has arrived, it
  4338. * inserts the time event directly into the recipient's event queue. The
  4339. * recipient then processes the time event just like any other event.
  4340. *
  4341. * Time events, as any other QF events derive from the ::QEvt base class.
  4342. * Typically, you will use a time event as-is, but you can also further
  4343. * derive more specialized time events from it by adding some more data
  4344. * members and/or specialized functions that operate on the specialized
  4345. * time events.
  4346. *
  4347. * Internally, the armed time events are organized into linked lists--one
  4348. * list for every supported ticking rate. These linked lists are scanned in
  4349. * every invocation of the QTIMEEVT_TICK_X() macro. Only armed (timing out)
  4350. * time events are in the list, so only armed time events consume CPU cycles.
  4351. *
  4352. * @sa ::QTimeEvt for the description of the data members
  4353. *
  4354. * @trace
  4355. * @tr{AQP215}
  4356. *
  4357. * @note
  4358. * QF manages the time events in the QTIMEEVT_TICK_X() macro, which must
  4359. * be called periodically, from the clock tick ISR or from other periodic
  4360. * source. QTIMEEVT_TICK_X() caYou might also use the special ::QTicker
  4361. * active object.
  4362. *
  4363. * @note
  4364. * Even though ::QTimeEvt is a subclass of ::QEvt, ::QTimeEvt instances can NOT
  4365. * be allocated dynamically from event pools. In other words, it is illegal to
  4366. * allocate ::QTimeEvt instances with the Q_NEW() or Q_NEW_X() macros.
  4367. */</documentation>
  4368. <!--${QF::QTimeEvt::next}-->
  4369. <attribute name="next" type="struct QTimeEvt * volatile" visibility="0x02" properties="0x00">
  4370. <documentation>/*! link to the next time event in the list
  4371. * @private @memberof QTimeEvt
  4372. */</documentation>
  4373. </attribute>
  4374. <!--${QF::QTimeEvt::act}-->
  4375. <attribute name="act" type="void * volatile" visibility="0x02" properties="0x00">
  4376. <documentation>/*! The active object that receives the time events
  4377. * @private @memberof QTimeEvt
  4378. */</documentation>
  4379. </attribute>
  4380. <!--${QF::QTimeEvt::ctr}-->
  4381. <attribute name="ctr" type="QTimeEvtCtr volatile" visibility="0x02" properties="0x00">
  4382. <documentation>/*! Internal down-counter of the time event.
  4383. * @private @memberof QTimeEvt
  4384. *
  4385. * @details
  4386. * The down-counter is decremented by 1 in every QTimeEvt_tick_() call.
  4387. * The time event fires (gets posted or published) when the down-counter
  4388. * reaches zero.
  4389. */</documentation>
  4390. </attribute>
  4391. <!--${QF::QTimeEvt::interval}-->
  4392. <attribute name="interval" type="QTimeEvtCtr" visibility="0x02" properties="0x00">
  4393. <documentation>/*! Interval for periodic time event (zero for one-shot time event)
  4394. * @private @memberof QTimeEvt
  4395. *
  4396. * @details
  4397. * The value of the interval is re-loaded to the internal down-counter
  4398. * when the time event expires, so that the time event keeps timing out
  4399. * periodically.
  4400. */</documentation>
  4401. </attribute>
  4402. <!--${QF::QTimeEvt::timeEvtHead_[QF_MAX_TICK_RATE]}-->
  4403. <attribute name="timeEvtHead_[QF_MAX_TICK_RATE]" type="QTimeEvt" visibility="0x00" properties="0x01">
  4404. <documentation>/*! heads of linked lists of time events, one for every clock tick rate */</documentation>
  4405. </attribute>
  4406. <!--${QF::QTimeEvt::ctorX}-->
  4407. <operation name="ctorX" type="void" visibility="0x00" properties="0x00">
  4408. <documentation>/*! The &quot;extended&quot; constructor to initialize a Time Event.
  4409. * @public @memberof QTimeEvt
  4410. *
  4411. * @details
  4412. * When creating a time event, you must commit it to a specific active object
  4413. * `act`, tick rate `tickRate` and event signal `sig`. You cannot change
  4414. * these attributes later.
  4415. *
  4416. * @param[in,out] me current instance pointer (see @ref oop)
  4417. * @param[in] act pointer to the active object associated with this
  4418. * time event. The time event will post itself to this AO.
  4419. * @param[in] sig signal to associate with this time event.
  4420. * @param[in] tickRate system clock tick rate to associate with this
  4421. * time event in the range [0..15].
  4422. *
  4423. * @precondition{qf_time,300}
  4424. * - the signal `sig` must be valid
  4425. * - the tick rate `tickRate` must be in range
  4426. *
  4427. * @note
  4428. * You should call QTimeEvt_ctorX() exactly once for every Time Event
  4429. * object **before** arming the Time Event. The ideal place for calling
  4430. * QTimeEvt_ctorX() is the constructor of the associated AO.
  4431. */
  4432. /*! @public @memberof QTimeEvt */</documentation>
  4433. <!--${QF::QTimeEvt::ctorX::act}-->
  4434. <parameter name="act" type="QActive * const"/>
  4435. <!--${QF::QTimeEvt::ctorX::sig}-->
  4436. <parameter name="sig" type="enum_t const"/>
  4437. <!--${QF::QTimeEvt::ctorX::tickRate}-->
  4438. <parameter name="tickRate" type="uint_fast8_t const"/>
  4439. <code>Q_REQUIRE_ID(300, (sig != 0)
  4440. &amp;&amp; (tickRate &lt; QF_MAX_TICK_RATE));
  4441. me-&gt;next = (QTimeEvt *)0;
  4442. me-&gt;ctr = 0U;
  4443. me-&gt;interval = 0U;
  4444. me-&gt;super.sig = (QSignal)sig;
  4445. /* For backwards compatibility with the deprecated QTimeEvt_ctor(),
  4446. * the active object pointer `act` can be uninitialized (NULL) and is
  4447. * NOT validated in the precondition. The active object pointer is
  4448. * validated in preconditions to QTimeEvt_armX() and QTimeEvt_rearm().
  4449. */
  4450. me-&gt;act = act;
  4451. /* Setting the POOL_ID event attribute to zero is correct only for
  4452. * events not allocated from event pools, which must be the case
  4453. * for Time Events.
  4454. */
  4455. me-&gt;super.poolId_ = 0U;
  4456. /* The refCtr_ attribute is not used in time events, so it is
  4457. * reused to hold the tickRate as well as other information
  4458. */
  4459. me-&gt;super.refCtr_ = (uint8_t)tickRate;</code>
  4460. </operation>
  4461. <!--${QF::QTimeEvt::armX}-->
  4462. <operation name="armX" type="void" visibility="0x00" properties="0x00">
  4463. <documentation>/*! Arm a time event (one shot or periodic) for direct event posting.
  4464. * @public @memberof QTimeEvt
  4465. *
  4466. * @details
  4467. * Arms a time event to fire in a specified number of clock ticks and with
  4468. * a specified interval. If the interval is zero, the time event is armed for
  4469. * one shot ('one-shot' time event). When the timeout expires, the time event
  4470. * gets directly posted (using the FIFO policy) into the event queue of the
  4471. * host active object. After posting, a one-shot time event gets automatically
  4472. * disarmed while a periodic time event (interval != 0) is automatically
  4473. * re-armed.
  4474. *
  4475. * A time event can be disarmed at any time by calling QTimeEvt_disarm().
  4476. * Also, a time event can be re-armed to fire in a different number of clock
  4477. * ticks by calling the QTimeEvt_rearm().
  4478. *
  4479. * @param[in,out] me current instance pointer (see @ref oop)
  4480. * @param[in] nTicks number of clock ticks (at the associated rate)
  4481. * to rearm the time event with.
  4482. * @param[in] interval interval (in clock ticks) for periodic time event.
  4483. *
  4484. * @precondition{qf_time,400}
  4485. * - the host AO must be valid,
  4486. * - the time eveht must be disarmed,
  4487. * - the number of clock ticks cannot be zero,
  4488. * - the signal must be valid.
  4489. *
  4490. * @attention
  4491. * Arming an already armed time event is __not__ allowed and is considered
  4492. * a programming error. The QP/C framework will assert if it detects an
  4493. * attempt to arm an already armed time event.
  4494. *
  4495. * @usage
  4496. * The following example shows how to arm a periodic time event as well as
  4497. * one-shot time event from a state machine of an active object:
  4498. * @include qf_tevt.c
  4499. */
  4500. /*! @public @memberof QTimeEvt */</documentation>
  4501. <!--${QF::QTimeEvt::armX::nTicks}-->
  4502. <parameter name="nTicks" type="QTimeEvtCtr const"/>
  4503. <!--${QF::QTimeEvt::armX::interval}-->
  4504. <parameter name="interval" type="QTimeEvtCtr const"/>
  4505. <code>uint_fast8_t const tickRate
  4506. = ((uint_fast8_t)me-&gt;super.refCtr_ &amp; QTE_TICK_RATE);
  4507. QTimeEvtCtr const ctr = me-&gt;ctr;
  4508. #ifdef Q_SPY
  4509. uint_fast8_t const qs_id = ((QActive *)(me-&gt;act))-&gt;prio;
  4510. #endif
  4511. Q_REQUIRE_ID(400, (me-&gt;act != (void *)0)
  4512. &amp;&amp; (ctr == 0U)
  4513. &amp;&amp; (nTicks != 0U)
  4514. &amp;&amp; (tickRate &lt; (uint_fast8_t)QF_MAX_TICK_RATE)
  4515. &amp;&amp; (me-&gt;super.sig &gt;= (QSignal)Q_USER_SIG));
  4516. #ifdef Q_NASSERT
  4517. Q_UNUSED_PAR(ctr);
  4518. #endif
  4519. QF_CRIT_STAT_
  4520. QF_CRIT_E_();
  4521. me-&gt;ctr = nTicks;
  4522. me-&gt;interval = interval;
  4523. /* is the time event unlinked?
  4524. * NOTE: For the duration of a single clock tick of the specified tick
  4525. * rate a time event can be disarmed and yet still linked into the list,
  4526. * because un-linking is performed exclusively in QTimeEvt_tick_().
  4527. */
  4528. if ((me-&gt;super.refCtr_ &amp; QTE_IS_LINKED) == 0U) {
  4529. me-&gt;super.refCtr_ |= QTE_IS_LINKED; /* mark as linked */
  4530. /* The time event is initially inserted into the separate
  4531. * &quot;freshly armed&quot; link list based on QTimeEvt_timeEvtHead_[tickRate].act.
  4532. * Only later, inside the QTimeEvt_tick_() function, the &quot;freshly armed&quot;
  4533. * list is appended to the main list of armed time events based on
  4534. * QTimeEvt_timeEvtHead_[tickRate].next. Again, this is to keep any
  4535. * changes to the main list exclusively inside the QTimeEvt_tick_()
  4536. * function.
  4537. */
  4538. me-&gt;next = (QTimeEvt *)QTimeEvt_timeEvtHead_[tickRate].act;
  4539. QTimeEvt_timeEvtHead_[tickRate].act = me;
  4540. }
  4541. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_ARM, qs_id)
  4542. QS_TIME_PRE_(); /* timestamp */
  4543. QS_OBJ_PRE_(me); /* this time event object */
  4544. QS_OBJ_PRE_(me-&gt;act); /* the active object */
  4545. QS_TEC_PRE_(nTicks); /* the number of ticks */
  4546. QS_TEC_PRE_(interval); /* the interval */
  4547. QS_U8_PRE_(tickRate); /* tick rate */
  4548. QS_END_NOCRIT_PRE_()
  4549. QF_CRIT_X_();</code>
  4550. </operation>
  4551. <!--${QF::QTimeEvt::disarm}-->
  4552. <operation name="disarm" type="bool" visibility="0x00" properties="0x00">
  4553. <documentation>/*! Disarm a time event.
  4554. * @public @memberof QTimeEvt
  4555. *
  4556. * @details
  4557. * Disarm the time event so it can be safely reused.
  4558. *
  4559. * @param[in,out] me current instance pointer (see @ref oop)
  4560. *
  4561. * @returns
  4562. * 'true' if the time event was truly disarmed, that is, it was running.
  4563. * The return of 'false' means that the time event was not truly disarmed,
  4564. * because it was not running. The 'false' return is only possible for one-
  4565. * shot time events that have been automatically disarmed upon expiration.
  4566. * In this case the 'false' return means that the time event has already
  4567. * been posted or published and should be expected in the active object's
  4568. * state machine.
  4569. *
  4570. * @note
  4571. * there is no harm in disarming an already disarmed time event
  4572. */
  4573. /*! @public @memberof QTimeEvt */</documentation>
  4574. <code>#ifdef Q_SPY
  4575. uint_fast8_t const qs_id = QACTIVE_CAST_(me-&gt;act)-&gt;prio;
  4576. #endif
  4577. QF_CRIT_STAT_
  4578. QF_CRIT_E_();
  4579. /* is the time event actually armed? */
  4580. bool wasArmed;
  4581. if (me-&gt;ctr != 0U) {
  4582. wasArmed = true;
  4583. me-&gt;super.refCtr_ |= QTE_WAS_DISARMED;
  4584. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_DISARM, qs_id)
  4585. QS_TIME_PRE_(); /* timestamp */
  4586. QS_OBJ_PRE_(me); /* this time event object */
  4587. QS_OBJ_PRE_(me-&gt;act); /* the target AO */
  4588. QS_TEC_PRE_(me-&gt;ctr); /* the number of ticks */
  4589. QS_TEC_PRE_(me-&gt;interval); /* the interval */
  4590. QS_U8_PRE_(me-&gt;super.refCtr_ &amp; QTE_TICK_RATE);
  4591. QS_END_NOCRIT_PRE_()
  4592. me-&gt;ctr = 0U; /* schedule removal from the list */
  4593. }
  4594. else { /* the time event was already disarmed automatically */
  4595. wasArmed = false;
  4596. me-&gt;super.refCtr_ &amp;= (uint8_t)(~QTE_WAS_DISARMED &amp; 0xFFU);
  4597. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_DISARM_ATTEMPT, qs_id)
  4598. QS_TIME_PRE_(); /* timestamp */
  4599. QS_OBJ_PRE_(me); /* this time event object */
  4600. QS_OBJ_PRE_(me-&gt;act); /* the target AO */
  4601. QS_U8_PRE_(me-&gt;super.refCtr_ &amp; QTE_TICK_RATE);
  4602. QS_END_NOCRIT_PRE_()
  4603. }
  4604. QF_CRIT_X_();
  4605. return wasArmed;</code>
  4606. </operation>
  4607. <!--${QF::QTimeEvt::rearm}-->
  4608. <operation name="rearm" type="bool" visibility="0x00" properties="0x00">
  4609. <documentation>/*! Rearm a time event.
  4610. * @public @memberof QTimeEvt
  4611. *
  4612. * @details
  4613. * Rearms a time event with a new number of clock ticks. This function can
  4614. * be used to adjust the current period of a periodic time event or to
  4615. * prevent a one-shot time event from expiring (e.g., a watchdog time event).
  4616. * Rearming a periodic timer leaves the interval unchanged and is a convenient
  4617. * method to adjust the phasing of a periodic time event.
  4618. *
  4619. * @param[in,out] me current instance pointer (see @ref oop)
  4620. * @param[in] nTicks number of clock ticks (at the associated rate)
  4621. * to rearm the time event with.
  4622. *
  4623. * @returns
  4624. * 'true' if the time event was running as it was re-armed. The 'false'
  4625. * return means that the time event was not truly rearmed because it was
  4626. * not running. The 'false' return is only possible for one-shot time events
  4627. * that have been automatically disarmed upon expiration. In this case the
  4628. * 'false' return means that the time event has already been posted or
  4629. * published and should be expected in the active object's state machine.
  4630. *
  4631. * @precondition{qf_time,600}
  4632. * - AO must be valid
  4633. * - tick rate must be in range
  4634. * - nTicks must not be zero,
  4635. * - the signal of this time event must be valid
  4636. */
  4637. /*! @public @memberof QTimeEvt */</documentation>
  4638. <!--${QF::QTimeEvt::rearm::nTicks}-->
  4639. <parameter name="nTicks" type="QTimeEvtCtr const"/>
  4640. <code>uint_fast8_t const tickRate
  4641. = (uint_fast8_t)me-&gt;super.refCtr_ &amp; QTE_TICK_RATE;
  4642. #ifdef Q_SPY
  4643. uint_fast8_t const qs_id = ((QActive *)(me-&gt;act))-&gt;prio;
  4644. #endif
  4645. Q_REQUIRE_ID(600, (me-&gt;act != (void *)0)
  4646. &amp;&amp; (tickRate &lt; QF_MAX_TICK_RATE)
  4647. &amp;&amp; (nTicks != 0U)
  4648. &amp;&amp; (me-&gt;super.sig &gt;= (QSignal)Q_USER_SIG));
  4649. QF_CRIT_STAT_
  4650. QF_CRIT_E_();
  4651. /* is the time evt not running? */
  4652. bool wasArmed;
  4653. if (me-&gt;ctr == 0U) {
  4654. wasArmed = false;
  4655. /* NOTE: For the duration of a single clock tick of the specified
  4656. * tick rate a time event can be disarmed and yet still linked into
  4657. * the list, because unlinking is performed exclusively in the
  4658. * QTimeEvt_tick_() function.
  4659. */
  4660. /* is the time event linked yet? */
  4661. if ((me-&gt;super.refCtr_ &amp; QTE_IS_LINKED) == 0U) {
  4662. me-&gt;super.refCtr_ |= QTE_IS_LINKED; /* mark as linked */
  4663. /* The time event is initially inserted into the separate
  4664. * &quot;freshly armed&quot; list based on QTimeEvt_timeEvtHead_[tickRate].act.
  4665. * Only later, inside the QTimeEvt_tick_() function, the &quot;freshly
  4666. * armed&quot; list is appended to the main list of armed time events
  4667. * based on QTimeEvt_timeEvtHead_[tickRate].next. Again, this is
  4668. * to keep any changes to the main list exclusively inside the
  4669. * QTimeEvt_tick_() function.
  4670. */
  4671. me-&gt;next = (QTimeEvt *)QTimeEvt_timeEvtHead_[tickRate].act;
  4672. QTimeEvt_timeEvtHead_[tickRate].act = me;
  4673. }
  4674. }
  4675. else { /* the time event was armed */
  4676. wasArmed = true;
  4677. }
  4678. me-&gt;ctr = nTicks; /* re-load the tick counter (shift the phasing) */
  4679. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_REARM, qs_id)
  4680. QS_TIME_PRE_(); /* timestamp */
  4681. QS_OBJ_PRE_(me); /* this time event object */
  4682. QS_OBJ_PRE_(me-&gt;act); /* the target AO */
  4683. QS_TEC_PRE_(me-&gt;ctr); /* the number of ticks */
  4684. QS_TEC_PRE_(me-&gt;interval); /* the interval */
  4685. QS_2U8_PRE_(tickRate, (wasArmed ? 1U : 0U));
  4686. QS_END_NOCRIT_PRE_()
  4687. QF_CRIT_X_();
  4688. return wasArmed;</code>
  4689. </operation>
  4690. <!--${QF::QTimeEvt::wasDisarmed}-->
  4691. <operation name="wasDisarmed" type="bool" visibility="0x00" properties="0x00">
  4692. <documentation>/*! Check the &quot;was disarmed&quot; status of a time event.
  4693. * @public @memberof QTimeEvt
  4694. *
  4695. * @details
  4696. * Useful for checking whether a one-shot time event was disarmed in the
  4697. * QTimeEvt_disarm() operation.
  4698. *
  4699. * @param[in,out] me current instance pointer (see @ref oop)
  4700. *
  4701. * @returns
  4702. * 'true' if the time event was truly disarmed in the last QTimeEvt_disarm()
  4703. * operation. The 'false' return means that the time event was not truly
  4704. * disarmed, because it was not running at that time. The 'false' return is
  4705. * only possible for one-shot time events that have been automatically disarmed
  4706. * upon expiration. In this case the 'false' return means that the time event
  4707. * has already been posted or published and should be expected in the active
  4708. * object's event queue.
  4709. *
  4710. * @note
  4711. * This function has a **side effect** of setting the &quot;was disarmed&quot; status,
  4712. * which means that the second and subsequent times this function is called
  4713. * the function will return 'true'.
  4714. */
  4715. /*! @public @memberof QTimeEvt */</documentation>
  4716. <code>uint8_t const wasDisarmed = (me-&gt;super.refCtr_ &amp; QTE_WAS_DISARMED);
  4717. me-&gt;super.refCtr_ |= QTE_WAS_DISARMED; /* mark as disarmed */
  4718. return wasDisarmed != 0U;</code>
  4719. </operation>
  4720. <!--${QF::QTimeEvt::currCtr}-->
  4721. <operation name="currCtr" type="QTimeEvtCtr" visibility="0x00" properties="0x00">
  4722. <specifiers>const</specifiers>
  4723. <documentation>/*! Get the current value of the down-counter of a time event.
  4724. * @public @memberof QTimeEvt
  4725. *
  4726. * @details
  4727. * Useful for checking how many clock ticks (at the tick rate associated
  4728. * with the time event) remain until the time event expires.
  4729. *
  4730. * @param[in,out] me current instance pointer (see @ref oop)
  4731. *
  4732. * @returns
  4733. * For an armed time event, the function returns the current value of the
  4734. * down-counter of the given time event. If the time event is not armed,
  4735. * the function returns 0.
  4736. *
  4737. * @note
  4738. * The function is thread-safe.
  4739. */
  4740. /*! @public @memberof QTimeEvt */</documentation>
  4741. <code>QF_CRIT_STAT_
  4742. QF_CRIT_E_();
  4743. QTimeEvtCtr const ret = me-&gt;ctr;
  4744. QF_CRIT_X_();
  4745. return ret;</code>
  4746. </operation>
  4747. <!--${QF::QTimeEvt::tick_}-->
  4748. <operation name="tick_" type="void" visibility="0x00" properties="0x01">
  4749. <documentation>/*! Processes all armed time events at every clock tick.
  4750. * @static @private @memberof QTimeEvt
  4751. *
  4752. * @details
  4753. * This internal helper function processes all armed ::QTimeEvt objects
  4754. * associated wit the tick rate `tickRate`.
  4755. *
  4756. * This function must be called periodically from a time-tick ISR or from
  4757. * a task so that QF can manage the timeout events assigned to the given
  4758. * system clock tick rate.
  4759. *
  4760. * @param[in] tickRate clock tick rate serviced in this call [1..15].
  4761. * @param[in] sender pointer to a sender object (only for QS tracing)
  4762. *
  4763. * @note
  4764. * this function should be called only via the macro QTIMEEVT_TICK_X()
  4765. *
  4766. * @note
  4767. * the calls to QTimeEvt_tick_() with different `tickRate` parameter can
  4768. * preempt each other. For example, higher clock tick rates might be
  4769. * serviced from interrupts while others from tasks (active objects).
  4770. *
  4771. * @sa ::QTimeEvt.
  4772. */
  4773. /*! @static @private @memberof QTimeEvt */</documentation>
  4774. <!--${QF::QTimeEvt::tick_::tickRate}-->
  4775. <parameter name="tickRate" type="uint_fast8_t const"/>
  4776. <!--${QF::QTimeEvt::tick_::sender}-->
  4777. <parameter name="sender" type="void const * const"/>
  4778. <code>#ifndef Q_SPY
  4779. Q_UNUSED_PAR(sender);
  4780. #endif
  4781. QTimeEvt *prev = &amp;QTimeEvt_timeEvtHead_[tickRate];
  4782. QF_CRIT_STAT_
  4783. QF_CRIT_E_();
  4784. QS_BEGIN_NOCRIT_PRE_(QS_QF_TICK, 0U)
  4785. ++prev-&gt;ctr;
  4786. QS_TEC_PRE_(prev-&gt;ctr); /* tick ctr */
  4787. QS_U8_PRE_(tickRate); /* tick rate */
  4788. QS_END_NOCRIT_PRE_()
  4789. /* scan the linked-list of time events at this rate... */
  4790. for (;;) {
  4791. QTimeEvt *t = prev-&gt;next; /* advance down the time evt. list */
  4792. /* end of the list? */
  4793. if (t == (QTimeEvt *)0) {
  4794. /* any new time events armed since the last QTimeEvt_tick_()? */
  4795. if (QTimeEvt_timeEvtHead_[tickRate].act != (void *)0) {
  4796. /* sanity check */
  4797. Q_ASSERT_CRIT_(110, prev != (QTimeEvt *)0);
  4798. prev-&gt;next = (QTimeEvt *)QTimeEvt_timeEvtHead_[tickRate].act;
  4799. QTimeEvt_timeEvtHead_[tickRate].act = (void *)0;
  4800. t = prev-&gt;next; /* switch to the new list */
  4801. }
  4802. else {
  4803. break; /* all currently armed time evts. processed */
  4804. }
  4805. }
  4806. /* time event scheduled for removal? */
  4807. if (t-&gt;ctr == 0U) {
  4808. prev-&gt;next = t-&gt;next;
  4809. /* mark time event 't' as NOT linked */
  4810. t-&gt;super.refCtr_ &amp;= (uint8_t)(~QTE_IS_LINKED &amp; 0xFFU);
  4811. /* do NOT advance the prev pointer */
  4812. QF_CRIT_X_(); /* exit crit. section to reduce latency */
  4813. /* prevent merging critical sections, see NOTE1 below */
  4814. QF_CRIT_EXIT_NOP();
  4815. }
  4816. else {
  4817. --t-&gt;ctr;
  4818. /* is time event about to expire? */
  4819. if (t-&gt;ctr == 0U) {
  4820. QActive * const act = (QActive *)t-&gt;act;
  4821. /* periodic time evt? */
  4822. if (t-&gt;interval != 0U) {
  4823. t-&gt;ctr = t-&gt;interval; /* rearm the time event */
  4824. prev = t; /* advance to this time event */
  4825. }
  4826. /* one-shot time event: automatically disarm */
  4827. else {
  4828. prev-&gt;next = t-&gt;next;
  4829. /* mark time event 't' as NOT linked */
  4830. t-&gt;super.refCtr_ &amp;= (uint8_t)(~QTE_IS_LINKED &amp; 0xFFU);
  4831. /* do NOT advance the prev pointer */
  4832. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act-&gt;prio)
  4833. QS_OBJ_PRE_(t); /* this time event object */
  4834. QS_OBJ_PRE_(act); /* the target AO */
  4835. QS_U8_PRE_(tickRate); /* tick rate */
  4836. QS_END_NOCRIT_PRE_()
  4837. }
  4838. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_POST, act-&gt;prio)
  4839. QS_TIME_PRE_(); /* timestamp */
  4840. QS_OBJ_PRE_(t); /* the time event object */
  4841. QS_SIG_PRE_(t-&gt;super.sig); /* signal of this time event */
  4842. QS_OBJ_PRE_(act); /* the target AO */
  4843. QS_U8_PRE_(tickRate); /* tick rate */
  4844. QS_END_NOCRIT_PRE_()
  4845. QF_CRIT_X_(); /* exit critical section before posting */
  4846. /* QACTIVE_POST() asserts internally if the queue overflows */
  4847. QACTIVE_POST(act, &amp;t-&gt;super, sender);
  4848. }
  4849. else {
  4850. prev = t; /* advance to this time event */
  4851. QF_CRIT_X_(); /* exit crit. section to reduce latency */
  4852. /* prevent merging critical sections
  4853. * In some QF ports the critical section exit takes effect only
  4854. * on the next machine instruction. If this case, the next
  4855. * instruction is another entry to a critical section, the
  4856. * critical section won't be really exited, but rather the
  4857. * two adjacent critical sections would be merged. The
  4858. * QF_CRIT_EXIT_NOP() macro contains minimal code required
  4859. * to prevent such merging of critical sections in QF ports,
  4860. * in which it can occur.
  4861. */
  4862. QF_CRIT_EXIT_NOP();
  4863. }
  4864. }
  4865. QF_CRIT_E_(); /* re-enter crit. section to continue */
  4866. }
  4867. QF_CRIT_X_();</code>
  4868. </operation>
  4869. <!--${QF::QTimeEvt::tick1_}-->
  4870. <operation name="tick1_?def Q_UTEST" type="void" visibility="0x00" properties="0x01">
  4871. <documentation>/*! Processes one clock tick for QUTest
  4872. * @static @private @memberof QTimeEvt
  4873. */
  4874. /*! @static @private @memberof QTimeEvt */</documentation>
  4875. <!--${QF::QTimeEvt::tick1_::tickRate}-->
  4876. <parameter name="tickRate" type="uint_fast8_t const"/>
  4877. <!--${QF::QTimeEvt::tick1_::sender}-->
  4878. <parameter name="sender" type="void const * const"/>
  4879. </operation>
  4880. <!--${QF::QTimeEvt::noActive}-->
  4881. <operation name="noActive" type="bool" visibility="0x00" properties="0x01">
  4882. <documentation>/*! Returns 'true' if there are no armed time events at a given tick rate.
  4883. * @static @public @memberof QTimeEvt
  4884. *
  4885. * @details
  4886. * Find out if any time events are armed at the given clock tick rate.
  4887. *
  4888. * @param[in] tickRate system clock tick rate to find out about.
  4889. *
  4890. * @returns
  4891. * 'true' if no time events are armed at the given tick rate and
  4892. * 'false' otherwise.
  4893. *
  4894. * @precondition{qf_time,800}
  4895. * - the tick rate must be in range
  4896. *
  4897. * @note
  4898. * This function should be called in critical section.
  4899. */
  4900. /*! @static @public @memberof QTimeEvt */</documentation>
  4901. <!--${QF::QTimeEvt::noActive::tickRate}-->
  4902. <parameter name="tickRate" type="uint_fast8_t const"/>
  4903. <code>Q_REQUIRE_ID(800, tickRate &lt; QF_MAX_TICK_RATE);
  4904. bool inactive;
  4905. if (QTimeEvt_timeEvtHead_[tickRate].next != (QTimeEvt *)0) {
  4906. inactive = false;
  4907. }
  4908. else if ((QTimeEvt_timeEvtHead_[tickRate].act != (void *)0)) {
  4909. inactive = false;
  4910. }
  4911. else {
  4912. inactive = true;
  4913. }
  4914. return inactive;</code>
  4915. </operation>
  4916. </class>
  4917. <!--${QF::QTicker}-->
  4918. <class name="QTicker" superclass="QF::QActive">
  4919. <documentation>/*! @brief &quot;Ticker&quot; Active Object class
  4920. * @class QTicker
  4921. * @extends QActive
  4922. *
  4923. * @details
  4924. * QTicker is an efficient active object specialized to process QF system
  4925. * clock tick at a specified tick rate [0..#QF_MAX_TICK_RATE].
  4926. * Placing system clock tick processing in an active object allows you
  4927. * to remove the non-deterministic QTIMEEVT_TICK_X() processing from the
  4928. * interrupt level and move it into the thread-level, where you can prioritize
  4929. * it as low as you wish.
  4930. *
  4931. * @usage
  4932. * The following example illustrates use of QTicker active objects:
  4933. * @include qf_ticker.c
  4934. */</documentation>
  4935. <!--${QF::QTicker::ctor}-->
  4936. <operation name="ctor" type="void" visibility="0x00" properties="0x00">
  4937. <documentation>/*! Constructor of the QTicker Active Object class
  4938. * @public @memberof QTicker
  4939. */
  4940. /*! @public @memberof QTicker */</documentation>
  4941. <!--${QF::QTicker::ctor::tickRate}-->
  4942. <parameter name="tickRate" type="uint_fast8_t const"/>
  4943. <code>static QActiveVtable const vtable = { /* QActive virtual table */
  4944. { &amp;QTicker_init_,
  4945. &amp;QTicker_dispatch_
  4946. #ifdef Q_SPY
  4947. ,&amp;QHsm_getStateHandler_
  4948. #endif
  4949. },
  4950. &amp;QActive_start_,
  4951. &amp;QTicker_post_,
  4952. &amp;QTicker_postLIFO_
  4953. };
  4954. QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(0)); /* superclass' ctor */
  4955. me-&gt;super.super.vptr = &amp;vtable.super; /* hook the vptr */
  4956. /* reuse eQueue.head for tick-rate */
  4957. me-&gt;super.eQueue.head = (QEQueueCtr)tickRate;</code>
  4958. </operation>
  4959. <!--${QF::QTicker::init_}-->
  4960. <operation name="init_" type="void" visibility="0x02" properties="0x01">
  4961. <documentation>/*! initialization (override)
  4962. * @private @memberof QTicker
  4963. */
  4964. /*! @private @memberof QTicker */</documentation>
  4965. <!--${QF::QTicker::init_::me}-->
  4966. <parameter name="me" type="QHsm * const"/>
  4967. <!--${QF::QTicker::init_::par}-->
  4968. <parameter name="par" type="void const * const"/>
  4969. <!--${QF::QTicker::init_::qs_id}-->
  4970. <parameter name="qs_id" type="uint_fast8_t const"/>
  4971. <code>Q_UNUSED_PAR(me);
  4972. Q_UNUSED_PAR(par);
  4973. Q_UNUSED_PAR(qs_id);
  4974. QTICKER_CAST_(me)-&gt;eQueue.tail = 0U;</code>
  4975. </operation>
  4976. <!--${QF::QTicker::dispatch_}-->
  4977. <operation name="dispatch_" type="void" visibility="0x02" properties="0x01">
  4978. <documentation>/*! dispatching (override)
  4979. * @private @memberof QTicker
  4980. */
  4981. /*! @private @memberof QTicker */</documentation>
  4982. <!--${QF::QTicker::dispatch_::me}-->
  4983. <parameter name="me" type="QHsm * const"/>
  4984. <!--${QF::QTicker::dispatch_::e}-->
  4985. <parameter name="e" type="QEvt const * const"/>
  4986. <!--${QF::QTicker::dispatch_::qs_id}-->
  4987. <parameter name="qs_id" type="uint_fast8_t const"/>
  4988. <code>Q_UNUSED_PAR(e);
  4989. Q_UNUSED_PAR(qs_id);
  4990. QF_CRIT_STAT_
  4991. QF_CRIT_E_();
  4992. QEQueueCtr nTicks = QTICKER_CAST_(me)-&gt;eQueue.tail; /* save # of ticks */
  4993. QTICKER_CAST_(me)-&gt;eQueue.tail = 0U; /* clear # ticks */
  4994. QF_CRIT_X_();
  4995. for (; nTicks &gt; 0U; --nTicks) {
  4996. QTimeEvt_tick_((uint_fast8_t)QTICKER_CAST_(me)-&gt;eQueue.head, me);
  4997. }</code>
  4998. </operation>
  4999. <!--${QF::QTicker::post_}-->
  5000. <operation name="post_" type="bool" visibility="0x00" properties="0x01">
  5001. <documentation>/*! post (override)
  5002. * @private @memberof QTicker
  5003. */
  5004. /*! @private @memberof QTicker */</documentation>
  5005. <!--${QF::QTicker::post_::me}-->
  5006. <parameter name="me" type="QActive * const"/>
  5007. <!--${QF::QTicker::post_::e}-->
  5008. <parameter name="e" type="QEvt const * const"/>
  5009. <!--${QF::QTicker::post_::margin}-->
  5010. <parameter name="margin" type="uint_fast16_t const"/>
  5011. <!--${QF::QTicker::post_::sender}-->
  5012. <parameter name="sender" type="void const * const"/>
  5013. <code>Q_UNUSED_PAR(e);
  5014. Q_UNUSED_PAR(margin);
  5015. #ifndef Q_SPY
  5016. Q_UNUSED_PAR(sender);
  5017. #endif
  5018. QF_CRIT_STAT_
  5019. QF_CRIT_E_();
  5020. if (me-&gt;eQueue.frontEvt == (QEvt *)0) {
  5021. static QEvt const tickEvt = { 0U, 0U, 0U };
  5022. me-&gt;eQueue.frontEvt = &amp;tickEvt; /* deliver event directly */
  5023. --me-&gt;eQueue.nFree; /* one less free event */
  5024. QACTIVE_EQUEUE_SIGNAL_(me); /* signal the event queue */
  5025. }
  5026. ++me-&gt;eQueue.tail; /* account for one more tick event */
  5027. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST, me-&gt;prio)
  5028. QS_TIME_PRE_(); /* timestamp */
  5029. QS_OBJ_PRE_(sender); /* the sender object */
  5030. QS_SIG_PRE_(0U); /* the signal of the event */
  5031. QS_OBJ_PRE_(me); /* this active object */
  5032. QS_2U8_PRE_(0U, 0U); /* pool Id &amp; refCtr of the evt */
  5033. QS_EQC_PRE_(0U); /* number of free entries */
  5034. QS_EQC_PRE_(0U); /* min number of free entries */
  5035. QS_END_NOCRIT_PRE_()
  5036. QF_CRIT_X_();
  5037. return true; /* the event is always posted correctly */</code>
  5038. </operation>
  5039. <!--${QF::QTicker::postLIFO_}-->
  5040. <operation name="postLIFO_" type="void" visibility="0x00" properties="0x01">
  5041. <documentation>/*! post-LIFO (override)
  5042. * @private @memberof QTicker
  5043. */
  5044. /*! @private @memberof QTicker */</documentation>
  5045. <!--${QF::QTicker::postLIFO_::me}-->
  5046. <parameter name="me" type="QActive * const"/>
  5047. <!--${QF::QTicker::postLIFO_::e}-->
  5048. <parameter name="e" type="QEvt const * const"/>
  5049. <code>Q_UNUSED_PAR(me);
  5050. Q_UNUSED_PAR(e);
  5051. Q_ERROR_ID(900);</code>
  5052. </operation>
  5053. </class>
  5054. <!--${QF::QEQueue}-->
  5055. <class name="QEQueue">
  5056. <documentation>/*! @brief Native QF Event Queue
  5057. * @class QEQueue
  5058. *
  5059. * @details
  5060. * This class describes the native QF event queue, which can be used as
  5061. * the event queue for active objects, or as a simple &quot;raw&quot; event queue for
  5062. * thread-safe event passing among non-framework entities, such as ISRs,
  5063. * device drivers, or other third-party components.&lt;br&gt;
  5064. *
  5065. * The native QF event queue is configured by defining the macro
  5066. * #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.&lt;br&gt;
  5067. * &lt;br&gt;
  5068. * The ::QEQueue structure contains only data members for managing an event
  5069. * queue, but does not contain the storage for the queue buffer, which must
  5070. * be provided externally during the queue initialization.&lt;br&gt;
  5071. * &lt;br&gt;
  5072. * The event queue can store only event pointers, not the whole events. The
  5073. * internal implementation uses the standard ring-buffer plus one external
  5074. * location that optimizes the queue operation for the most frequent case
  5075. * of empty queue.&lt;br&gt;
  5076. * &lt;br&gt;
  5077. * The ::QEQueue structure is used with two sets of functions. One set is for
  5078. * the active object event queue, which might need to block the active object
  5079. * task when the event queue is empty and might need to unblock it when
  5080. * events are posted to the queue. The interface for the native active object
  5081. * event queue consists of the following functions: QActive_post(),
  5082. * QActive_postLIFO(), and QActive_get_(). Additionally the function
  5083. * QEQueue_init() is used to initialize the queue.&lt;br&gt;
  5084. * &lt;br&gt;
  5085. * The other set of functions, uses ::QEQueue as a simple &quot;raw&quot; event
  5086. * queue to pass events between entities other than active objects, such as
  5087. * ISRs. The &quot;raw&quot; event queue is not capable of blocking on the get()
  5088. * operation, but is still thread-safe because it uses QF critical section
  5089. * to protect its integrity. The interface for the &quot;raw&quot; thread-safe queue
  5090. * consists of the following functions: QEQueue_post(),
  5091. * QEQueue_postLIFO(), and QEQueue_get(). Additionally the function
  5092. * QEQueue_init() is used to initialize the queue.
  5093. *
  5094. * &lt;br&gt;ote Most event queue operations (both the active object queues and
  5095. * the &quot;raw&quot; queues) internally use the QF critical section. You should be
  5096. * careful not to invoke those operations from other critical sections when
  5097. * nesting of critical sections is not supported.
  5098. *
  5099. * @sa ::QEQueue for the description of the data members
  5100. */</documentation>
  5101. <!--${QF::QEQueue::frontEvt}-->
  5102. <attribute name="frontEvt" type="QEvt const * volatile" visibility="0x02" properties="0x00">
  5103. <documentation>/*! pointer to event at the front of the queue.
  5104. * @private @memberof QEQueue
  5105. *
  5106. * @details
  5107. * All incoming and outgoing events pass through the frontEvt location.
  5108. * When the queue is empty (which is most of the time), the extra
  5109. * frontEvt location allows to bypass the ring buffer altogether,
  5110. * greatly optimizing the performance of the queue. Only bursts of events
  5111. * engage the ring buffer.
  5112. *
  5113. * &lt;br&gt;ote The additional role of this attribute is to indicate the empty
  5114. * status of the queue. The queue is empty when frontEvt is NULL.
  5115. */</documentation>
  5116. </attribute>
  5117. <!--${QF::QEQueue::ring}-->
  5118. <attribute name="ring" type="QEvt const **" visibility="0x02" properties="0x00">
  5119. <documentation>/*! pointer to the start of the ring buffer
  5120. * @private @memberof QEQueue
  5121. */</documentation>
  5122. </attribute>
  5123. <!--${QF::QEQueue::end}-->
  5124. <attribute name="end" type="QEQueueCtr" visibility="0x02" properties="0x00">
  5125. <documentation>/*! offset of the end of the ring buffer from the start of the buffer
  5126. * @private @memberof QEQueue
  5127. */</documentation>
  5128. </attribute>
  5129. <!--${QF::QEQueue::head}-->
  5130. <attribute name="head" type="QEQueueCtr volatile" visibility="0x02" properties="0x00">
  5131. <documentation>/*! offset to where next event will be inserted into the buffer
  5132. * @private @memberof QEQueue
  5133. */</documentation>
  5134. </attribute>
  5135. <!--${QF::QEQueue::tail}-->
  5136. <attribute name="tail" type="QEQueueCtr volatile" visibility="0x02" properties="0x00">
  5137. <documentation>/*! offset of where next event will be extracted from the buffer
  5138. * @private @memberof QEQueue
  5139. */</documentation>
  5140. </attribute>
  5141. <!--${QF::QEQueue::nFree}-->
  5142. <attribute name="nFree" type="QEQueueCtr volatile" visibility="0x02" properties="0x00">
  5143. <documentation>/*! number of free events in the ring buffer
  5144. * @private @memberof QEQueue
  5145. */</documentation>
  5146. </attribute>
  5147. <!--${QF::QEQueue::nMin}-->
  5148. <attribute name="nMin" type="QEQueueCtr" visibility="0x02" properties="0x00">
  5149. <documentation>/*! Minimum number of free events ever in the ring buffer.
  5150. * @private @memberof QEQueue
  5151. *
  5152. * @details
  5153. * This attribute remembers the low-watermark of the ring buffer,
  5154. * which provides a valuable information for sizing event queues.
  5155. * @sa QF_getQueueMargin().
  5156. */</documentation>
  5157. </attribute>
  5158. <!--${QF::QEQueue::init}-->
  5159. <operation name="init" type="void" visibility="0x00" properties="0x00">
  5160. <documentation>/*! Initialize the native QF event queue.
  5161. * @public @memberof QEQueue
  5162. *
  5163. * @details
  5164. * Initialize the event queue by giving it the storage for the ring buffer.
  5165. *
  5166. * @param[in,out] me current instance pointer (see @ref oop)
  5167. * @param[in] qSto an array of pointers to ::QEvt to sereve as the
  5168. * ring buffer for the event queue
  5169. * @param[in] qLen the length of the `qSto` buffer (in ::QEvt pointers)
  5170. *
  5171. * @note The actual capacity of the queue is qLen + 1, because of the extra
  5172. * location forntEvt.
  5173. *
  5174. * @note
  5175. * This function is also used to initialize the event queues of active
  5176. * objects in the built-int QV and QK kernels, as well as other
  5177. * QP ports to OSes/RTOSes that do provide a suitable message queue.
  5178. */
  5179. /*! @public @memberof QEQueue */</documentation>
  5180. <!--${QF::QEQueue::init::qSto}-->
  5181. <parameter name="qSto" type="QEvt const ** const"/>
  5182. <!--${QF::QEQueue::init::qLen}-->
  5183. <parameter name="qLen" type="uint_fast16_t const"/>
  5184. <code>me-&gt;frontEvt = (QEvt *)0; /* no events in the queue */
  5185. me-&gt;ring = qSto; /* the beginning of the ring buffer */
  5186. me-&gt;end = (QEQueueCtr)qLen;
  5187. if (qLen != 0U) {
  5188. me-&gt;head = 0U;
  5189. me-&gt;tail = 0U;
  5190. }
  5191. me-&gt;nFree = (QEQueueCtr)(qLen + 1U); /* +1 for frontEvt */
  5192. me-&gt;nMin = me-&gt;nFree;</code>
  5193. </operation>
  5194. <!--${QF::QEQueue::post}-->
  5195. <operation name="post" type="bool" visibility="0x00" properties="0x00">
  5196. <documentation>/*! Post an event to the &quot;raw&quot; thread-safe event queue (FIFO).
  5197. * @public @memberof QEQueue
  5198. *
  5199. * @details
  5200. * Post an event to the &quot;raw&quot; thread-safe event queue using the
  5201. * First-In-First-Out (FIFO) order.
  5202. *
  5203. * @param[in,out] me current instance pointer (see @ref oop)
  5204. * @param[in] e pointer to the event to be posted to the queue
  5205. * @param[in] margin number of required free slots in the queue after
  5206. * posting the event. The special value #QF_NO_MARGIN
  5207. * means that this function will assert if posting
  5208. * @returns 'true' (success) when the posting succeeded with the provided
  5209. * margin and 'false' (failure) when the posting fails.
  5210. *
  5211. * @precondition{qf_qeq,200}
  5212. * - event must be valid
  5213. *
  5214. * @note
  5215. * The #QF_NO_MARGIN value of the `margin` parameter is special and
  5216. * denotes situation when the post() operation is assumed to succeed (event
  5217. * delivery guarantee). An assertion fires, when the event cannot be
  5218. * delivered in this case.
  5219. *
  5220. * @note This function can be called from any task context or ISR context.
  5221. *
  5222. * @sa QEQueue_postLIFO(), QEQueue_get()
  5223. */
  5224. /*! @public @memberof QEQueue */</documentation>
  5225. <!--${QF::QEQueue::post::e}-->
  5226. <parameter name="e" type="QEvt const * const"/>
  5227. <!--${QF::QEQueue::post::margin}-->
  5228. <parameter name="margin" type="uint_fast16_t const"/>
  5229. <!--${QF::QEQueue::post::qs_id}-->
  5230. <parameter name="qs_id" type="uint_fast8_t const"/>
  5231. <code>#ifndef Q_SPY
  5232. Q_UNUSED_PAR(qs_id);
  5233. #endif
  5234. Q_REQUIRE_ID(200, e != (QEvt *)0);
  5235. QF_CRIT_STAT_
  5236. QF_CRIT_E_();
  5237. QEQueueCtr nFree = me-&gt;nFree; /* get volatile into temporary */
  5238. /* required margin available? */
  5239. bool status;
  5240. if (((margin == QF_NO_MARGIN) &amp;&amp; (nFree &gt; 0U))
  5241. || (nFree &gt; (QEQueueCtr)margin))
  5242. {
  5243. /* is it a dynamic event? */
  5244. if (e-&gt;poolId_ != 0U) {
  5245. QEvt_refCtr_inc_(e); /* increment the reference counter */
  5246. }
  5247. --nFree; /* one free entry just used up */
  5248. me-&gt;nFree = nFree; /* update the original */
  5249. if (me-&gt;nMin &gt; nFree) {
  5250. me-&gt;nMin = nFree; /* update minimum so far */
  5251. }
  5252. QS_BEGIN_NOCRIT_PRE_(QS_QF_EQUEUE_POST, qs_id)
  5253. QS_TIME_PRE_(); /* timestamp */
  5254. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  5255. QS_OBJ_PRE_(me); /* this queue object */
  5256. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  5257. QS_EQC_PRE_(nFree); /* number of free entries */
  5258. QS_EQC_PRE_(me-&gt;nMin); /* min number of free entries */
  5259. QS_END_NOCRIT_PRE_()
  5260. /* was the queue empty? */
  5261. if (me-&gt;frontEvt == (QEvt *)0) {
  5262. me-&gt;frontEvt = e; /* deliver event directly */
  5263. }
  5264. /* queue was not empty, insert event into the ring-buffer */
  5265. else {
  5266. /* insert event into the ring buffer (FIFO)... */
  5267. me-&gt;ring[me-&gt;head] = e; /* insert e into buffer */
  5268. /* need to wrap the head? */
  5269. if (me-&gt;head == 0U) {
  5270. me-&gt;head = me-&gt;end; /* wrap around */
  5271. }
  5272. --me-&gt;head;
  5273. }
  5274. status = true; /* event posted successfully */
  5275. }
  5276. else {
  5277. /*! @note assert if event cannot be posted and dropping events is
  5278. * not acceptable
  5279. */
  5280. Q_ASSERT_CRIT_(210, margin != QF_NO_MARGIN);
  5281. QS_BEGIN_NOCRIT_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qs_id)
  5282. QS_TIME_PRE_(); /* timestamp */
  5283. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  5284. QS_OBJ_PRE_(me); /* this queue object */
  5285. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  5286. QS_EQC_PRE_(nFree); /* number of free entries */
  5287. QS_EQC_PRE_(margin); /* margin requested */
  5288. QS_END_NOCRIT_PRE_()
  5289. status = false;
  5290. }
  5291. QF_CRIT_X_();
  5292. return status;</code>
  5293. </operation>
  5294. <!--${QF::QEQueue::postLIFO}-->
  5295. <operation name="postLIFO" type="void" visibility="0x00" properties="0x00">
  5296. <documentation>/*! Post an event to the &quot;raw&quot; thread-safe event queue (LIFO).
  5297. * @public @memberof QEQueue
  5298. *
  5299. * @details
  5300. * Post an event to the &quot;raw&quot; thread-safe event queue using the
  5301. * Last-In-First-Out (LIFO) order.
  5302. *
  5303. * @param[in,out] me current instance pointer (see @ref oop)
  5304. * @param[in] e pointer to the event to be posted to the queue
  5305. *
  5306. * @precondition{qf_qeq,300}
  5307. * - the queue must be able to accept the event (cannot overflow)
  5308. * @attention
  5309. * The LIFO policy should be used only with great __caution__, because
  5310. * it alters the order of events in the queue.
  5311. *
  5312. * @note
  5313. * This function can be called from any task context or ISR context.
  5314. *
  5315. * @note
  5316. * this function is used for the &quot;raw&quot; thread-safe queues and __not__
  5317. * for the queues of active objects.
  5318. *
  5319. * @sa
  5320. * QEQueue_post(), QEQueue_get(), QActive_defer()
  5321. */
  5322. /*! @public @memberof QEQueue */</documentation>
  5323. <!--${QF::QEQueue::postLIFO::e}-->
  5324. <parameter name="e" type="QEvt const * const"/>
  5325. <!--${QF::QEQueue::postLIFO::qs_id}-->
  5326. <parameter name="qs_id" type="uint_fast8_t const"/>
  5327. <code>#ifndef Q_SPY
  5328. Q_UNUSED_PAR(qs_id);
  5329. #endif
  5330. QF_CRIT_STAT_
  5331. QF_CRIT_E_();
  5332. QEQueueCtr nFree = me-&gt;nFree; /* get volatile into temporary */
  5333. Q_REQUIRE_CRIT_(300, nFree != 0U);
  5334. /* is it a dynamic event? */
  5335. if (e-&gt;poolId_ != 0U) {
  5336. QEvt_refCtr_inc_(e); /* increment the reference counter */
  5337. }
  5338. --nFree; /* one free entry just used up */
  5339. me-&gt;nFree = nFree; /* update the original */
  5340. if (me-&gt;nMin &gt; nFree) {
  5341. me-&gt;nMin = nFree; /* update minimum so far */
  5342. }
  5343. QS_BEGIN_NOCRIT_PRE_(QS_QF_EQUEUE_POST_LIFO, qs_id)
  5344. QS_TIME_PRE_(); /* timestamp */
  5345. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  5346. QS_OBJ_PRE_(me); /* this queue object */
  5347. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_);/* pool Id &amp; ref Count of event */
  5348. QS_EQC_PRE_(nFree); /* number of free entries */
  5349. QS_EQC_PRE_(me-&gt;nMin); /* min number of free entries */
  5350. QS_END_NOCRIT_PRE_()
  5351. QEvt const * const frontEvt = me-&gt;frontEvt; /* read into temp */
  5352. me-&gt;frontEvt = e; /* deliver event directly to the front of the queue */
  5353. /* was the queue not empty? */
  5354. if (frontEvt != (QEvt *)0) {
  5355. ++me-&gt;tail;
  5356. if (me-&gt;tail == me-&gt;end) { /* need to wrap the tail? */
  5357. me-&gt;tail = 0U; /* wrap around */
  5358. }
  5359. me-&gt;ring[me-&gt;tail] = frontEvt; /* save old front evt */
  5360. }
  5361. QF_CRIT_X_();</code>
  5362. </operation>
  5363. <!--${QF::QEQueue::get}-->
  5364. <operation name="get" type="QEvt const *" visibility="0x00" properties="0x00">
  5365. <documentation>/*! Obtain an event from the &quot;raw&quot; thread-safe queue.
  5366. * @public @memberof QEQueue
  5367. *
  5368. * @details
  5369. * Retrieves an event from the front of the &quot;raw&quot; thread-safe queue and
  5370. * returns a pointer to this event to the caller.
  5371. *
  5372. * @param[in,out] me current instance pointer (see @ref oop)
  5373. *
  5374. * @returns
  5375. * pointer to event at the front of the queue, if the queue is
  5376. * not empty and NULL if the queue is empty.
  5377. *
  5378. * @note
  5379. * this function is used for the &quot;raw&quot; thread-safe queues and __not__
  5380. * for the queues of active objects.
  5381. *
  5382. * @sa
  5383. * QEQueue_post(), QEQueue_postLIFO(), QActive_recall()
  5384. */
  5385. /*! @public @memberof QEQueue */</documentation>
  5386. <!--${QF::QEQueue::get::qs_id}-->
  5387. <parameter name="qs_id" type="uint_fast8_t const"/>
  5388. <code>#ifndef Q_SPY
  5389. Q_UNUSED_PAR(qs_id);
  5390. #endif
  5391. QF_CRIT_STAT_
  5392. QF_CRIT_E_();
  5393. QEvt const * const e = me-&gt;frontEvt; /* remove event from the front */
  5394. /* was the queue not empty? */
  5395. if (e != (QEvt *)0) {
  5396. /* use a temporary variable to increment me-&gt;nFree */
  5397. QEQueueCtr const nFree = me-&gt;nFree + 1U;
  5398. me-&gt;nFree = nFree; /* update the number of free */
  5399. /* any events in the ring buffer? */
  5400. if (nFree &lt;= me-&gt;end) {
  5401. me-&gt;frontEvt = me-&gt;ring[me-&gt;tail]; /* get from tail */
  5402. if (me-&gt;tail == 0U) { /* need to wrap the tail? */
  5403. me-&gt;tail = me-&gt;end; /* wrap around */
  5404. }
  5405. --me-&gt;tail;
  5406. QS_BEGIN_NOCRIT_PRE_(QS_QF_EQUEUE_GET, qs_id)
  5407. QS_TIME_PRE_(); /* timestamp */
  5408. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  5409. QS_OBJ_PRE_(me); /* this queue object */
  5410. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_);/* pool Id &amp; ref Count */
  5411. QS_EQC_PRE_(nFree); /* number of free entries */
  5412. QS_END_NOCRIT_PRE_()
  5413. }
  5414. else {
  5415. me-&gt;frontEvt = (QEvt *)0; /* queue becomes empty */
  5416. /* all entries in the queue must be free (+1 for fronEvt) */
  5417. Q_ASSERT_CRIT_(410, nFree == (me-&gt;end + 1U));
  5418. QS_BEGIN_NOCRIT_PRE_(QS_QF_EQUEUE_GET_LAST, qs_id)
  5419. QS_TIME_PRE_(); /* timestamp */
  5420. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  5421. QS_OBJ_PRE_(me); /* this queue object */
  5422. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  5423. QS_END_NOCRIT_PRE_()
  5424. }
  5425. }
  5426. QF_CRIT_X_();
  5427. return e;</code>
  5428. </operation>
  5429. <!--${QF::QEQueue::getNFree}-->
  5430. <operation name="getNFree" type="QEQueueCtr" visibility="0x00" properties="0x02">
  5431. <specifiers>const</specifiers>
  5432. <documentation>/*! &quot;raw&quot; thread-safe QF event queue operation for obtaining the number
  5433. * of free entries still available in the queue.
  5434. * @public @memberof QEQueue
  5435. *
  5436. * @details
  5437. * This operation needs to be used with caution because the number of free
  5438. * entries can change unexpectedly. The main intent for using this operation
  5439. * is in conjunction with event deferral. In this case the queue is accessed
  5440. * only from a single thread (by a single AO), so the number of free
  5441. * entries cannot change unexpectedly.
  5442. *
  5443. * @param[in] me current instance pointer (see @ref oop)
  5444. *
  5445. * @returns the current number of free slots in the queue.
  5446. */
  5447. /*! @public @memberof QEQueue */</documentation>
  5448. <code>return me-&gt;nFree;</code>
  5449. </operation>
  5450. <!--${QF::QEQueue::getNMin}-->
  5451. <operation name="getNMin" type="QEQueueCtr" visibility="0x00" properties="0x02">
  5452. <specifiers>const</specifiers>
  5453. <documentation>/*! &quot;raw&quot; thread-safe QF event queue operation for obtaining the minimum
  5454. * number of free entries ever in the queue (a.k.a. &quot;low-watermark&quot;).
  5455. * @public @memberof QEQueue
  5456. *
  5457. * @details
  5458. * This operation needs to be used with caution because the &quot;low-watermark&quot;
  5459. * can change unexpectedly. The main intent for using this operation is to
  5460. * get an idea of queue usage to size the queue adequately.
  5461. *
  5462. * @param[in] me current instance pointer (see @ref oop)
  5463. *
  5464. * @returns the minimum number of free entries ever in the queue since init.
  5465. */
  5466. /*! @public @memberof QEQueue */</documentation>
  5467. <code>return me-&gt;nMin;</code>
  5468. </operation>
  5469. <!--${QF::QEQueue::isEmpty}-->
  5470. <operation name="isEmpty" type="bool" visibility="0x00" properties="0x02">
  5471. <specifiers>const</specifiers>
  5472. <documentation>/*! &quot;raw&quot; thread-safe QF event queue operation to find out if the queue
  5473. * is empty.
  5474. * @public @memberof QEQueue
  5475. *
  5476. * @details
  5477. * This operation needs to be used with caution because the queue status
  5478. * can change unexpectedly. The main intent for using this operation is in
  5479. * conjunction with event deferral. In this case the queue is accessed only
  5480. * from a single thread (by a single AO), so no other entity can post
  5481. * events to the queue.
  5482. *
  5483. * @param[in] me_ current instance pointer (see @ref oop)
  5484. *
  5485. * @returns 'true' if the queue is current empty and 'false' otherwise.
  5486. */
  5487. /*! @public @memberof QEQueue */</documentation>
  5488. <code>return me-&gt;frontEvt == (QEvt *)0;</code>
  5489. </operation>
  5490. </class>
  5491. <!--${QF::QMPool}-->
  5492. <class name="QMPool">
  5493. <documentation>/*! @brief Native QF Memory Pool
  5494. * @class QMPool
  5495. *
  5496. * @details
  5497. * A fixed block-size memory pool is a very fast and efficient data
  5498. * structure for dynamic allocation of fixed block-size chunks of memory.
  5499. * A memory pool offers fast and deterministic allocation and recycling of
  5500. * memory blocks and is not subject to fragmenation.&lt;br&gt;
  5501. *
  5502. * The ::QMPool class describes the native QF memory pool, which can be used as
  5503. * the event pool for dynamic event allocation, or as a fast, deterministic
  5504. * fixed block-size heap for any other objects in your application.
  5505. *
  5506. * @note
  5507. * ::QMPool contains only data members for managing a memory pool, but
  5508. * does not contain the pool storage, which must be provided externally
  5509. * during the pool initialization.
  5510. *
  5511. * @note
  5512. * The native QF event pool is configured by defining the macro
  5513. * #QF_EPOOL_TYPE_ as ::QMPool in the specific QF port header file.
  5514. */</documentation>
  5515. <!--${QF::QMPool::start}-->
  5516. <attribute name="start" type="void *" visibility="0x02" properties="0x00">
  5517. <documentation>/*! start of the memory managed by this memory pool
  5518. * @private @memberof QMPool
  5519. */</documentation>
  5520. </attribute>
  5521. <!--${QF::QMPool::end}-->
  5522. <attribute name="end" type="void *" visibility="0x02" properties="0x00">
  5523. <documentation>/*! end of the memory managed by this memory pool
  5524. * @private @memberof QMPool
  5525. */</documentation>
  5526. </attribute>
  5527. <!--${QF::QMPool::free_head}-->
  5528. <attribute name="free_head" type="void * volatile" visibility="0x02" properties="0x00">
  5529. <documentation>/*! head of linked list of free blocks
  5530. * @private @memberof QMPool
  5531. */</documentation>
  5532. </attribute>
  5533. <!--${QF::QMPool::blockSize}-->
  5534. <attribute name="blockSize" type="QMPoolSize" visibility="0x02" properties="0x00">
  5535. <documentation>/*! maximum block size (in bytes)
  5536. * @private @memberof QMPool
  5537. */</documentation>
  5538. </attribute>
  5539. <!--${QF::QMPool::nTot}-->
  5540. <attribute name="nTot" type="QMPoolCtr" visibility="0x02" properties="0x00">
  5541. <documentation>/*! total number of blocks
  5542. * @private @memberof QMPool
  5543. */</documentation>
  5544. </attribute>
  5545. <!--${QF::QMPool::nFree}-->
  5546. <attribute name="nFree" type="QMPoolCtr volatile" visibility="0x02" properties="0x00">
  5547. <documentation>/*! number of free blocks remaining
  5548. * @private @memberof QMPool
  5549. */</documentation>
  5550. </attribute>
  5551. <!--${QF::QMPool::nMin}-->
  5552. <attribute name="nMin" type="QMPoolCtr" visibility="0x02" properties="0x00">
  5553. <documentation>/*! minimum number of free blocks ever present in this pool
  5554. * @private @memberof QMPool
  5555. *
  5556. * @details
  5557. * this attribute remembers the low watermark of the pool, which
  5558. * provides a valuable information for sizing event pools.
  5559. * @sa QF_getPoolMin().
  5560. */</documentation>
  5561. </attribute>
  5562. <!--${QF::QMPool::init}-->
  5563. <operation name="init" type="void" visibility="0x00" properties="0x00">
  5564. <documentation>/*! Initializes the native QF memory pool
  5565. * @public @memberof QMPool
  5566. *
  5567. * @details
  5568. * Initialize a fixed block-size memory pool by providing it with the pool
  5569. * memory to manage, size of this memory, and the block size.
  5570. *
  5571. * @param[in,out] me current instance pointer (see @ref oop)
  5572. * @param[in] poolSto pointer to the memory buffer for pool storage
  5573. * @param[in] poolSize size of the storage buffer in bytes
  5574. * @param[in] blockSize fixed-size of the memory blocks in bytes
  5575. *
  5576. * @precondition{qf_mem,100}
  5577. * - the memory block must be valid
  5578. * - the poolSize must fit at least one free block
  5579. * - the blockSize must not be too close to the top of the dynamic range
  5580. *
  5581. * @attention
  5582. * The caller of QMPool::init() must make sure that the `poolSto`
  5583. * pointer is properly **aligned**. In particular, it must be possible to
  5584. * efficiently store a pointer at the location pointed to by `poolSto`.
  5585. * Internally, the QMPool_init() function rounds up the block size
  5586. * `blockSize` so that it can fit an integer number of pointers.
  5587. * This is done to achieve proper alignment of the blocks within the pool.
  5588. *
  5589. * @note
  5590. * Due to the rounding of block size the actual capacity of the pool might
  5591. * be less than (`poolSize` / `blockSize`). You can check the capacity
  5592. * of the pool by calling the QF_getPoolMin() function.
  5593. *
  5594. * @note
  5595. * This function is **not** protected by a critical section, because
  5596. * it is intended to be called only during the initialization of the system,
  5597. * when interrupts are not allowed yet.
  5598. *
  5599. * @note
  5600. * Many QF ports use memory pools to implement the event pools.
  5601. *
  5602. * @usage
  5603. * The following example illustrates how to invoke QMPool_init():
  5604. * @include qmp_init.c
  5605. */
  5606. /*! @public @memberof QMPool */</documentation>
  5607. <!--${QF::QMPool::init::poolSto}-->
  5608. <parameter name="poolSto" type="void * const"/>
  5609. <!--${QF::QMPool::init::poolSize}-->
  5610. <parameter name="poolSize" type="uint_fast32_t"/>
  5611. <!--${QF::QMPool::init::blockSize}-->
  5612. <parameter name="blockSize" type="uint_fast16_t"/>
  5613. <code>Q_REQUIRE_ID(100, (poolSto != (void *)0)
  5614. &amp;&amp; (poolSize &gt;= (uint_fast32_t)sizeof(QFreeBlock))
  5615. &amp;&amp; ((uint_fast16_t)(blockSize + sizeof(QFreeBlock)) &gt; blockSize));
  5616. me-&gt;free_head = poolSto;
  5617. /* round up the blockSize to fit an integer # free blocks, no division */
  5618. me-&gt;blockSize = (QMPoolSize)sizeof(QFreeBlock); /* start with just one */
  5619. /* #free blocks that fit in one memory block */
  5620. uint_fast16_t nblocks = 1U;
  5621. while (me-&gt;blockSize &lt; (QMPoolSize)blockSize) {
  5622. me-&gt;blockSize += (QMPoolSize)sizeof(QFreeBlock);
  5623. ++nblocks;
  5624. }
  5625. blockSize = (uint_fast16_t)me-&gt;blockSize; /* round-up to nearest block */
  5626. /* the pool buffer must fit at least one rounded-up block */
  5627. Q_ASSERT_ID(110, poolSize &gt;= blockSize);
  5628. /* chain all blocks together in a free-list... */
  5629. poolSize -= (uint_fast32_t)blockSize; /* don't count the last block */
  5630. me-&gt;nTot = 1U; /* the last block already in the pool */
  5631. /* start at the head of the free list */
  5632. QFreeBlock *fb = (QFreeBlock *)me-&gt;free_head;
  5633. /* chain all blocks together in a free-list... */
  5634. while (poolSize &gt;= (uint_fast32_t)blockSize) {
  5635. fb-&gt;next = &amp;fb[nblocks]; /* point next link to next block */
  5636. fb = fb-&gt;next; /* advance to the next block */
  5637. poolSize -= (uint_fast32_t)blockSize; /* reduce available pool size */
  5638. ++me-&gt;nTot; /* increment the number of blocks so far */
  5639. }
  5640. fb-&gt;next = (QFreeBlock *)0; /* the last link points to NULL */
  5641. me-&gt;nFree = me-&gt;nTot; /* all blocks are free */
  5642. me-&gt;nMin = me-&gt;nTot; /* the minimum number of free blocks */
  5643. me-&gt;start = poolSto; /* the original start this pool buffer */
  5644. me-&gt;end = fb; /* the last block in this pool */</code>
  5645. </operation>
  5646. <!--${QF::QMPool::get}-->
  5647. <operation name="get" type="void *" visibility="0x00" properties="0x00">
  5648. <documentation>/*! Obtains a memory block from a memory pool.
  5649. * @public @memberof QMPool
  5650. *
  5651. * @details
  5652. * The function allocates a memory block from the pool and returns a pointer
  5653. * to the block back to the caller.
  5654. *
  5655. * @param[in,out] me current instance pointer (see @ref oop)
  5656. * @param[in] margin the minimum number of unused blocks still available
  5657. * in the pool after the allocation.
  5658. *
  5659. * @returns
  5660. * A pointer to a memory block or NULL if no more blocks are available in
  5661. * the memory pool.
  5662. *
  5663. * @note
  5664. * This function can be called from any task level or ISR level.
  5665. *
  5666. * @note
  5667. * The memory pool `me` must be initialized before any events can
  5668. * be requested from it. Also, the QMPool_get() function uses internally a
  5669. * QF critical section, so you should be careful not to call it from within
  5670. * a critical section when nesting of critical section is not supported.
  5671. *
  5672. * @attention
  5673. * An allocated block must be later returned back to the **same** pool
  5674. * from which it has been allocated.
  5675. *
  5676. * @sa QMPool_put()
  5677. *
  5678. * @trace
  5679. * @tr{PQP18_3}
  5680. *
  5681. * @usage
  5682. * The following example illustrates how to use QMPool_get():
  5683. * @include qmp_use.c
  5684. */
  5685. /*! @public @memberof QMPool */</documentation>
  5686. <!--${QF::QMPool::get::margin}-->
  5687. <parameter name="margin" type="uint_fast16_t const"/>
  5688. <!--${QF::QMPool::get::qs_id}-->
  5689. <parameter name="qs_id" type="uint_fast8_t const"/>
  5690. <code>#ifndef Q_SPY
  5691. Q_UNUSED_PAR(qs_id);
  5692. #endif
  5693. QF_CRIT_STAT_
  5694. QF_CRIT_E_();
  5695. /* have more free blocks than the requested margin? */
  5696. QFreeBlock *fb;
  5697. if (me-&gt;nFree &gt; (QMPoolCtr)margin) {
  5698. void *fb_next;
  5699. fb = (QFreeBlock *)me-&gt;free_head; /* get a free block */
  5700. /* the pool has some free blocks, so a free block must be available */
  5701. Q_ASSERT_CRIT_(310, fb != (QFreeBlock *)0);
  5702. fb_next = fb-&gt;next; /* put volatile into temporary */
  5703. /* is the pool becoming empty? */
  5704. --me-&gt;nFree; /* one less free block */
  5705. if (me-&gt;nFree == 0U) {
  5706. /* pool is becoming empty, so the next free block must be NULL */
  5707. Q_ASSERT_CRIT_(320, fb_next == (QFreeBlock *)0);
  5708. me-&gt;nMin = 0U; /* remember that the pool got empty */
  5709. }
  5710. else {
  5711. /*! @invariant
  5712. * The pool is not empty, so the next free-block pointer,
  5713. * so the next free block must be in range.
  5714. */
  5715. /* NOTE: The next free block pointer can fall out of range
  5716. * when the client code writes past the memory block, thus
  5717. * corrupting the next block.
  5718. */
  5719. Q_ASSERT_CRIT_(330,
  5720. (me-&gt;start &lt;= fb_next) &amp;&amp; (fb_next &lt;= me-&gt;end));
  5721. /* is the number of free blocks the new minimum so far? */
  5722. if (me-&gt;nMin &gt; me-&gt;nFree) {
  5723. me-&gt;nMin = me-&gt;nFree; /* remember the new minimum */
  5724. }
  5725. }
  5726. me-&gt;free_head = fb_next; /* set the head to the next free block */
  5727. QS_BEGIN_NOCRIT_PRE_(QS_QF_MPOOL_GET, qs_id)
  5728. QS_TIME_PRE_(); /* timestamp */
  5729. QS_OBJ_PRE_(me); /* this memory pool */
  5730. QS_MPC_PRE_(me-&gt;nFree); /* # of free blocks in the pool */
  5731. QS_MPC_PRE_(me-&gt;nMin); /* min # free blocks ever in the pool */
  5732. QS_END_NOCRIT_PRE_()
  5733. }
  5734. /* don't have enough free blocks at this point */
  5735. else {
  5736. fb = (QFreeBlock *)0;
  5737. QS_BEGIN_NOCRIT_PRE_(QS_QF_MPOOL_GET_ATTEMPT, qs_id)
  5738. QS_TIME_PRE_(); /* timestamp */
  5739. QS_OBJ_PRE_(me); /* this memory pool */
  5740. QS_MPC_PRE_(me-&gt;nFree); /* # of free blocks in the pool */
  5741. QS_MPC_PRE_(margin); /* the requested margin */
  5742. QS_END_NOCRIT_PRE_()
  5743. }
  5744. QF_CRIT_X_();
  5745. return fb; /* return the block or NULL pointer to the caller */</code>
  5746. </operation>
  5747. <!--${QF::QMPool::put}-->
  5748. <operation name="put" type="void" visibility="0x00" properties="0x00">
  5749. <documentation>/*! Recycles a memory block back to a memory pool.
  5750. * @public @memberof QMPool
  5751. *
  5752. * @details
  5753. * Recycle a memory block to the fixed block-size memory pool.
  5754. *
  5755. * @param[in,out] me current instance pointer (see @ref oop)
  5756. * @param[in] b pointer to the memory block that is being recycled
  5757. *
  5758. * @precondition{qf_mem,200}
  5759. * - the number of free blocks cannot exceed the total # blocks
  5760. * - the block pointer must be in range for this pool.
  5761. *
  5762. * @attention
  5763. * The recycled block must be allocated from the **same** memory pool
  5764. * to which it is returned.
  5765. *
  5766. * @note
  5767. * This function can be called from any task level or ISR level.
  5768. *
  5769. * @sa
  5770. * QMPool_get()
  5771. *
  5772. * @usage
  5773. * The following example illustrates how to use QMPool_put():
  5774. * @include qmp_use.c
  5775. */
  5776. /*! @public @memberof QMPool */</documentation>
  5777. <!--${QF::QMPool::put::b}-->
  5778. <parameter name="b" type="void * const"/>
  5779. <!--${QF::QMPool::put::qs_id}-->
  5780. <parameter name="qs_id" type="uint_fast8_t const"/>
  5781. <code>#ifndef Q_SPY
  5782. Q_UNUSED_PAR(qs_id);
  5783. #endif
  5784. Q_REQUIRE_ID(200, (me-&gt;nFree &lt; me-&gt;nTot)
  5785. &amp;&amp; (me-&gt;start &lt;= b) &amp;&amp; (b &lt;= me-&gt;end));
  5786. QF_CRIT_STAT_
  5787. QF_CRIT_E_();
  5788. ((QFreeBlock *)b)-&gt;next = (QFreeBlock *)me-&gt;free_head;/* link into list */
  5789. me-&gt;free_head = b; /* set as new head of the free list */
  5790. ++me-&gt;nFree; /* one more free block in this pool */
  5791. QS_BEGIN_NOCRIT_PRE_(QS_QF_MPOOL_PUT, qs_id)
  5792. QS_TIME_PRE_(); /* timestamp */
  5793. QS_OBJ_PRE_(me); /* this memory pool */
  5794. QS_MPC_PRE_(me-&gt;nFree); /* the number of free blocks in the pool */
  5795. QS_END_NOCRIT_PRE_()
  5796. QF_CRIT_X_();</code>
  5797. </operation>
  5798. </class>
  5799. <!--${QF::QF-base}-->
  5800. <package name="QF-base" stereotype="0x02" namespace="QF_">
  5801. <!--${QF::QF-base::Attr}-->
  5802. <attribute name="Attr" type="typedef struct" visibility="0x04" properties="0x00">
  5803. <documentation>/*! @brief QF active object framework
  5804. * @class QF
  5805. */</documentation>
  5806. <code>{
  5807. uint8_t dummy; /*&lt; dummy attribute */
  5808. } QF;</code>
  5809. </attribute>
  5810. <!--${QF::QF-base::intLock_}-->
  5811. <attribute name="intLock_" type="uint_fast8_t volatile" visibility="0x00" properties="0x01">
  5812. <documentation>/*! Interrupt lock up-down counter (used in some QF ports )
  5813. * @static @private @memberof QF
  5814. */</documentation>
  5815. </attribute>
  5816. <!--${QF::QF-base::intNest_}-->
  5817. <attribute name="intNest_" type="uint_fast8_t volatile" visibility="0x00" properties="0x01">
  5818. <documentation>/*! Interrupt nesting up-down counter (used in some QF ports )
  5819. * @static @private @memberof QF
  5820. */</documentation>
  5821. </attribute>
  5822. <!--${QF::QF-base::init}-->
  5823. <operation name="init" type="void" visibility="0x00" properties="0x01">
  5824. <documentation>/*! QF initialization
  5825. * @static @public @memberof QF
  5826. *
  5827. * @details
  5828. * Initializes QF and must be called exactly once before any other QF
  5829. * function. Typcially, QF_init() is called from main() even before
  5830. * initializing the Board Support Package (BSP).
  5831. *
  5832. * @note
  5833. * QF_init() clears the internal QF variables, so that the framework
  5834. * can start correctly even if the startup code fails to clear the
  5835. * uninitialized data (as is required by the C Standard).
  5836. */
  5837. /*! @static @public @memberof QF */</documentation>
  5838. </operation>
  5839. <!--${QF::QF-base::stop}-->
  5840. <operation name="stop" type="void" visibility="0x00" properties="0x01">
  5841. <documentation>/*! Function invoked by the application layer to stop the QF
  5842. * application and return control to the OS/Kernel.
  5843. * @static @public @memberof QF
  5844. *
  5845. * @details
  5846. * This function stops the QF application. After calling this function,
  5847. * QF attempts to gracefully stop the application. This graceful shutdown
  5848. * might take some time to complete. The typical use of this function is
  5849. * for terminating the QF application to return back to the operating
  5850. * system or for handling fatal errors that require shutting down
  5851. * (and possibly re-setting) the system.
  5852. *
  5853. * @attention
  5854. * After calling QF_stop() the application must terminate and cannot
  5855. * continue. In particular, QF_stop() is **not** intended to be followed
  5856. * by a call to QF_init() to &quot;resurrect&quot; the application.
  5857. *
  5858. * @sa QF_onCleanup()
  5859. */
  5860. /*! @static @public @memberof QF */</documentation>
  5861. </operation>
  5862. <!--${QF::QF-base::run}-->
  5863. <operation name="run" type="int_t" visibility="0x00" properties="0x01">
  5864. <documentation>/*! Transfers control to QF to run the application.
  5865. * @static @public @memberof QF
  5866. *
  5867. * @details
  5868. * QF_run() is typically called from your startup code after you initialize
  5869. * the QF and start at least one active object with QACTIVE_START().
  5870. *
  5871. * @returns
  5872. * In QK, the QF_run() does not return.
  5873. */
  5874. /*! @static @public @memberof QF */</documentation>
  5875. </operation>
  5876. <!--${QF::QF-base::psInit}-->
  5877. <operation name="psInit" type="void" visibility="0x00" properties="0x03">
  5878. <documentation>/*! initialization of publish-subscribe
  5879. *
  5880. * @deprecated
  5881. * @sa QActive_psInit()
  5882. */</documentation>
  5883. <!--${QF::QF-base::psInit::subscrSto}-->
  5884. <parameter name="subscrSto" type="QSubscrList * const"/>
  5885. <!--${QF::QF-base::psInit::maxSignal}-->
  5886. <parameter name="maxSignal" type="enum_t const"/>
  5887. <code>QActive_psInit(subscrSto, maxSignal);</code>
  5888. </operation>
  5889. <!--${QF::QF-base::getQueueMin}-->
  5890. <operation name="getQueueMin" type="uint_fast16_t" visibility="0x00" properties="0x01">
  5891. <documentation>/*! This function returns the minimum of free entries of
  5892. * the given event queue.
  5893. * @static @public @memberof QF
  5894. *
  5895. * @details
  5896. * Queries the minimum of free ever present in the given event queue of
  5897. * an active object with priority `prio`, since the active object
  5898. * was started.
  5899. *
  5900. * @note
  5901. * This function is available only when the native QF event queue
  5902. * implementation is used. Requesting the queue minimum of an unused
  5903. * priority level raises an assertion in the QF. (A priority level becomes
  5904. * used in QF after the call to the QActive_register_() function.)
  5905. *
  5906. * @param[in] prio Priority of the active object, whose queue is queried
  5907. *
  5908. * @returns
  5909. * the minimum of free ever present in the given event queue of an active
  5910. * object with priority `prio`, since the active object was started.
  5911. */
  5912. /*! @static @public @memberof QF */</documentation>
  5913. <!--${QF::QF-base::getQueueMin::prio}-->
  5914. <parameter name="prio" type="uint_fast8_t const"/>
  5915. <code>Q_REQUIRE_ID(400, (prio &lt;= QF_MAX_ACTIVE)
  5916. &amp;&amp; (QActive_registry_[prio] != (QActive *)0));
  5917. QF_CRIT_STAT_
  5918. QF_CRIT_E_();
  5919. uint_fast16_t const min =
  5920. (uint_fast16_t)QActive_registry_[prio]-&gt;eQueue.nMin;
  5921. QF_CRIT_X_();
  5922. return min;</code>
  5923. </operation>
  5924. <!--${QF::QF-base::onStartup}-->
  5925. <operation name="onStartup" type="void" visibility="0x00" properties="0x01">
  5926. <documentation>/*! Startup QF callback.
  5927. * @static @public @memberof QF
  5928. *
  5929. * @details
  5930. * The purpose of the QF_onStartup() callback is to configure and enable
  5931. * hardware interrupts. The callback is invoked from QF_run(), right before
  5932. * starting the underlying real-time kernel. By that time, the application
  5933. * is considered ready to receive and service interrupts.
  5934. *
  5935. * This function is application-specific and is not implemented in QF, but
  5936. * rather in the Board Support Package (BSP) for the given application.
  5937. */
  5938. /*! @static @public @memberof QF */</documentation>
  5939. </operation>
  5940. <!--${QF::QF-base::onCleanup}-->
  5941. <operation name="onCleanup" type="void" visibility="0x00" properties="0x01">
  5942. <documentation>/*! Cleanup QF callback.
  5943. * @static @public @memberof QF
  5944. *
  5945. * @details
  5946. * QF_onCleanup() is called in some QF ports before QF returns to the
  5947. * underlying real-time kernel or operating system.
  5948. *
  5949. * This function is strongly platform-specific and is not implemented in
  5950. * the QF, but either in the QF port or in the Board Support Package (BSP)
  5951. * for the given application. Some QF ports might not require implementing
  5952. * QF_onCleanup() at all, because many embedded applications don't have
  5953. * anything to exit to.
  5954. *
  5955. * @sa QF_stop()
  5956. */
  5957. /*! @static @public @memberof QF */</documentation>
  5958. </operation>
  5959. </package>
  5960. <!--${QF::QF-dyn}-->
  5961. <package name="QF-dyn" stereotype="0x02" namespace="QF_">
  5962. <!--${QF::QF-dyn::poolInit}-->
  5963. <operation name="poolInit" type="void" visibility="0x00" properties="0x01">
  5964. <documentation>/*! Event pool initialization for dynamic allocation of events.
  5965. * @static @public @memberof QF
  5966. *
  5967. * @details
  5968. * This function initializes one event pool at a time and must be called
  5969. * exactly once for each event pool before the pool can be used.
  5970. *
  5971. * @param[in] poolSto pointer to the storage for the event pool
  5972. * @param[in] poolSize size of the storage for the pool in bytes
  5973. * @param[in] evtSize the block-size of the pool in bytes, which determines
  5974. * the maximum size of events that can be allocated from the pool.
  5975. *
  5976. * @attention
  5977. * You might initialize many event pools by making many consecutive calls
  5978. * to the QF_poolInit() function. However, for the simplicity of the internal
  5979. * implementation, you must initialize event pools in the **ascending order**
  5980. * of the event size.
  5981. *
  5982. * Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that can
  5983. * be adapted for QF event pools. In case such support is missing, QF provides
  5984. * a native QF event pool implementation. The macro #QF_EPOOL_TYPE_ determines
  5985. * the type of event pool used by a particular QF port. See structure ::QMPool
  5986. * for more information.
  5987. *
  5988. * @note The actual number of events available in the pool might be actually
  5989. * less than (`poolSize` / `evtSize`) due to the internal alignment
  5990. * of the blocks that the pool might perform. You can always check the
  5991. * capacity of the pool by calling QF_getPoolMin().
  5992. *
  5993. * @note The dynamic allocation of events is optional, meaning that you
  5994. * might choose not to use dynamic events. In that case calling QF_poolInit()
  5995. * and using up memory for the memory blocks is unnecessary.
  5996. *
  5997. * @sa QF initialization example for QF_init()
  5998. */
  5999. /*! @static @public @memberof QF */</documentation>
  6000. <!--${QF::QF-dyn::poolInit::poolSto}-->
  6001. <parameter name="poolSto" type="void * const"/>
  6002. <!--${QF::QF-dyn::poolInit::poolSize}-->
  6003. <parameter name="poolSize" type="uint_fast32_t const"/>
  6004. <!--${QF::QF-dyn::poolInit::evtSize}-->
  6005. <parameter name="evtSize" type="uint_fast16_t const"/>
  6006. <code>/*! @pre cannot exceed the number of available memory pools */
  6007. Q_REQUIRE_ID(200, QF_maxPool_ &lt; QF_MAX_EPOOL);
  6008. /*! @pre please initialize event pools in ascending order of evtSize: */
  6009. Q_REQUIRE_ID(201, (QF_maxPool_ == 0U)
  6010. || (QF_EPOOL_EVENT_SIZE_(QF_ePool_[QF_maxPool_ - 1U])
  6011. &lt; evtSize));
  6012. /* perform the platform-dependent initialization of the pool */
  6013. QF_EPOOL_INIT_(QF_ePool_[QF_maxPool_], poolSto, poolSize, evtSize);
  6014. ++QF_maxPool_; /* one more pool */
  6015. #ifdef Q_SPY
  6016. /* generate the object-dictionary entry for the initialized pool */
  6017. {
  6018. uint8_t obj_name[9] = &quot;EvtPool?&quot;;
  6019. obj_name[7] = (uint8_t)(((uint8_t)'0' + QF_maxPool_) &amp; 0x7FU);
  6020. QS_obj_dict_pre_(&amp;QF_ePool_[QF_maxPool_ - 1U], (char const *)obj_name);
  6021. }
  6022. #endif /* Q_SPY*/</code>
  6023. </operation>
  6024. <!--${QF::QF-dyn::poolGetMaxBlockSize}-->
  6025. <operation name="poolGetMaxBlockSize" type="uint_fast16_t" visibility="0x00" properties="0x01">
  6026. <documentation>/*! Obtain the block size of any registered event pools.
  6027. * @static @public @memberof QF
  6028. *
  6029. * @details
  6030. * Obtain the block size of any registered event pools
  6031. */
  6032. /*! @static @public @memberof QF */</documentation>
  6033. <code>return QF_EPOOL_EVENT_SIZE_(QF_ePool_[QF_maxPool_ - 1U]);</code>
  6034. </operation>
  6035. <!--${QF::QF-dyn::getPoolMin}-->
  6036. <operation name="getPoolMin" type="uint_fast16_t" visibility="0x00" properties="0x01">
  6037. <documentation>/*! Obtain the minimum of free entries of the given event pool.
  6038. * @static @public @memberof QF
  6039. *
  6040. * @details
  6041. * This function obtains the minimum number of free blocks in the given
  6042. * event pool since this pool has been initialized by a call to QF_poolInit().
  6043. *
  6044. * @param[in] poolId event pool ID in the range 1..QF_maxPool_, where
  6045. * QF_maxPool_ is the number of event pools initialized
  6046. * with the function QF_poolInit().
  6047. *
  6048. * @returns
  6049. * the minimum number of unused blocks in the given event pool.
  6050. */
  6051. /*! @static @public @memberof QF */</documentation>
  6052. <!--${QF::QF-dyn::getPoolMin::poolId}-->
  6053. <parameter name="poolId" type="uint_fast8_t const"/>
  6054. <code>/*! @pre the poolId must be in range */
  6055. Q_REQUIRE_ID(400, (poolId &lt;= QF_MAX_EPOOL)
  6056. &amp;&amp; (0U &lt; poolId) &amp;&amp; (poolId &lt;= QF_maxPool_));
  6057. QF_CRIT_STAT_
  6058. QF_CRIT_E_();
  6059. uint_fast16_t const min = (uint_fast16_t)QF_ePool_[poolId - 1U].nMin;
  6060. QF_CRIT_X_();
  6061. return min;</code>
  6062. </operation>
  6063. <!--${QF::QF-dyn::newX_}-->
  6064. <operation name="newX_" type="QEvt *" visibility="0x00" properties="0x01">
  6065. <documentation>/*! Internal QF implementation of creating new dynamic event.
  6066. * @static @private @memberof QF
  6067. *
  6068. * @details
  6069. * Allocates an event dynamically from one of the QF event pools.
  6070. *
  6071. * @param[in] evtSize the size (in bytes) of the event to allocate
  6072. * @param[in] margin the number of un-allocated events still available
  6073. * in a given event pool after the allocation completes.
  6074. * The special value ::QF_NO_MARGIN means that this function
  6075. * will assert if allocation fails.
  6076. * @param[in] sig the signal to be assigned to the allocated event
  6077. *
  6078. * @returns
  6079. * pointer to the newly allocated event. This pointer can be NULL only if
  6080. * margin != #QF_NO_MARGIN and the event cannot be allocated with the
  6081. * specified margin still available in the given pool.
  6082. *
  6083. * @note
  6084. * The internal QF function QF_newX_() raises an assertion when the
  6085. * `margin` parameter is #QF_NO_MARGIN and allocation of the event turns
  6086. * out to be impossible due to event pool depletion, or incorrect (too big)
  6087. * size of the requested event.
  6088. *
  6089. * @note
  6090. * The application code should not call this function directly.
  6091. * The only allowed use is thorough the macros Q_NEW() or Q_NEW_X().
  6092. */
  6093. /*! @static @private @memberof QF */</documentation>
  6094. <!--${QF::QF-dyn::newX_::evtSize}-->
  6095. <parameter name="evtSize" type="uint_fast16_t const"/>
  6096. <!--${QF::QF-dyn::newX_::margin}-->
  6097. <parameter name="margin" type="uint_fast16_t const"/>
  6098. <!--${QF::QF-dyn::newX_::sig}-->
  6099. <parameter name="sig" type="enum_t const"/>
  6100. <code>uint_fast8_t idx;
  6101. /* find the pool index that fits the requested event size ... */
  6102. for (idx = 0U; idx &lt; QF_maxPool_; ++idx) {
  6103. if (evtSize &lt;= QF_EPOOL_EVENT_SIZE_(QF_ePool_[idx])) {
  6104. break;
  6105. }
  6106. }
  6107. /* cannot run out of registered pools */
  6108. Q_ASSERT_ID(310, idx &lt; QF_maxPool_);
  6109. /* get e -- platform-dependent */
  6110. QEvt *e;
  6111. #ifdef Q_SPY
  6112. QF_EPOOL_GET_(QF_ePool_[idx], e,
  6113. ((margin != QF_NO_MARGIN) ? margin : 0U),
  6114. (uint_fast8_t)QS_EP_ID + idx + 1U);
  6115. #else
  6116. QF_EPOOL_GET_(QF_ePool_[idx], e,
  6117. ((margin != QF_NO_MARGIN) ? margin : 0U), 0U);
  6118. #endif
  6119. /* was e allocated correctly? */
  6120. QS_CRIT_STAT_
  6121. if (e != (QEvt *)0) {
  6122. e-&gt;sig = (QSignal)sig; /* set signal for this event */
  6123. e-&gt;poolId_ = (uint8_t)(idx + 1U); /* store the pool ID */
  6124. e-&gt;refCtr_ = 0U; /* set the reference counter to 0 */
  6125. QS_BEGIN_PRE_(QS_QF_NEW, (uint_fast8_t)QS_EP_ID + e-&gt;poolId_)
  6126. QS_TIME_PRE_(); /* timestamp */
  6127. QS_EVS_PRE_(evtSize); /* the size of the event */
  6128. QS_SIG_PRE_(sig); /* the signal of the event */
  6129. QS_END_PRE_()
  6130. }
  6131. /* event cannot be allocated */
  6132. else {
  6133. /* This assertion means that the event allocation failed,
  6134. * and this failure cannot be tolerated. The most frequent
  6135. * reason is an event leak in the application.
  6136. */
  6137. Q_ASSERT_ID(320, margin != QF_NO_MARGIN);
  6138. QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, (uint_fast8_t)QS_EP_ID + idx + 1U)
  6139. QS_TIME_PRE_(); /* timestamp */
  6140. QS_EVS_PRE_(evtSize); /* the size of the event */
  6141. QS_SIG_PRE_(sig); /* the signal of the event */
  6142. QS_END_PRE_()
  6143. }
  6144. return e; /* can't be NULL if we can't tolerate failed allocation */</code>
  6145. </operation>
  6146. <!--${QF::QF-dyn::gc}-->
  6147. <operation name="gc" type="void" visibility="0x00" properties="0x01">
  6148. <documentation>/*! Recycle a dynamic event
  6149. * @static @public @memberof QF
  6150. *
  6151. * @details
  6152. * This function implements a simple garbage collector for the dynamic events.
  6153. * Only dynamic events are candidates for recycling. (A dynamic event is one
  6154. * that is allocated from an event pool, which is determined as non-zero
  6155. * e-&gt;poolId_ attribute.) Next, the function decrements the reference counter
  6156. * of the event (e-&gt;refCtr_), and recycles the event only if the counter drops
  6157. * to zero (meaning that no more references are outstanding for this event).
  6158. * The dynamic event is recycled by returning it to the pool from which
  6159. * it was originally allocated.
  6160. *
  6161. * @param[in] e pointer to the event to recycle
  6162. *
  6163. * @note
  6164. * QF invokes the garbage collector at all appropriate contexts, when
  6165. * an event can become garbage (automatic garbage collection), so the
  6166. * application code should have no need to call QF_gc() directly. The QF_gc()
  6167. * function is exposed only for special cases when your application sends
  6168. * dynamic events to the &quot;raw&quot; thread-safe queues (see ::QEQueue). Such
  6169. * queues are processed outside of QF and the automatic garbage collection
  6170. * is **NOT** performed for these events. In this case you need to call
  6171. * QF_gc() explicitly.
  6172. */
  6173. /*! @static @public @memberof QF */</documentation>
  6174. <!--${QF::QF-dyn::gc::e}-->
  6175. <parameter name="e" type="QEvt const * const"/>
  6176. <code>/* is it a dynamic event? */
  6177. if (e-&gt;poolId_ != 0U) {
  6178. QF_CRIT_STAT_
  6179. QF_CRIT_E_();
  6180. /* isn't this the last reference? */
  6181. if (e-&gt;refCtr_ &gt; 1U) {
  6182. QS_BEGIN_NOCRIT_PRE_(QS_QF_GC_ATTEMPT,
  6183. (uint_fast8_t)QS_EP_ID + e-&gt;poolId_)
  6184. QS_TIME_PRE_(); /* timestamp */
  6185. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  6186. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  6187. QS_END_NOCRIT_PRE_()
  6188. QEvt_refCtr_dec_(e); /* decrement the ref counter */
  6189. QF_CRIT_X_();
  6190. }
  6191. /* this is the last reference to this event, recycle it */
  6192. else {
  6193. uint_fast8_t const idx = (uint_fast8_t)e-&gt;poolId_ - 1U;
  6194. QS_BEGIN_NOCRIT_PRE_(QS_QF_GC,
  6195. (uint_fast8_t)QS_EP_ID + e-&gt;poolId_)
  6196. QS_TIME_PRE_(); /* timestamp */
  6197. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  6198. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  6199. QS_END_NOCRIT_PRE_()
  6200. QF_CRIT_X_();
  6201. /* pool ID must be in range */
  6202. Q_ASSERT_ID(410, idx &lt; QF_maxPool_);
  6203. /* cast 'const' away, which is OK, because it's a pool event */
  6204. #ifdef Q_SPY
  6205. QF_EPOOL_PUT_(QF_ePool_[idx], (QEvt *)e,
  6206. (uint_fast8_t)QS_EP_ID + e-&gt;poolId_);
  6207. #else
  6208. QF_EPOOL_PUT_(QF_ePool_[idx], (QEvt *)e, 0U);
  6209. #endif
  6210. }
  6211. }</code>
  6212. </operation>
  6213. <!--${QF::QF-dyn::newRef_}-->
  6214. <operation name="newRef_" type="QEvt const *" visibility="0x00" properties="0x01">
  6215. <documentation>/*! Internal QF implementation of creating new event reference.
  6216. * @static @private @memberof QF
  6217. *
  6218. * @details
  6219. * Creates and returns a new reference to the current event e
  6220. *
  6221. * @param[in] e pointer to the current event
  6222. * @param[in] evtRef the event reference
  6223. *
  6224. * @returns
  6225. * the newly created reference to the event `e`
  6226. *
  6227. * @note
  6228. * The application code should not call this function directly.
  6229. * The only allowed use is thorough the macro Q_NEW_REF().
  6230. */
  6231. /*! @static @private @memberof QF */</documentation>
  6232. <!--${QF::QF-dyn::newRef_::e}-->
  6233. <parameter name="e" type="QEvt const * const"/>
  6234. <!--${QF::QF-dyn::newRef_::evtRef}-->
  6235. <parameter name="evtRef" type="void const * const"/>
  6236. <code>#ifdef Q_NASSERT
  6237. Q_UNUSED_PAR(evtRef);
  6238. #endif
  6239. /*! @pre the event must be dynamic and the provided event reference
  6240. * must not be already in use */
  6241. Q_REQUIRE_ID(500,
  6242. (e-&gt;poolId_ != 0U)
  6243. &amp;&amp; (evtRef == (void *)0));
  6244. QF_CRIT_STAT_
  6245. QF_CRIT_E_();
  6246. QEvt_refCtr_inc_(e); /* increments the ref counter */
  6247. QS_BEGIN_NOCRIT_PRE_(QS_QF_NEW_REF,
  6248. (uint_fast8_t)QS_EP_ID + e-&gt;poolId_)
  6249. QS_TIME_PRE_(); /* timestamp */
  6250. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  6251. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  6252. QS_END_NOCRIT_PRE_()
  6253. QF_CRIT_X_();
  6254. return e;</code>
  6255. </operation>
  6256. <!--${QF::QF-dyn::deleteRef_}-->
  6257. <operation name="deleteRef_" type="void" visibility="0x00" properties="0x01">
  6258. <documentation>/*! Internal QF implementation of deleting event reference.
  6259. * @static @private @memberof QF
  6260. *
  6261. * @details
  6262. * Deletes an existing reference to the event e
  6263. *
  6264. * @param[in] evtRef the event reference
  6265. *
  6266. * @note
  6267. * The application code should not call this function directly.
  6268. * The only allowed use is thorough the macro Q_DELETE_REF().
  6269. */
  6270. /*! @static @private @memberof QF */</documentation>
  6271. <!--${QF::QF-dyn::deleteRef_::evtRef}-->
  6272. <parameter name="evtRef" type="void const * const"/>
  6273. <code>QS_CRIT_STAT_
  6274. QEvt const * const e = (QEvt const *)evtRef;
  6275. QS_BEGIN_PRE_(QS_QF_DELETE_REF,
  6276. (uint_fast8_t)QS_EP_ID + e-&gt;poolId_)
  6277. QS_TIME_PRE_(); /* timestamp */
  6278. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  6279. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  6280. QS_END_PRE_()
  6281. #if (QF_MAX_EPOOL &gt; 0U)
  6282. QF_gc(e);
  6283. #endif</code>
  6284. </operation>
  6285. </package>
  6286. <!--${QF::QF-pkg}-->
  6287. <package name="QF-pkg" stereotype="0x02" namespace="QF_">
  6288. <!--${QF::QF-pkg::ePool_[QF_MAX_EPOOL]}-->
  6289. <attribute name="ePool_[QF_MAX_EPOOL]? (QF_MAX_EPOOL &gt; 0U)" type="QF_EPOOL_TYPE_" visibility="0x00" properties="0x00">
  6290. <documentation>/*! array of event pools managed by QF */</documentation>
  6291. </attribute>
  6292. <!--${QF::QF-pkg::maxPool_}-->
  6293. <attribute name="maxPool_" type="uint_fast8_t" visibility="0x00" properties="0x00">
  6294. <documentation>/*! number of initialized event pools */</documentation>
  6295. </attribute>
  6296. <!--${QF::QF-pkg::readySet_}-->
  6297. <attribute name="readySet_" type="QPSet" visibility="0x00" properties="0x01">
  6298. <documentation>/*! &quot;Ready-set&quot; of all threads used in the built-in kernels
  6299. * @static @private @memberof QF
  6300. */</documentation>
  6301. </attribute>
  6302. <!--${QF::QF-pkg::bzero}-->
  6303. <operation name="bzero" type="void" visibility="0x00" properties="0x01">
  6304. <documentation>/*! Clear a specified region of memory to zero.
  6305. * @static @public @memberof QF
  6306. *
  6307. * @details
  6308. * Clears a memory buffer by writing zeros byte-by-byte.
  6309. *
  6310. * @param[in] start pointer to the beginning of a memory buffer.
  6311. * @param[in] len length of the memory buffer to clear (in bytes)
  6312. *
  6313. * @note The main application of this function is clearing the internal QF
  6314. * variables upon startup. This is done to avoid problems with non-standard
  6315. * startup code provided with some compilers and toolsets (e.g., TI DSPs or
  6316. * Microchip MPLAB), which does not zero the uninitialized variables, as
  6317. * required by the ANSI C standard.
  6318. */
  6319. /*! @static @public @memberof QF */</documentation>
  6320. <!--${QF::QF-pkg::bzero::start}-->
  6321. <parameter name="start" type="void * const"/>
  6322. <!--${QF::QF-pkg::bzero::len}-->
  6323. <parameter name="len" type="uint_fast16_t const"/>
  6324. <code>uint8_t *ptr = (uint8_t *)start;
  6325. for (uint_fast16_t n = len; n &gt; 0U; --n) {
  6326. *ptr = 0U;
  6327. ++ptr;
  6328. }</code>
  6329. </operation>
  6330. </package>
  6331. <!--${QF::QF-extern-C}-->
  6332. <package name="QF-extern-C" stereotype="0x02" namespace="QF_">
  6333. <!--${QF::QF-extern-C::onContextSw}-->
  6334. <operation name="onContextSw?def QF_ON_CONTEXT_SW" type="void" visibility="0x00" properties="0x00">
  6335. <documentation>/*! QF context switch callback used in built-in kernels (QV, QK, QXK)
  6336. * @static @public @memberof QF
  6337. *
  6338. * @details
  6339. * This callback function provides a mechanism to perform additional
  6340. * custom operations when one of the built-in kernels switches context
  6341. * from one thread to another.
  6342. *
  6343. * @param[in] prev pointer to the previous thread (active object)
  6344. * (prev==0 means that `prev` was the idle loop)
  6345. * @param[in] next pointer to the next thread (active object)
  6346. * (next==0) means that `next` is the idle loop)
  6347. * @attention
  6348. * QF_onContextSw() is invoked with interrupts **disabled** and must also
  6349. * return with interrupts **disabled**.
  6350. *
  6351. * @note
  6352. * This callback is enabled by defining the macro #QF_ON_CONTEXT_SW.
  6353. *
  6354. * @include qf_oncontextsw.c
  6355. */
  6356. /*! @static @public @memberof QF */</documentation>
  6357. <!--${QF::QF-extern-C::onContextSw::prev}-->
  6358. <parameter name="prev" type="QActive *"/>
  6359. <!--${QF::QF-extern-C::onContextSw::next}-->
  6360. <parameter name="next" type="QActive *"/>
  6361. </operation>
  6362. </package>
  6363. </package>
  6364. <!--${QF-QMPool-impl}-->
  6365. <package name="QF-QMPool-impl" stereotype="0x02">
  6366. <!--${QF-QMPool-impl::QF_EPOOL_TYPE_}-->
  6367. <attribute name="QF_EPOOL_TYPE_" type="" visibility="0x03" properties="0x00">
  6368. <documentation>Native QF event pool</documentation>
  6369. <code>QMPool</code>
  6370. </attribute>
  6371. <!--${QF-QMPool-impl::QF_EPOOL_INIT_}-->
  6372. <operation name="QF_EPOOL_INIT_" type="" visibility="0x03" properties="0x00">
  6373. <documentation>Native QF event pool initialization</documentation>
  6374. <!--${QF-QMPool-impl::QF_EPOOL_INIT_::p_}-->
  6375. <parameter name="p_" type="QMPool *"/>
  6376. <!--${QF-QMPool-impl::QF_EPOOL_INIT_::poolSto_}-->
  6377. <parameter name="poolSto_" type="void *"/>
  6378. <!--${QF-QMPool-impl::QF_EPOOL_INIT_::poolSize_}-->
  6379. <parameter name="poolSize_" type="uint_fast32_t"/>
  6380. <!--${QF-QMPool-impl::QF_EPOOL_INIT_::evtSize_}-->
  6381. <parameter name="evtSize_" type="uint_fast16_t"/>
  6382. <code>\
  6383. (QMPool_init(&amp;(p_), (poolSto_), (poolSize_), (evtSize_)))</code>
  6384. </operation>
  6385. <!--${QF-QMPool-impl::QF_EPOOL_EVENT_SIZE_}-->
  6386. <operation name="QF_EPOOL_EVENT_SIZE_" type="" visibility="0x03" properties="0x00">
  6387. <documentation>Native QF event pool event-size getter</documentation>
  6388. <!--${QF-QMPool-impl::QF_EPOOL_EVENT_S~::p_}-->
  6389. <parameter name="p_" type="QMPool const *"/>
  6390. <code>((uint_fast16_t)(p_).blockSize)</code>
  6391. </operation>
  6392. <!--${QF-QMPool-impl::QF_EPOOL_GET_}-->
  6393. <operation name="QF_EPOOL_GET_" type="" visibility="0x03" properties="0x00">
  6394. <documentation>Native QF event pool get-event</documentation>
  6395. <!--${QF-QMPool-impl::QF_EPOOL_GET_::p_}-->
  6396. <parameter name="p_" type="QMPool *"/>
  6397. <!--${QF-QMPool-impl::QF_EPOOL_GET_::e_}-->
  6398. <parameter name="e_" type="QEvt *"/>
  6399. <!--${QF-QMPool-impl::QF_EPOOL_GET_::m_}-->
  6400. <parameter name="m_" type="uint_fast16_t"/>
  6401. <!--${QF-QMPool-impl::QF_EPOOL_GET_::qs_id_}-->
  6402. <parameter name="qs_id_" type="uint8_t"/>
  6403. <code>\
  6404. ((e_) = (QEvt *)QMPool_get(&amp;(p_), (m_), (qs_id_)))</code>
  6405. </operation>
  6406. <!--${QF-QMPool-impl::QF_EPOOL_PUT_}-->
  6407. <operation name="QF_EPOOL_PUT_" type="" visibility="0x03" properties="0x00">
  6408. <documentation>Native QF event pool put-event</documentation>
  6409. <!--${QF-QMPool-impl::QF_EPOOL_PUT_::p_}-->
  6410. <parameter name="p_" type="QMPool *"/>
  6411. <!--${QF-QMPool-impl::QF_EPOOL_PUT_::e_}-->
  6412. <parameter name="e_" type="QEvt *"/>
  6413. <!--${QF-QMPool-impl::QF_EPOOL_PUT_::qs_id_}-->
  6414. <parameter name="qs_id_" type="uint8_t"/>
  6415. <code>\
  6416. (QMPool_put(&amp;(p_), (e_), (qs_id_)))</code>
  6417. </operation>
  6418. </package>
  6419. <!--${QV}-->
  6420. <package name="QV" stereotype="0x05">
  6421. <!--${QV::QV-base}-->
  6422. <package name="QV-base" stereotype="0x02" namespace="QV_">
  6423. <!--${QV::QV-base::Attr}-->
  6424. <attribute name="Attr" type="typedef struct" visibility="0x04" properties="0x00">
  6425. <documentation>/*! @brief QV cooperative kernel
  6426. * @class QV
  6427. */</documentation>
  6428. <code>{
  6429. uint8_t dummy; /*&lt; dummy attribute */
  6430. } QV;</code>
  6431. </attribute>
  6432. <!--${QV::QV-base::onIdle}-->
  6433. <operation name="onIdle" type="void" visibility="0x00" properties="0x01">
  6434. <documentation>/*! QV idle callback (customized in BSPs)
  6435. * @static @public @memberof QV
  6436. *
  6437. * @details
  6438. * QV_onIdle() is called by the cooperative QV kernel (from QF_run()) when
  6439. * the scheduler detects that no events are available for active objects
  6440. * (the idle condition). This callback gives the application an opportunity
  6441. * to enter a power-saving CPU mode, or perform some other idle processing
  6442. * (such as QS software tracing output).
  6443. *
  6444. * @attention
  6445. * QV_onIdle() is invoked with interrupts **DISABLED** because the idle
  6446. * condition can be asynchronously changed at any time by an interrupt.
  6447. * QV_onIdle() MUST enable the interrupts internally, but not before
  6448. * putting the CPU into the low-power mode. (Ideally, enabling interrupts and
  6449. * low-power mode should happen atomically). At the very least, the function
  6450. * MUST enable interrupts, otherwise interrupts will remain disabled
  6451. * permanently.
  6452. */
  6453. /*! @static @public @memberof QV */</documentation>
  6454. </operation>
  6455. </package>
  6456. <!--${QV::QF-cust}-->
  6457. <package name="QF-cust" stereotype="0x02" namespace="QF_">
  6458. <!--${QV::QF-cust::init}-->
  6459. <operation name="init" type="void" visibility="0x00" properties="0x01">
  6460. <documentation>/*! QF initialization for QV
  6461. * @static @public @memberof QF
  6462. */
  6463. /*! @static @public @memberof QF */</documentation>
  6464. <code>#if (QF_MAX_EPOOL &gt; 0U)
  6465. QF_maxPool_ = 0U;
  6466. #endif
  6467. QF_bzero(&amp;QTimeEvt_timeEvtHead_[0], sizeof(QTimeEvt_timeEvtHead_));
  6468. QF_bzero(&amp;QActive_registry_[0], sizeof(QActive_registry_));
  6469. QF_bzero(&amp;QF_readySet_, sizeof(QF_readySet_));
  6470. #ifdef QV_INIT
  6471. QV_INIT(); /* port-specific initialization of the QV kernel */
  6472. #endif</code>
  6473. </operation>
  6474. <!--${QV::QF-cust::stop}-->
  6475. <operation name="stop" type="void" visibility="0x00" properties="0x01">
  6476. <documentation>/*! Stop the QF customization for QV
  6477. * @static @public @memberof QF
  6478. */
  6479. /*! @static @public @memberof QF */</documentation>
  6480. <code>QF_onCleanup(); /* application-specific cleanup callback */
  6481. /* nothing else to do for the cooperative QV kernel */</code>
  6482. </operation>
  6483. <!--${QV::QF-cust::run}-->
  6484. <operation name="run" type="int_t" visibility="0x00" properties="0x01">
  6485. <documentation>/*! QF_run() customization for QV kernel
  6486. * @static @public @memberof QF
  6487. */
  6488. /*! @static @public @memberof QF */</documentation>
  6489. <code>#ifdef Q_SPY
  6490. /* produce the QS_QF_RUN trace record */
  6491. QF_INT_DISABLE();
  6492. QS_beginRec_((uint_fast8_t)QS_QF_RUN);
  6493. QS_endRec_();
  6494. QF_INT_ENABLE();
  6495. #endif /* Q_SPY */
  6496. QF_onStartup(); /* application-specific startup callback */
  6497. QF_INT_DISABLE();
  6498. #ifdef QV_START
  6499. QV_START(); /* port-specific startup of the QV kernel */
  6500. #endif
  6501. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  6502. uint8_t pprev = 0U; /* previously used priority */
  6503. #endif /* (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) */
  6504. for (;;) { /* QV event loop... */
  6505. /* find the maximum priority AO ready to run */
  6506. if (QPSet_notEmpty(&amp;QF_readySet_)) {
  6507. uint8_t const p = (uint8_t)QPSet_findMax(&amp;QF_readySet_);
  6508. QActive * const a = QActive_registry_[p];
  6509. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  6510. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_NEXT, p)
  6511. QS_TIME_PRE_(); /* timestamp */
  6512. QS_2U8_PRE_(p, /* priority of the scheduled AO */
  6513. pprev); /* previous priority */
  6514. QS_END_NOCRIT_PRE_()
  6515. #ifdef QF_ON_CONTEXT_SW
  6516. QF_onContextSw(((pprev != 0U)
  6517. ? QActive_registry_[pprev]
  6518. : (QActive *)0), a);
  6519. #endif /* QF_ON_CONTEXT_SW */
  6520. pprev = p; /* update previous priority */
  6521. #endif /* (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) */
  6522. QF_INT_ENABLE();
  6523. /* perform the run-to-completion (RTC) step...
  6524. * 1. retrieve the event from the AO's event queue, which
  6525. * by this time must be non-empty (and QV asserts it).
  6526. * 2. dispatch the event to the AO's state machine.
  6527. * 3. determine if event is garbage and collect it if so
  6528. */
  6529. QEvt const * const e = QActive_get_(a);
  6530. QHSM_DISPATCH(&amp;a-&gt;super, e, a-&gt;prio);
  6531. #if (QF_MAX_EPOOL &gt; 0U)
  6532. QF_gc(e);
  6533. #endif
  6534. QF_INT_DISABLE();
  6535. if (a-&gt;eQueue.frontEvt == (QEvt *)0) { /* empty queue? */
  6536. QPSet_remove(&amp;QF_readySet_, p);
  6537. }
  6538. }
  6539. else { /* no AO ready to run --&gt; idle */
  6540. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  6541. if (pprev != 0U) {
  6542. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_IDLE, pprev)
  6543. QS_TIME_PRE_(); /* timestamp */
  6544. QS_U8_PRE_(pprev); /* previous priority */
  6545. QS_END_NOCRIT_PRE_()
  6546. #ifdef QF_ON_CONTEXT_SW
  6547. QF_onContextSw(QActive_registry_[pprev], (QActive *)0);
  6548. #endif /* QF_ON_CONTEXT_SW */
  6549. pprev = 0U; /* update previous priority */
  6550. }
  6551. #endif /* (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) */
  6552. /* QV_onIdle() must be called with interrupts DISABLED
  6553. * because the determination of the idle condition (all event
  6554. * queues empty) can change at any time by an interrupt posting
  6555. * events to a queue.
  6556. *
  6557. * NOTE: QV_onIdle() MUST enable interrupts internally,
  6558. * ideally at the same time as putting the CPU into a power-
  6559. * saving mode.
  6560. */
  6561. QV_onIdle();
  6562. QF_INT_DISABLE(); /* disable interrupts before looping back */
  6563. }
  6564. }
  6565. #ifdef __GNUC__ /* GNU compiler? */
  6566. return 0;
  6567. #endif</code>
  6568. </operation>
  6569. </package>
  6570. <!--${QV::QActive}-->
  6571. <class name="QActive">
  6572. <documentation>/*! QActive active object class customization for QV */</documentation>
  6573. <!--${QV::QActive::start_}-->
  6574. <operation name="start_" type="void" visibility="0x00" properties="0x04">
  6575. <documentation>/*! Starts execution of an active object and registers the object
  6576. * with the framework customized for the QV kernel
  6577. * @public @memberof QActive
  6578. *
  6579. * @precondition{qv,300}
  6580. * - stack storage must not be provided because the QV kernel
  6581. * does not need per-AO stacks.
  6582. */
  6583. /*! @public @memberof QActive */</documentation>
  6584. <!--${QV::QActive::start_::prioSpec}-->
  6585. <parameter name="prioSpec" type="QPrioSpec const"/>
  6586. <!--${QV::QActive::start_::qSto}-->
  6587. <parameter name="qSto" type="QEvt const * * const"/>
  6588. <!--${QV::QActive::start_::qLen}-->
  6589. <parameter name="qLen" type="uint_fast16_t const"/>
  6590. <!--${QV::QActive::start_::stkSto}-->
  6591. <parameter name="stkSto" type="void * const"/>
  6592. <!--${QV::QActive::start_::stkSize}-->
  6593. <parameter name="stkSize" type="uint_fast16_t const"/>
  6594. <!--${QV::QActive::start_::par}-->
  6595. <parameter name="par" type="void const * const"/>
  6596. <code>Q_UNUSED_PAR(stkSto); /* not needed in QV */
  6597. Q_UNUSED_PAR(stkSize); /* not needed in QV */
  6598. Q_REQUIRE_ID(300, stkSto == (void *)0);
  6599. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  6600. me-&gt;pthre = (uint8_t)(prioSpec &gt;&gt; 8U); /* preemption-threshold */
  6601. QActive_register_(me); /* make QF aware of this active object */
  6602. QEQueue_init(&amp;me-&gt;eQueue, qSto, qLen); /* init the built-in queue */
  6603. QHSM_INIT(&amp;me-&gt;super, par, me-&gt;prio); /* top-most initial tran. */
  6604. QS_FLUSH(); /* flush the trace buffer to the host */</code>
  6605. </operation>
  6606. </class>
  6607. </package>
  6608. <!--${QV-impl}-->
  6609. <package name="QV-impl" stereotype="0x02">
  6610. <!--${QV-impl::QF_SCHED_STAT_}-->
  6611. <attribute name="QF_SCHED_STAT_" type="" visibility="0x03" properties="0x00">
  6612. <documentation>/*! QV scheduler lock status (not needed in QV) */</documentation>
  6613. </attribute>
  6614. <!--${QV-impl::QF_SCHED_LOCK_}-->
  6615. <operation name="QF_SCHED_LOCK_" type="" visibility="0x03" properties="0x00">
  6616. <documentation>/*! QV scheduler locking (not needed in QV) */</documentation>
  6617. <!--${QV-impl::QF_SCHED_LOCK_::dummy}-->
  6618. <parameter name="dummy" type=""/>
  6619. <code>((void)0)</code>
  6620. </operation>
  6621. <!--${QV-impl::QF_SCHED_UNLOCK_}-->
  6622. <operation name="QF_SCHED_UNLOCK_" type="" visibility="0x03" properties="0x00">
  6623. <documentation>/*! QV scheduler unlocking (not needed in QV) */</documentation>
  6624. <code>((void)0)</code>
  6625. </operation>
  6626. <!--${QV-impl::QACTIVE_EQUEUE_WAIT_}-->
  6627. <operation name="QACTIVE_EQUEUE_WAIT_" type="" visibility="0x03" properties="0x00">
  6628. <documentation>* QV native event queue waiting</documentation>
  6629. <!--${QV-impl::QACTIVE_EQUEUE_W~::me_}-->
  6630. <parameter name="me_" type="QActive *"/>
  6631. <code>\
  6632. Q_ASSERT_ID(0, (me_)-&gt;eQueue.frontEvt != (QEvt *)0)</code>
  6633. </operation>
  6634. <!--${QV-impl::QACTIVE_EQUEUE_SIGNAL_}-->
  6635. <operation name="QACTIVE_EQUEUE_SIGNAL_" type="" visibility="0x03" properties="0x00">
  6636. <documentation>/*! QV native event queue signaling */</documentation>
  6637. <!--${QV-impl::QACTIVE_EQUEUE_S~::me_}-->
  6638. <parameter name="me_" type="QActive *"/>
  6639. <code>\
  6640. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)(me_)-&gt;prio)</code>
  6641. </operation>
  6642. </package>
  6643. <!--${QK}-->
  6644. <package name="QK" stereotype="0x05">
  6645. <!--${QK::QK-base}-->
  6646. <package name="QK-base" stereotype="0x02" namespace="QK_">
  6647. <!--${QK::QK-base::schedLock}-->
  6648. <operation name="schedLock" type="QSchedStatus" visibility="0x00" properties="0x01">
  6649. <documentation>/*! QK selective scheduler lock
  6650. * @static @public @memberof QK
  6651. *
  6652. * @details
  6653. * This function locks the QK scheduler to the specified ceiling.
  6654. *
  6655. * @param[in] ceiling preemption ceiling to which the QK scheduler
  6656. * needs to be locked
  6657. *
  6658. * @returns
  6659. * The previous QK Scheduler lock status, which is to be used to unlock
  6660. * the scheduler by restoring its previous lock status in
  6661. * QK_schedUnlock().
  6662. *
  6663. * @precondition{qk,600}
  6664. * - The QK scheduler lock cannot be called from an ISR
  6665. *
  6666. * @note
  6667. * QK_schedLock() must be always followed by the corresponding
  6668. * QK_schedUnlock().
  6669. *
  6670. * @sa QK_schedUnlock()
  6671. *
  6672. * @usage
  6673. * The following example shows how to lock and unlock the QK scheduler:
  6674. * @include qk_lock.c
  6675. */
  6676. /*! @static @public @memberof QK */</documentation>
  6677. <!--${QK::QK-base::schedLock::ceiling}-->
  6678. <parameter name="ceiling" type="uint_fast8_t const"/>
  6679. <code>QF_CRIT_STAT_
  6680. QF_CRIT_E_();
  6681. Q_REQUIRE_ID(600, !QK_ISR_CONTEXT_());
  6682. /* first store the previous lock prio */
  6683. QSchedStatus stat;
  6684. if (ceiling &gt; QK_attr_.lockCeil) { /* raising the lock ceiling? */
  6685. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_LOCK, 0U)
  6686. QS_TIME_PRE_(); /* timestamp */
  6687. /* the previous lock ceiling &amp; new lock ceiling */
  6688. QS_2U8_PRE_(QK_attr_.lockCeil, (uint8_t)ceiling);
  6689. QS_END_NOCRIT_PRE_()
  6690. /* previous status of the lock */
  6691. stat = (QSchedStatus)QK_attr_.lockHolder;
  6692. stat |= (QSchedStatus)QK_attr_.lockCeil &lt;&lt; 8U;
  6693. /* new status of the lock */
  6694. QK_attr_.lockHolder = QK_attr_.actPrio;
  6695. QK_attr_.lockCeil = (uint8_t)ceiling;
  6696. }
  6697. else {
  6698. stat = 0xFFU; /* scheduler not locked */
  6699. }
  6700. QF_CRIT_X_();
  6701. return stat; /* return the status to be saved in a stack variable */</code>
  6702. </operation>
  6703. <!--${QK::QK-base::schedUnlock}-->
  6704. <operation name="schedUnlock" type="void" visibility="0x00" properties="0x01">
  6705. <documentation>/*! QK selective scheduler unlock
  6706. * @static @public @memberof QK
  6707. *
  6708. * @details
  6709. * This function unlocks the QK scheduler to the previous status.
  6710. *
  6711. * @param[in] stat previous QK Scheduler lock status returned from
  6712. * QK_schedLock()
  6713. *
  6714. * @precondition{qk,700}
  6715. * - the QK scheduler cannot be unlocked: from the ISR context
  6716. * - the current lock ceiling must be greater than the previous
  6717. *
  6718. * @note
  6719. * QK_schedUnlock() must always follow the corresponding
  6720. * QK_schedLock().
  6721. *
  6722. * @sa QK_schedLock()
  6723. *
  6724. * @usage
  6725. * The following example shows how to lock and unlock the QK scheduler:
  6726. * @include qk_lock.c
  6727. */
  6728. /*! @static @public @memberof QK */</documentation>
  6729. <!--${QK::QK-base::schedUnlock::stat}-->
  6730. <parameter name="stat" type="QSchedStatus const"/>
  6731. <code>/* has the scheduler been actually locked by the last QK_schedLock()? */
  6732. if (stat != 0xFFU) {
  6733. uint8_t const lockCeil = QK_attr_.lockCeil;
  6734. uint8_t const prevCeil = (uint8_t)(stat &gt;&gt; 8U);
  6735. QF_CRIT_STAT_
  6736. QF_CRIT_E_();
  6737. Q_REQUIRE_ID(700, (!QK_ISR_CONTEXT_())
  6738. &amp;&amp; (lockCeil &gt; prevCeil));
  6739. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
  6740. QS_TIME_PRE_(); /* timestamp */
  6741. // current lock ceiling (old), previous lock ceiling (new) */
  6742. QS_2U8_PRE_(lockCeil, prevCeil);
  6743. QS_END_NOCRIT_PRE_()
  6744. /* restore the previous lock ceiling and lock holder */
  6745. QK_attr_.lockCeil = prevCeil;
  6746. QK_attr_.lockHolder = (uint8_t)(stat &amp; 0xFFU);
  6747. /* find if any AOs should be run after unlocking the scheduler */
  6748. if (QK_sched_() != 0U) { /* preemption needed? */
  6749. QK_activate_(); /* activate any unlocked AOs */
  6750. }
  6751. QF_CRIT_X_();
  6752. }</code>
  6753. </operation>
  6754. <!--${QK::QK-base::onIdle}-->
  6755. <operation name="onIdle" type="void" visibility="0x00" properties="0x01">
  6756. <documentation>/*! QK idle callback (customized in BSPs for QK)
  6757. * @static @public @memberof QK
  6758. *
  6759. * @details
  6760. * QK_onIdle() is called continuously by the QK idle loop. This callback
  6761. * gives the application an opportunity to enter a power-saving CPU mode,
  6762. * or perform some other idle processing.
  6763. *
  6764. * @note
  6765. * QK_onIdle() is invoked with interrupts enabled and must also return with
  6766. * interrupts enabled.
  6767. */
  6768. /*! @static @public @memberof QK */</documentation>
  6769. </operation>
  6770. </package>
  6771. <!--${QK::QF-cust}-->
  6772. <package name="QF-cust" stereotype="0x02" namespace="QF_">
  6773. <!--${QK::QF-cust::init}-->
  6774. <operation name="init" type="void" visibility="0x00" properties="0x01">
  6775. <documentation>/*! QF initialization for QK
  6776. * @static @public @memberof QF
  6777. */
  6778. /*! @static @public @memberof QF */</documentation>
  6779. <code>#if (QF_MAX_EPOOL &gt; 0U)
  6780. QF_maxPool_ = 0U;
  6781. #endif
  6782. QF_bzero(&amp;QTimeEvt_timeEvtHead_[0], sizeof(QTimeEvt_timeEvtHead_));
  6783. QF_bzero(&amp;QActive_registry_[0], sizeof(QActive_registry_));
  6784. QF_bzero(&amp;QF_readySet_, sizeof(QF_readySet_));
  6785. QF_bzero(&amp;QK_attr_, sizeof(QK_attr_));
  6786. /* setup the QK scheduler as initially locked and not running */
  6787. QK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); /* scheduler locked */
  6788. /* QK idle AO object (const in ROM) */
  6789. static QActive const idle_ao = { (struct QHsmVtable const *)0 };
  6790. /* register the idle AO object (cast 'const' away) */
  6791. QActive_registry_[0] = (QActive *)&amp;idle_ao;
  6792. #ifdef QK_INIT
  6793. QK_INIT(); /* port-specific initialization of the QK kernel */
  6794. #endif</code>
  6795. </operation>
  6796. <!--${QK::QF-cust::stop}-->
  6797. <operation name="stop" type="void" visibility="0x00" properties="0x01">
  6798. <documentation>/*! Stop the QF customization for QK
  6799. * @static @public @memberof QF
  6800. */
  6801. /*! @static @public @memberof QF */</documentation>
  6802. <code>QF_onCleanup(); /* application-specific cleanup callback */
  6803. /* nothing else to do for the preemptive QK kernel */</code>
  6804. </operation>
  6805. <!--${QK::QF-cust::run}-->
  6806. <operation name="run" type="int_t" visibility="0x00" properties="0x01">
  6807. <documentation>/*! QF_run() customization for QK kernel
  6808. * @static @public @memberof QF
  6809. */
  6810. /*! @static @public @memberof QF */</documentation>
  6811. <code>#ifdef Q_SPY
  6812. /* produce the QS_QF_RUN trace record */
  6813. QF_INT_DISABLE();
  6814. QS_beginRec_((uint_fast8_t)QS_QF_RUN);
  6815. QS_endRec_();
  6816. QF_INT_ENABLE();
  6817. #endif /* Q_SPY */
  6818. QF_onStartup(); /* application-specific startup callback */
  6819. QF_INT_DISABLE();
  6820. QK_attr_.lockCeil = 0U; /* unlock the QK scheduler */
  6821. /* activate AOs to process events posted so far */
  6822. if (QK_sched_() != 0U) {
  6823. QK_activate_();
  6824. }
  6825. #ifdef QK_START
  6826. QK_START(); /* port-specific startup of the QK kernel */
  6827. #endif
  6828. QF_INT_ENABLE();
  6829. for (;;) { /* QK idle loop... */
  6830. QK_onIdle(); /* application-specific QK on-idle callback */
  6831. }
  6832. #ifdef __GNUC__
  6833. return 0;
  6834. #endif</code>
  6835. </operation>
  6836. </package>
  6837. <!--${QK::QActive}-->
  6838. <class name="QActive">
  6839. <documentation>/*! QActive active object class customization for QK */</documentation>
  6840. <!--${QK::QActive::start_}-->
  6841. <operation name="start_" type="void" visibility="0x00" properties="0x04">
  6842. <documentation>/*! Starts execution of an active object and registers the object
  6843. * with the framework customized for the QK kernel
  6844. * @public @memberof QActive
  6845. *
  6846. * @precondition{qk,300}
  6847. * - stack storage must not be provided because the QK kernel
  6848. * does not need per-AO stacks.
  6849. */
  6850. /*! @public @memberof QActive */</documentation>
  6851. <!--${QK::QActive::start_::prioSpec}-->
  6852. <parameter name="prioSpec" type="QPrioSpec const"/>
  6853. <!--${QK::QActive::start_::qSto}-->
  6854. <parameter name="qSto" type="QEvt const * * const"/>
  6855. <!--${QK::QActive::start_::qLen}-->
  6856. <parameter name="qLen" type="uint_fast16_t const"/>
  6857. <!--${QK::QActive::start_::stkSto}-->
  6858. <parameter name="stkSto" type="void * const"/>
  6859. <!--${QK::QActive::start_::stkSize}-->
  6860. <parameter name="stkSize" type="uint_fast16_t const"/>
  6861. <!--${QK::QActive::start_::par}-->
  6862. <parameter name="par" type="void const * const"/>
  6863. <code>Q_UNUSED_PAR(stkSto); /* not needed in QK */
  6864. Q_UNUSED_PAR(stkSize); /* not needed in QK */
  6865. Q_REQUIRE_ID(300, (!QK_ISR_CONTEXT_())
  6866. &amp;&amp; (stkSto == (void *)0));
  6867. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  6868. me-&gt;pthre = (uint8_t)(prioSpec &gt;&gt; 8U); /* preemption-threshold */
  6869. QActive_register_(me); /* make QF aware of this active object */
  6870. QEQueue_init(&amp;me-&gt;eQueue, qSto, qLen); /* init the built-in queue */
  6871. QHSM_INIT(&amp;me-&gt;super, par, me-&gt;prio); /* top-most initial tran. */
  6872. QS_FLUSH(); /* flush the trace buffer to the host */
  6873. /* See if this AO needs to be scheduled if QK is already running */
  6874. QF_CRIT_STAT_
  6875. QF_CRIT_E_();
  6876. if (QK_sched_() != 0U) { /* activation needed? */
  6877. QK_activate_();
  6878. }
  6879. QF_CRIT_X_();</code>
  6880. </operation>
  6881. </class>
  6882. <!--${QK::QK-extern-C}-->
  6883. <package name="QK-extern-C" stereotype="0x02" namespace="QK_">
  6884. <!--${QK::QK-extern-C::Attr}-->
  6885. <attribute name="Attr" type="typedef struct" visibility="0x04" properties="0x00">
  6886. <documentation>/*! @brief QK preemptive non-blocking kernel
  6887. * @class QK
  6888. */</documentation>
  6889. <code>{
  6890. uint8_t volatile actPrio; /*!&lt; QF prio of the active AO */
  6891. uint8_t volatile nextPrio; /*!&lt; QF prio of the next AO to execute */
  6892. uint8_t volatile actThre; /*!&lt; active preemption-threshold */
  6893. uint8_t volatile lockCeil; /*!&lt; lock preemption-ceiling (0==no-lock) */
  6894. uint8_t volatile lockHolder; /*!&lt; QF prio of the AO holding the lock */
  6895. } QK;</code>
  6896. </attribute>
  6897. <!--${QK::QK-extern-C::attr_}-->
  6898. <attribute name="attr_" type="QK" visibility="0x00" properties="0x00">
  6899. <documentation>/*! attributes of the QK kernel
  6900. * @static @private @memberof QK
  6901. */
  6902. /*! @static @private @memberof QK */</documentation>
  6903. </attribute>
  6904. <!--${QK::QK-extern-C::sched_}-->
  6905. <operation name="sched_" type="uint_fast8_t" visibility="0x00" properties="0x00">
  6906. <documentation>/*! QK scheduler finds the highest-priority AO ready to run
  6907. * @static @private @memberof QK
  6908. *
  6909. * @details
  6910. * The QK scheduler finds out the priority of the highest-priority AO
  6911. * that (1) has events to process and (2) has priority that is above the
  6912. * current priority.
  6913. *
  6914. * @returns
  6915. * The QF-priority of the next active object to activate, or zero
  6916. * if no activation of AO is needed.
  6917. *
  6918. * @attention
  6919. * QK_sched_() must be always called with interrupts **disabled** and
  6920. * returns with interrupts **disabled**.
  6921. */
  6922. /*! @static @private @memberof QK */</documentation>
  6923. <code>uint_fast8_t p;
  6924. if (QPSet_isEmpty(&amp;QF_readySet_)) {
  6925. p = 0U; /* no activation needed */
  6926. }
  6927. else {
  6928. /* find the highest-prio AO with non-empty event queue */
  6929. p = QPSet_findMax(&amp;QF_readySet_);
  6930. /* is the AO's priority below the active preemption-threshold? */
  6931. if (p &lt;= QK_attr_.actThre) {
  6932. p = 0U; /* no activation needed */
  6933. }
  6934. /* is the AO's priority below the lock-ceiling? */
  6935. else if (p &lt;= QK_attr_.lockCeil) {
  6936. p = 0U; /* no activation needed */
  6937. }
  6938. else {
  6939. QK_attr_.nextPrio = (uint8_t)p; /* next AO to run */
  6940. }
  6941. }
  6942. return p;</code>
  6943. </operation>
  6944. <!--${QK::QK-extern-C::activate_}-->
  6945. <operation name="activate_" type="void" visibility="0x00" properties="0x00">
  6946. <documentation>/*! QK activator activates the next active object. The activated AO preempts
  6947. * the currently executing AOs.
  6948. * @static @private @memberof QK
  6949. *
  6950. * @details
  6951. * QK_activate_() activates ready-to run AOs that are above the initial
  6952. * preemption-threshold.
  6953. *
  6954. * @precondition{qk,500}
  6955. * - QK_attr_.actPrio and QK_attr_.nextPrio must be in range
  6956. *
  6957. * @attention
  6958. * QK_activate_() must be always called with interrupts **disabled** and
  6959. * returns with interrupts **disabled**.
  6960. */
  6961. /*! @static @private @memberof QK */</documentation>
  6962. <code>uint8_t const prio_in = QK_attr_.actPrio; /* saved initial priority */
  6963. uint8_t p = QK_attr_.nextPrio; /* next prio to run */
  6964. QK_attr_.nextPrio = 0U; /* clear for the next time */
  6965. Q_REQUIRE_ID(500, (prio_in &lt;= QF_MAX_ACTIVE)
  6966. &amp;&amp; (0U &lt; p) &amp;&amp; (p &lt;= QF_MAX_ACTIVE));
  6967. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  6968. uint8_t pprev = prio_in;
  6969. #endif /* QF_ON_CONTEXT_SW || Q_SPY */
  6970. /* loop until no more ready-to-run AOs of higher pthre than the initial */
  6971. QActive *a;
  6972. do {
  6973. a = QActive_registry_[p]; /* obtain the pointer to the AO */
  6974. Q_ASSERT_ID(505, a != (QActive *)0); /* the AO must be registered */
  6975. /* set new active priority and preemption-threshold */
  6976. QK_attr_.actPrio = p;
  6977. QK_attr_.actThre = a-&gt;pthre;
  6978. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  6979. if (p != pprev) { /* changing threads? */
  6980. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_NEXT, p)
  6981. QS_TIME_PRE_(); /* timestamp */
  6982. QS_2U8_PRE_(p, /* priority of the scheduled AO */
  6983. pprev); /* previous priority */
  6984. QS_END_NOCRIT_PRE_()
  6985. #ifdef QF_ON_CONTEXT_SW
  6986. QF_onContextSw(((pprev != 0U)
  6987. ? QActive_registry_[pprev]
  6988. : (QActive *)0), a);
  6989. #endif /* QF_ON_CONTEXT_SW */
  6990. pprev = p; /* update previous priority */
  6991. }
  6992. #endif /* QF_ON_CONTEXT_SW || Q_SPY */
  6993. QF_INT_ENABLE(); /* unconditionally enable interrupts */
  6994. /* perform the run-to-completion (RTC) step...
  6995. * 1. retrieve the event from the AO's event queue, which by this
  6996. * time must be non-empty and QActive_get_() asserts it.
  6997. * 2. dispatch the event to the AO's state machine.
  6998. * 3. determine if event is garbage and collect it if so
  6999. */
  7000. QEvt const * const e = QActive_get_(a);
  7001. QHSM_DISPATCH(&amp;a-&gt;super, e, p);
  7002. #if (QF_MAX_EPOOL &gt; 0U)
  7003. QF_gc(e);
  7004. #endif
  7005. /* determine the next highest-priority AO ready to run... */
  7006. QF_INT_DISABLE(); /* unconditionally disable interrupts */
  7007. if (a-&gt;eQueue.frontEvt == (QEvt *)0) { /* empty queue? */
  7008. QPSet_remove(&amp;QF_readySet_, p);
  7009. }
  7010. if (QPSet_isEmpty(&amp;QF_readySet_)) {
  7011. p = 0U; /* no activation needed */
  7012. }
  7013. else {
  7014. /* find new highest-prio AO ready to run... */
  7015. p = (uint8_t)QPSet_findMax(&amp;QF_readySet_);
  7016. /* is the new priority below the initial preemption-threshold? */
  7017. if (p &lt;= QActive_registry_[prio_in]-&gt;pthre) {
  7018. p = 0U; /* no activation needed */
  7019. }
  7020. /* is the AO's priority below the lock preemption-ceiling? */
  7021. else if (p &lt;= QK_attr_.lockCeil) {
  7022. p = 0U; /* no activation needed */
  7023. }
  7024. else {
  7025. Q_ASSERT_ID(510, p &lt;= QF_MAX_ACTIVE);
  7026. }
  7027. }
  7028. } while (p != 0U);
  7029. /* restore the active priority and preemption-threshold */
  7030. QK_attr_.actPrio = prio_in;
  7031. QK_attr_.actThre = QActive_registry_[prio_in]-&gt;pthre;
  7032. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  7033. if (prio_in != 0U) { /* resuming an active object? */
  7034. a = QActive_registry_[prio_in]; /* pointer to the preempted AO */
  7035. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_NEXT, prio_in)
  7036. QS_TIME_PRE_(); /* timestamp */
  7037. /* priority of the resumed AO, previous priority */
  7038. QS_2U8_PRE_(prio_in, pprev);
  7039. QS_END_NOCRIT_PRE_()
  7040. }
  7041. else { /* resuming priority==0 --&gt; idle */
  7042. a = (QActive *)0; /* QK idle loop */
  7043. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_IDLE, pprev)
  7044. QS_TIME_PRE_(); /* timestamp */
  7045. QS_U8_PRE_(pprev); /* previous priority */
  7046. QS_END_NOCRIT_PRE_()
  7047. }
  7048. #ifdef QF_ON_CONTEXT_SW
  7049. QF_onContextSw(QActive_registry_[pprev], a);
  7050. #endif /* QF_ON_CONTEXT_SW */
  7051. #endif /* QF_ON_CONTEXT_SW || Q_SPY */</code>
  7052. </operation>
  7053. </package>
  7054. </package>
  7055. <!--${QK-impl}-->
  7056. <package name="QK-impl" stereotype="0x02">
  7057. <!--${QK-impl::QK_ISR_CONTEXT_}-->
  7058. <operation name="QK_ISR_CONTEXT_?ndef QK_ISR_CONTEXT_" type="" visibility="0x03" properties="0x00">
  7059. <documentation>/*! Internal macro that reports the execution context (ISR vs. thread)
  7060. *
  7061. * @returns true if the code executes in the ISR context and false
  7062. * otherwise
  7063. */</documentation>
  7064. <code>(QF_intNest_ != 0U)</code>
  7065. </operation>
  7066. <!--${QK-impl::QF_SCHED_STAT_}-->
  7067. <attribute name="QF_SCHED_STAT_" type="" visibility="0x03" properties="0x00">
  7068. <documentation>/*! QK scheduler lock status */</documentation>
  7069. <code>QSchedStatus lockStat_;</code>
  7070. </attribute>
  7071. <!--${QK-impl::QF_SCHED_LOCK_}-->
  7072. <operation name="QF_SCHED_LOCK_" type="" visibility="0x03" properties="0x00">
  7073. <documentation>/*! QK selective scheduler locking */</documentation>
  7074. <!--${QK-impl::QF_SCHED_LOCK_::ceil_}-->
  7075. <parameter name="ceil_" type="uint_fast8_t"/>
  7076. <code>do { \
  7077. if (QK_ISR_CONTEXT_()) { \
  7078. lockStat_ = 0xFFU; \
  7079. } else { \
  7080. lockStat_ = QK_schedLock((ceil_)); \
  7081. } \
  7082. } while (false)</code>
  7083. </operation>
  7084. <!--${QK-impl::QF_SCHED_UNLOCK_}-->
  7085. <operation name="QF_SCHED_UNLOCK_" type="" visibility="0x03" properties="0x00">
  7086. <documentation>/*! QK selective scheduler unlocking */</documentation>
  7087. <code>do { \
  7088. if (lockStat_ != 0xFFU) { \
  7089. QK_schedUnlock(lockStat_); \
  7090. } \
  7091. } while (false)</code>
  7092. </operation>
  7093. <!--${QK-impl::QACTIVE_EQUEUE_WAIT_}-->
  7094. <operation name="QACTIVE_EQUEUE_WAIT_" type="" visibility="0x03" properties="0x00">
  7095. <documentation>/*! QK native event queue waiting */</documentation>
  7096. <!--${QK-impl::QACTIVE_EQUEUE_W~::me_}-->
  7097. <parameter name="me_" type="QActive *"/>
  7098. <code>\
  7099. (Q_ASSERT_ID(110, (me_)-&gt;eQueue.frontEvt != (QEvt *)0))</code>
  7100. </operation>
  7101. <!--${QK-impl::QACTIVE_EQUEUE_SIGNAL_}-->
  7102. <operation name="QACTIVE_EQUEUE_SIGNAL_" type="" visibility="0x03" properties="0x00">
  7103. <documentation>/*! QK native event queue signaling */</documentation>
  7104. <!--${QK-impl::QACTIVE_EQUEUE_S~::me_}-->
  7105. <parameter name="me_" type="QActive *"/>
  7106. <code>do { \
  7107. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)(me_)-&gt;prio); \
  7108. if (!QK_ISR_CONTEXT_()) { \
  7109. if (QK_sched_() != 0U) { \
  7110. QK_activate_(); \
  7111. } \
  7112. } \
  7113. } while (false)</code>
  7114. </operation>
  7115. </package>
  7116. <!--${QXK}-->
  7117. <package name="QXK" stereotype="0x05">
  7118. <!--${QXK::QXK-base}-->
  7119. <package name="QXK-base" stereotype="0x02" namespace="QXK_">
  7120. <!--${QXK::QXK-base::onIdle}-->
  7121. <operation name="onIdle" type="void" visibility="0x00" properties="0x01">
  7122. <documentation>/*! QXK idle callback (customized in BSPs for QXK)
  7123. * @static @public @memberof QXK
  7124. *
  7125. * @details
  7126. * QXK_onIdle() is called continuously by the QXK idle thread. This callback
  7127. * gives the application an opportunity to enter a power-saving CPU mode,
  7128. * or perform some other idle processing.
  7129. *
  7130. * @note
  7131. * QXK_onIdle() is invoked with interrupts enabled and must also return with
  7132. * interrupts enabled.
  7133. */
  7134. /*! @static @public @memberof QXK */</documentation>
  7135. </operation>
  7136. <!--${QXK::QXK-base::schedLock}-->
  7137. <operation name="schedLock" type="QSchedStatus" visibility="0x00" properties="0x01">
  7138. <documentation>/*! QXK Scheduler lock
  7139. * @static @public @memberof QXK
  7140. *
  7141. * @details
  7142. * This function locks the QXK scheduler to the specified ceiling.
  7143. *
  7144. * @param[in] ceiling preemption ceiling to which the QXK scheduler
  7145. * needs to be locked
  7146. *
  7147. * @returns
  7148. * The previous QXK Scheduler lock status, which is to be used to unlock
  7149. * the scheduler by restoring its previous lock status in
  7150. * QXK_schedUnlock().
  7151. *
  7152. * @precondition{qxk,400}
  7153. * - the QXK scheduler lock cannot be called from an ISR
  7154. *
  7155. * @note
  7156. * A QXK scheduler can be locked from both basic threads (AOs) and
  7157. * extended threads and the scheduler locks can nest.
  7158. *
  7159. * @note
  7160. * QXK_schedLock() must be always followed by the corresponding
  7161. * QXK_schedUnlock().
  7162. *
  7163. * @attention
  7164. * QXK will fire an assertion if a thread holding the lock attempts
  7165. * to block.
  7166. *
  7167. * @sa QXK_schedUnlock()
  7168. *
  7169. * @usage
  7170. * The following example shows how to lock and unlock the QXK scheduler:
  7171. * @include qxk_lock.c
  7172. */
  7173. /*! @static @public @memberof QXK */</documentation>
  7174. <!--${QXK::QXK-base::schedLock::ceiling}-->
  7175. <parameter name="ceiling" type="uint_fast8_t const"/>
  7176. <code>QF_CRIT_STAT_
  7177. QF_CRIT_E_();
  7178. Q_REQUIRE_ID(400, !QXK_ISR_CONTEXT_());
  7179. QSchedStatus stat; /* saved lock status to be returned */
  7180. /* is the lock ceiling being raised? */
  7181. if (ceiling &gt; (uint_fast8_t)QXK_attr_.lockCeil) {
  7182. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_LOCK, 0U)
  7183. QS_TIME_PRE_(); /* timestamp */
  7184. /* the previous lock ceiling &amp; new lock ceiling */
  7185. QS_2U8_PRE_(QXK_attr_.lockCeil, (uint8_t)ceiling);
  7186. QS_END_NOCRIT_PRE_()
  7187. /* previous status of the lock */
  7188. stat = (QSchedStatus)QXK_attr_.lockHolder;
  7189. stat |= (QSchedStatus)QXK_attr_.lockCeil &lt;&lt; 8U;
  7190. /* new status of the lock */
  7191. QXK_attr_.lockHolder = (QXK_attr_.curr != (QActive *)0)
  7192. ? QXK_attr_.curr-&gt;prio
  7193. : 0U;
  7194. QXK_attr_.lockCeil = (uint8_t)ceiling;
  7195. }
  7196. else {
  7197. stat = 0xFFU; /* scheduler not locked */
  7198. }
  7199. QF_CRIT_X_();
  7200. return stat; /* return the status to be saved in a stack variable */</code>
  7201. </operation>
  7202. <!--${QXK::QXK-base::schedUnlock}-->
  7203. <operation name="schedUnlock" type="void" visibility="0x00" properties="0x01">
  7204. <documentation>/*! QXK Scheduler unlock
  7205. * @static @public @memberof QXK
  7206. *
  7207. * @details
  7208. * This function unlocks the QXK scheduler to the previous status.
  7209. *
  7210. * @param[in] stat previous QXK Scheduler lock status returned from
  7211. * QXK_schedLock()
  7212. *
  7213. * @precondition{qxk,500}
  7214. * - the QXK scheduler cannot be unlocked from the ISR context
  7215. * @precondition{qxk,501}
  7216. * - the current lock ceiling must be greater than the previous
  7217. *
  7218. * @note
  7219. * A QXK scheduler can be locked from both basic threads (AOs) and
  7220. * extended threads and the scheduler locks can nest.
  7221. *
  7222. * @note
  7223. * QXK_schedUnlock() must always follow the corresponding QXK_schedLock().
  7224. *
  7225. * @usage
  7226. * The following example shows how to lock and unlock the QXK scheduler:
  7227. * @include qxk_lock.c
  7228. */
  7229. /*! @static @public @memberof QXK */</documentation>
  7230. <!--${QXK::QXK-base::schedUnlock::stat}-->
  7231. <parameter name="stat" type="QSchedStatus const"/>
  7232. <code>/* has the scheduler been actually locked by the last QXK_schedLock()? */
  7233. if (stat != 0xFFU) {
  7234. uint8_t const prevCeil = (uint8_t)(stat &gt;&gt; 8U);
  7235. QF_CRIT_STAT_
  7236. QF_CRIT_E_();
  7237. Q_REQUIRE_ID(500, !QXK_ISR_CONTEXT_());
  7238. Q_REQUIRE_ID(501, QXK_attr_.lockCeil &gt; prevCeil);
  7239. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_UNLOCK, 0U)
  7240. QS_TIME_PRE_(); /* timestamp */
  7241. /* ceiling before unlocking &amp; prio after unlocking */
  7242. QS_2U8_PRE_(QXK_attr_.lockCeil, prevCeil);
  7243. QS_END_NOCRIT_PRE_()
  7244. /* restore the previous lock ceiling and lock holder */
  7245. QXK_attr_.lockCeil = prevCeil;
  7246. QXK_attr_.lockHolder = (uint8_t)(stat &amp; 0xFFU);
  7247. /* find if any threads should be run after unlocking the scheduler */
  7248. if (QXK_sched_() != 0U) { /* activation needed? */
  7249. QXK_activate_(); /* synchronously activate basic-thred(s) */
  7250. }
  7251. QF_CRIT_X_();
  7252. }</code>
  7253. </operation>
  7254. <!--${QXK::QXK-base::Timeouts}-->
  7255. <attribute name="Timeouts" type="enum" visibility="0x04" properties="0x00">
  7256. <documentation>/*! timeout signals for extended threads
  7257. * @static @private @memberof QXK
  7258. */
  7259. /*! @static @private @memberof QXK */</documentation>
  7260. <code>{
  7261. QXK_DELAY_SIG = 1,
  7262. QXK_TIMEOUT_SIG
  7263. };</code>
  7264. </attribute>
  7265. </package>
  7266. <!--${QXK::QF-cust}-->
  7267. <package name="QF-cust" stereotype="0x02" namespace="QF_">
  7268. <!--${QXK::QF-cust::init}-->
  7269. <operation name="init" type="void" visibility="0x00" properties="0x01">
  7270. <documentation>/*! QF initialization for QXK
  7271. * @static @public @memberof QF
  7272. */
  7273. /*! @static @public @memberof QF */</documentation>
  7274. <code>#if (QF_MAX_EPOOL &gt; 0U)
  7275. QF_maxPool_ = 0U;
  7276. #endif
  7277. QF_bzero(&amp;QTimeEvt_timeEvtHead_[0], sizeof(QTimeEvt_timeEvtHead_));
  7278. QF_bzero(&amp;QActive_registry_[0], sizeof(QActive_registry_));
  7279. QF_bzero(&amp;QF_readySet_, sizeof(QF_readySet_));
  7280. QF_bzero(&amp;QXK_attr_, sizeof(QXK_attr_));
  7281. /* setup the QXK scheduler as initially locked and not running */
  7282. QXK_attr_.lockCeil = (QF_MAX_ACTIVE + 1U); /* scheduler locked */
  7283. /* QXK idle AO object (const in ROM) */
  7284. static QActive const idle_ao = { (struct QHsmVtable const *)0 };
  7285. /* register the idle AO object (cast 'const' away) */
  7286. QActive_registry_[0] = (QActive *)&amp;idle_ao;
  7287. QXK_attr_.prev = QActive_registry_[0];
  7288. #ifdef QXK_INIT
  7289. QXK_INIT(); /* port-specific initialization of the QXK kernel */
  7290. #endif</code>
  7291. </operation>
  7292. <!--${QXK::QF-cust::stop}-->
  7293. <operation name="stop" type="void" visibility="0x00" properties="0x01">
  7294. <documentation>/*! Stop the QF customization for QXK
  7295. * @static @public @memberof QF
  7296. */
  7297. /*! @static @public @memberof QF */</documentation>
  7298. <code>QF_onCleanup(); /* application-specific cleanup callback */
  7299. /* nothing else to do for the dual-mode QXK kernel */</code>
  7300. </operation>
  7301. <!--${QXK::QF-cust::run}-->
  7302. <operation name="run" type="int_t" visibility="0x00" properties="0x01">
  7303. <documentation>/*! QF_run() customization for QXK kernel
  7304. * @static @public @memberof QF
  7305. */
  7306. /*! @static @public @memberof QF */</documentation>
  7307. <code>#ifdef Q_SPY
  7308. QS_SIG_DICTIONARY(QXK_DELAY_SIG, (void *)0);
  7309. QS_SIG_DICTIONARY(QXK_TIMEOUT_SIG, (void *)0);
  7310. /* produce the QS_QF_RUN trace record */
  7311. QF_INT_DISABLE();
  7312. QS_beginRec_((uint_fast8_t)QS_QF_RUN);
  7313. QS_endRec_();
  7314. QF_INT_ENABLE();
  7315. #endif /* Q_SPY */
  7316. QF_onStartup(); /* application-specific startup callback */
  7317. QF_INT_DISABLE();
  7318. QXK_attr_.lockCeil = 0U; /* unlock the QXK scheduler */
  7319. /* activate AOs to process events posted so far */
  7320. if (QXK_sched_() != 0U) {
  7321. QXK_activate_();
  7322. }
  7323. #ifdef QXK_START
  7324. QXK_START(); /* port-specific startup of the QXK kernel */
  7325. #endif
  7326. QF_INT_ENABLE();
  7327. for (;;) { /* QXK idle loop... */
  7328. QXK_onIdle(); /* application-specific QXK idle callback */
  7329. }
  7330. #ifdef __GNUC__
  7331. return 0;
  7332. #endif</code>
  7333. </operation>
  7334. </package>
  7335. <!--${QXK::QXThread}-->
  7336. <class name="QXThread" superclass="QF::QActive">
  7337. <documentation>/*! @brief eXtended (blocking) thread of the QXK preemptive kernel
  7338. * @class QXThread
  7339. * @extends QActive
  7340. *
  7341. * @details
  7342. * ::QXThread represents the eXtended (blocking) thread of the QXK
  7343. * kernel. Each extended thread in the application must be represented
  7344. * by the corresponding ::QXThread instance
  7345. *
  7346. * @note
  7347. * Typically, ::QXThread is instantiated directly in the application code.
  7348. * The customization of the thread occurs in the QXThread_ctor(), where you
  7349. * provide the thread-handler function as the parameter.
  7350. *
  7351. * @usage
  7352. * The following example illustrates how to instantiate and use an extended
  7353. * thread in your application.
  7354. * @include qxk_thread.c
  7355. */</documentation>
  7356. <!--${QXK::QXThread::timeEvt}-->
  7357. <attribute name="timeEvt" type="QTimeEvt" visibility="0x02" properties="0x00">
  7358. <documentation>/*! time event to handle blocking timeouts */</documentation>
  7359. </attribute>
  7360. <!--${QXK::QXThread::dummy}-->
  7361. <attribute name="dummy" type="QXThread const *" visibility="0x02" properties="0x01">
  7362. <documentation>/*! dummy static to force generation of &quot;struct QXThread&quot; */</documentation>
  7363. </attribute>
  7364. <!--${QXK::QXThread::ctor}-->
  7365. <operation name="ctor" type="void" visibility="0x00" properties="0x00">
  7366. <documentation>/*! constructor of an extended-thread
  7367. * @public @memberof QXThread
  7368. *
  7369. * @details
  7370. * Performs the first step of QXThread initialization by assigning the
  7371. * thread-handler function and the tick rate at which it will handle
  7372. * the timeouts.
  7373. *
  7374. * @param[in,out] me current instance pointer (see @ref oop)
  7375. * @param[in] handler the thread-handler function
  7376. * @param[in] tickRate the ticking rate for timeouts in this thread
  7377. * (see QXThread_delay() and QTIMEEVT_TICK_X())
  7378. *
  7379. * @note
  7380. * Must be called only ONCE before QXTHREAD_START().
  7381. *
  7382. * @usage
  7383. * The following example illustrates how to invoke QXThread_ctor() in the
  7384. * main() function
  7385. *
  7386. * @include
  7387. * qxk_thread_ctor.c
  7388. */
  7389. /*! @public @memberof QXThread */</documentation>
  7390. <!--${QXK::QXThread::ctor::handler}-->
  7391. <parameter name="handler" type="QXThreadHandler const"/>
  7392. <!--${QXK::QXThread::ctor::tickRate}-->
  7393. <parameter name="tickRate" type="uint_fast8_t const"/>
  7394. <code>static QXThreadVtable const vtable = { /* QXThread virtual table */
  7395. { &amp;QXThread_init_, /* not used in QXThread */
  7396. &amp;QXThread_dispatch_ /* not used in QXThread */
  7397. #ifdef Q_SPY
  7398. ,&amp;QHsm_getStateHandler_ /* not used in QXThread */
  7399. #endif
  7400. },
  7401. &amp;QXThread_start_,
  7402. &amp;QXThread_post_,
  7403. &amp;QXThread_postLIFO_
  7404. };
  7405. union QHsmAttr tmp;
  7406. tmp.thr = handler;
  7407. QActive_ctor(&amp;me-&gt;super, tmp.fun); /* superclass' ctor */
  7408. me-&gt;super.super.vptr = &amp;vtable.super; /* hook to QXThread vtable */
  7409. me-&gt;super.super.state.act = Q_ACTION_CAST(0); /*mark as extended thread */
  7410. /* construct the time event member added in the QXThread class */
  7411. QTimeEvt_ctorX(&amp;me-&gt;timeEvt, &amp;me-&gt;super,
  7412. (enum_t)QXK_DELAY_SIG, tickRate);</code>
  7413. </operation>
  7414. <!--${QXK::QXThread::delay}-->
  7415. <operation name="delay" type="bool" visibility="0x00" properties="0x01">
  7416. <documentation>/*! delay (block) the current extended thread for a specified # ticks
  7417. * @static @public @memberof QXThread
  7418. *
  7419. * @details
  7420. * Blocking delay for the number of clock tick at the associated tick rate.
  7421. *
  7422. * @param[in] nTicks number of clock ticks (at the associated rate)
  7423. * to wait for the event to arrive.
  7424. *
  7425. * @returns
  7426. * 'true' if delay has expired, 'false' if it delay was canceled with
  7427. * QXThread_delayCancel().
  7428. *
  7429. * @precondition{qxk_xthr,800}
  7430. * - must NOT be called from an ISR;
  7431. * - number of ticks cannot be zero
  7432. * - be called from an extended thread;
  7433. * - the thread must NOT be already blocked on any object.
  7434. * @precondition{qxk_xthr,801}
  7435. * - the thread must NOT be holding a scheduler lock.
  7436. *
  7437. * @note
  7438. * For the delay to work, the QTIMEEVT_TICK_X() macro needs to be called
  7439. * periodically at the associated clock tick rate.
  7440. *
  7441. * @sa QXThread_ctor()
  7442. * @sa QTIMEEVT_TICK_X()
  7443. */
  7444. /*! @public @memberof QXThread */</documentation>
  7445. <!--${QXK::QXThread::delay::nTicks}-->
  7446. <parameter name="nTicks" type="uint_fast16_t const"/>
  7447. <code>QF_CRIT_STAT_
  7448. QF_CRIT_E_();
  7449. QXThread * const thr = QXTHREAD_CAST_(QXK_attr_.curr);
  7450. Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
  7451. &amp;&amp; (nTicks != 0U) /* number of ticks cannot be zero */
  7452. &amp;&amp; (thr != (QXThread *)0) /* current thread must be extended */
  7453. &amp;&amp; (thr-&gt;super.super.temp.obj == (QMState *)0)); /* !blocked */
  7454. Q_REQUIRE_ID(801, QXK_attr_.lockHolder != thr-&gt;super.prio);
  7455. /* remember the blocking object */
  7456. thr-&gt;super.super.temp.obj = QXK_PTR_CAST_(QMState const*, &amp;thr-&gt;timeEvt);
  7457. QXThread_teArm_(thr, (enum_t)QXK_DELAY_SIG, nTicks);
  7458. QXThread_block_(thr);
  7459. QF_CRIT_X_();
  7460. QF_CRIT_EXIT_NOP(); /* BLOCK here */
  7461. QF_CRIT_E_();
  7462. /* the blocking object must be the time event */
  7463. Q_ENSURE_ID(890, thr-&gt;super.super.temp.obj
  7464. == QXK_PTR_CAST_(QMState const*, &amp;thr-&gt;timeEvt));
  7465. thr-&gt;super.super.temp.obj = (QMState *)0; /* clear */
  7466. QF_CRIT_X_();
  7467. /* signal of zero means that the time event was posted without
  7468. * being canceled.
  7469. */
  7470. return thr-&gt;timeEvt.super.sig == 0U;</code>
  7471. </operation>
  7472. <!--${QXK::QXThread::delayCancel}-->
  7473. <operation name="delayCancel" type="bool" visibility="0x00" properties="0x00">
  7474. <documentation>/*! cancel the delay
  7475. * @public @memberof QXThread
  7476. *
  7477. * @details
  7478. * Cancel the blocking delay and cause return from the QXThread_delay()
  7479. * function.
  7480. *
  7481. * @returns
  7482. * &quot;true&quot; if the thread was actually blocked on QXThread_delay() and
  7483. * &quot;false&quot; otherwise.
  7484. */
  7485. /*! @public @memberof QXThread */</documentation>
  7486. <code>QF_CRIT_STAT_
  7487. QF_CRIT_E_();
  7488. bool wasArmed;
  7489. if (me-&gt;super.super.temp.obj == QXK_PTR_CAST_(QMState*, &amp;me-&gt;timeEvt)) {
  7490. wasArmed = QXThread_teDisarm_(me);
  7491. QXThread_unblock_(me);
  7492. }
  7493. else {
  7494. wasArmed = false;
  7495. }
  7496. QF_CRIT_X_();
  7497. return wasArmed;</code>
  7498. </operation>
  7499. <!--${QXK::QXThread::queueGet}-->
  7500. <operation name="queueGet" type="QEvt const *" visibility="0x00" properties="0x01">
  7501. <documentation>/*! obtain a message from the private message queue (block if no messages)
  7502. * @static @public @memberof QXThread
  7503. *
  7504. * @details
  7505. * The QXThread_queueGet() operation allows the calling extended thread to
  7506. * receive QP events directly into its own built-in event queue from an ISR,
  7507. * basic thread (AO), or another extended thread.
  7508. *
  7509. * If QXThread_queueGet() is called when no events are present in the
  7510. * thread's private event queue, the operation blocks the current extended
  7511. * thread until either an event is received, or a user-specified timeout
  7512. * expires.
  7513. *
  7514. * @param[in] nTicks number of clock ticks (at the associated rate)
  7515. * to wait for the event to arrive. The value of
  7516. * ::QXTHREAD_NO_TIMEOUT indicates that no timeout will
  7517. * occur and the queue will block indefinitely.
  7518. * @returns
  7519. * A pointer to the event. If the pointer is not NULL, the event was delivered.
  7520. * Otherwise the event pointer of NULL indicates that the queue has timed out.
  7521. *
  7522. * @precondition{qxk_xthr,500}
  7523. * - must NOT be called from an ISR;
  7524. * - be called from an extended thread;
  7525. * - the thread must NOT be already blocked on any object.
  7526. * @precondition{qxk_xthr,501}
  7527. * - the thread must NOT be holding a scheduler lock.
  7528. */
  7529. /*! @static @public @memberof QXThread */</documentation>
  7530. <!--${QXK::QXThread::queueGet::nTicks}-->
  7531. <parameter name="nTicks" type="uint_fast16_t const"/>
  7532. <code>QF_CRIT_STAT_
  7533. QF_CRIT_E_();
  7534. QXThread * const thr = QXTHREAD_CAST_(QXK_attr_.curr);
  7535. Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
  7536. &amp;&amp; (thr != (QXThread *)0) /* current thread must be extended */
  7537. &amp;&amp; (thr-&gt;super.super.temp.obj == (QMState *)0)); /* !blocked */
  7538. Q_REQUIRE_ID(501, QXK_attr_.lockHolder != thr-&gt;super.prio);
  7539. /* is the queue empty? */
  7540. if (thr-&gt;super.eQueue.frontEvt == (QEvt *)0) {
  7541. /* remember the blocking object (the thread's queue) */
  7542. thr-&gt;super.super.temp.obj
  7543. = QXK_PTR_CAST_(QMState const*, &amp;thr-&gt;super.eQueue);
  7544. QXThread_teArm_(thr, (enum_t)QXK_TIMEOUT_SIG, nTicks);
  7545. QPSet_remove(&amp;QF_readySet_, (uint_fast8_t)thr-&gt;super.prio);
  7546. (void)QXK_sched_(); /* schedule other threads */
  7547. QF_CRIT_X_();
  7548. QF_CRIT_EXIT_NOP(); /* BLOCK here */
  7549. QF_CRIT_E_();
  7550. /* the blocking object must be this queue */
  7551. Q_ASSERT_ID(510, thr-&gt;super.super.temp.obj
  7552. == QXK_PTR_CAST_(QMState const*, &amp;thr-&gt;super.eQueue));
  7553. thr-&gt;super.super.temp.obj = (QMState *)0; /* clear */
  7554. }
  7555. /* is the queue not empty? */
  7556. QEvt const *e;
  7557. if (thr-&gt;super.eQueue.frontEvt != (QEvt *)0) {
  7558. e = thr-&gt;super.eQueue.frontEvt; /* remove from the front */
  7559. QEQueueCtr const nFree= thr-&gt;super.eQueue.nFree + 1U;
  7560. thr-&gt;super.eQueue.nFree = nFree; /* update the number of free */
  7561. /* any events in the ring buffer? */
  7562. if (nFree &lt;= thr-&gt;super.eQueue.end) {
  7563. /* remove event from the tail */
  7564. thr-&gt;super.eQueue.frontEvt =
  7565. thr-&gt;super.eQueue.ring[thr-&gt;super.eQueue.tail];
  7566. if (thr-&gt;super.eQueue.tail == 0U) { /* need to wrap? */
  7567. thr-&gt;super.eQueue.tail = thr-&gt;super.eQueue.end; /* wrap */
  7568. }
  7569. --thr-&gt;super.eQueue.tail;
  7570. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_GET, thr-&gt;super.prio)
  7571. QS_TIME_PRE_(); /* timestamp */
  7572. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  7573. QS_OBJ_PRE_(&amp;thr-&gt;super); /* this active object */
  7574. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  7575. QS_EQC_PRE_(nFree); /* number of free entries */
  7576. QS_END_NOCRIT_PRE_()
  7577. }
  7578. else {
  7579. thr-&gt;super.eQueue.frontEvt = (QEvt *)0; /* empty queue */
  7580. /* all entries in the queue must be free (+1 for fronEvt) */
  7581. Q_ASSERT_ID(520, nFree == (thr-&gt;super.eQueue.end + 1U));
  7582. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_GET_LAST, thr-&gt;super.prio)
  7583. QS_TIME_PRE_(); /* timestamp */
  7584. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  7585. QS_OBJ_PRE_(&amp;thr-&gt;super); /* this active object */
  7586. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  7587. QS_END_NOCRIT_PRE_()
  7588. }
  7589. }
  7590. else { /* the queue is still empty -- the timeout must have fired */
  7591. e = (QEvt *)0;
  7592. }
  7593. QF_CRIT_X_();
  7594. return e;</code>
  7595. </operation>
  7596. <!--${QXK::QXThread::init_}-->
  7597. <operation name="init_" type="void" visibility="0x01" properties="0x01">
  7598. <documentation>/*! Overrides QHsm_init_()
  7599. * @private @memberof QXThread
  7600. */
  7601. /*! @private @memberof QXThread */</documentation>
  7602. <!--${QXK::QXThread::init_::me}-->
  7603. <parameter name="me" type="QHsm * const"/>
  7604. <!--${QXK::QXThread::init_::par}-->
  7605. <parameter name="par" type="void const * const"/>
  7606. <!--${QXK::QXThread::init_::qs_id}-->
  7607. <parameter name="qs_id" type="uint_fast8_t const"/>
  7608. <code>Q_UNUSED_PAR(me);
  7609. Q_UNUSED_PAR(par);
  7610. Q_UNUSED_PAR(qs_id);
  7611. Q_ERROR_ID(110);</code>
  7612. </operation>
  7613. <!--${QXK::QXThread::dispatch_}-->
  7614. <operation name="dispatch_" type="void" visibility="0x01" properties="0x01">
  7615. <documentation>/*! Overrides QHsm_dispatch_()
  7616. * @private @memberof QXThread
  7617. */
  7618. /*! @private @memberof QXThread */</documentation>
  7619. <!--${QXK::QXThread::dispatch_::me}-->
  7620. <parameter name="me" type="QHsm * const"/>
  7621. <!--${QXK::QXThread::dispatch_::e}-->
  7622. <parameter name="e" type="QEvt const * const"/>
  7623. <!--${QXK::QXThread::dispatch_::qs_id}-->
  7624. <parameter name="qs_id" type="uint_fast8_t const"/>
  7625. <code>Q_UNUSED_PAR(me);
  7626. Q_UNUSED_PAR(e);
  7627. Q_UNUSED_PAR(qs_id);
  7628. Q_ERROR_ID(120);</code>
  7629. </operation>
  7630. <!--${QXK::QXThread::start_}-->
  7631. <operation name="start_" type="void" visibility="0x01" properties="0x01">
  7632. <documentation>/*! start QXThread private implementation
  7633. * @private @memberof QXThread
  7634. *
  7635. * @details
  7636. * Starts execution of an extended thread and registers it with the framework.
  7637. * The extended thread becomes ready-to-run immediately and is scheduled
  7638. * if the QXK is already running.
  7639. *
  7640. * @param[in,out] me current instance pointer (see @ref oop)
  7641. * @param[in] prio QF-priority of the thread, but no preemption-
  7642. * threshold. See also ::QPrioSpec.
  7643. * @param[in] qSto pointer to the storage for the ring buffer of the
  7644. * event queue. This cold be NULL, if this extended
  7645. * thread does not use the built-in event queue.
  7646. * @param[in] qLen length of the event queue [in events],
  7647. * or zero if queue not used
  7648. * @param[in] stkSto pointer to the stack storage (must be provided)
  7649. * @param[in] stkSize stack size [in bytes] (must not be zero)
  7650. * @param[in] par pointer to an extra parameter (might be NULL).
  7651. *
  7652. * @precondition{qxk_xthr,200}
  7653. * - must NOT be called from an ISR;
  7654. * - the stack storage must be provided;
  7655. * - the thread must be instantiated (see QXThread_ctor())
  7656. * - preemption-threshold is NOT provided (because QXK kernel
  7657. * does not support preemption-threshold scheduling)
  7658. *
  7659. * @note
  7660. * Currently, extended trheads in QXK do NOT support preemption-threshold.
  7661. * The `prio` must NOT provide preemption-threshold and this function
  7662. * will assert it in the precondition.
  7663. *
  7664. * @usage
  7665. * QXThread_start_() should NOT be called directly, only via the macro
  7666. * QXTHREAD_START(). The following example shows starting an extended
  7667. * thread:
  7668. * @include qxk_start.c
  7669. */
  7670. /*! @private @memberof QXThread */</documentation>
  7671. <!--${QXK::QXThread::start_::me}-->
  7672. <parameter name="me" type="QActive * const"/>
  7673. <!--${QXK::QXThread::start_::prioSpec}-->
  7674. <parameter name="prioSpec" type="QPrioSpec const"/>
  7675. <!--${QXK::QXThread::start_::qSto}-->
  7676. <parameter name="qSto" type="QEvt const * * const"/>
  7677. <!--${QXK::QXThread::start_::qLen}-->
  7678. <parameter name="qLen" type="uint_fast16_t const"/>
  7679. <!--${QXK::QXThread::start_::stkSto}-->
  7680. <parameter name="stkSto" type="void * const"/>
  7681. <!--${QXK::QXThread::start_::stkSize}-->
  7682. <parameter name="stkSize" type="uint_fast16_t const"/>
  7683. <!--${QXK::QXThread::start_::par}-->
  7684. <parameter name="par" type="void const * const"/>
  7685. <code>Q_UNUSED_PAR(par);
  7686. Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
  7687. &amp;&amp; (stkSto != (void *)0) /* stack must be provided */
  7688. &amp;&amp; (stkSize != 0U)
  7689. &amp;&amp; (me-&gt;super.state.act == (QActionHandler)0)
  7690. &amp;&amp; ((prioSpec &amp; 0xFF00U) == 0U));
  7691. /* is storage for the queue buffer provided? */
  7692. if (qSto != (QEvt const **)0) {
  7693. QEQueue_init(&amp;me-&gt;eQueue, qSto, qLen);
  7694. }
  7695. /* extended thread constructor puts the thread handler in place of
  7696. * the top-most initial transition 'me-&gt;super.temp.act'
  7697. */
  7698. QXK_stackInit_(me, me-&gt;super.temp.thr, stkSto, stkSize);
  7699. /* the new thread is not blocked on any object */
  7700. me-&gt;super.temp.obj = (QMState *)0;
  7701. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  7702. me-&gt;pthre = 0U; /* preemption-threshold NOT used */
  7703. QActive_register_(me); /* make QF aware of this active object */
  7704. QF_CRIT_STAT_
  7705. QF_CRIT_E_();
  7706. /* extended-thread becomes ready immediately */
  7707. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;prio);
  7708. /* see if this thread needs to be scheduled in case QXK is running */
  7709. if (QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE) {
  7710. (void)QXK_sched_(); /* schedule other threads */
  7711. }
  7712. QF_CRIT_X_();</code>
  7713. </operation>
  7714. <!--${QXK::QXThread::post_}-->
  7715. <operation name="post_" type="bool" visibility="0x01" properties="0x01">
  7716. <documentation>/*! post to the QXThread event queue private implementation
  7717. * @private @memberof QXThread
  7718. *
  7719. * @details
  7720. * Direct event posting is the simplest asynchronous communication method
  7721. * available in QF. The following example illustrates how the Philo active
  7722. * object posts directly the HUNGRY event to the Table active object.
  7723. * &lt;br&gt;
  7724. * The parameter `margin` specifies the minimum number of free slots in
  7725. * the queue that must be available for posting to succeed. The function
  7726. * returns 1 (success) if the posting succeeded (with the provided margin)
  7727. * and 0 (failure) when the posting fails.
  7728. *
  7729. * @param[in,out] me current instance pointer (see @ref oop)
  7730. * @param[in] e pointer to the event to be posted
  7731. * @param[in] margin number of required free slots in the queue after
  7732. * posting the event. The special value #QF_NO_MARGIN
  7733. * means that this function will assert if posting fails.
  7734. * @param[in] sender pointer to a sender object (used only for QS tracing).
  7735. *
  7736. * @returns
  7737. * 'true' (success) if the posting succeeded (with the provided margin) and
  7738. * 'false' (failure) when the posting fails.
  7739. *
  7740. * @note
  7741. * Should be called only via the macro QXTHREAD_POST_X().
  7742. *
  7743. * @note
  7744. * The #QF_NO_MARGIN value of the `margin` parameter is special and
  7745. * denotes situation when the post() operation is assumed to succeed
  7746. * (event delivery guarantee). An assertion fires, when the event cannot
  7747. * be delivered in this case.
  7748. *
  7749. * @note
  7750. * For compatibility with the V-table from the superclass ::QActive, the
  7751. * me-pointer is typed as pointing to QActive. However, the `me` pointer
  7752. * here actually points to the QXThread subclass. Therefore the downcast
  7753. * (QXThread *)me is always correct.
  7754. */
  7755. /*! @private @memberof QXThread */</documentation>
  7756. <!--${QXK::QXThread::post_::me}-->
  7757. <parameter name="me" type="QActive * const"/>
  7758. <!--${QXK::QXThread::post_::e}-->
  7759. <parameter name="e" type="QEvt const * const"/>
  7760. <!--${QXK::QXThread::post_::margin}-->
  7761. <parameter name="margin" type="uint_fast16_t const"/>
  7762. <!--${QXK::QXThread::post_::sender}-->
  7763. <parameter name="sender" type="void const * const"/>
  7764. <code>#ifndef Q_SPY
  7765. Q_UNUSED_PAR(sender);
  7766. #endif
  7767. QF_CRIT_STAT_
  7768. QS_TEST_PROBE_DEF(&amp;QXThread_post_)
  7769. /* is it the private time event? */
  7770. bool status;
  7771. if (e == &amp;QXTHREAD_CAST_(me)-&gt;timeEvt.super) {
  7772. QF_CRIT_E_();
  7773. /* the private time event is disarmed and not in any queue,
  7774. * so it is safe to change its signal. The signal of 0 means
  7775. * that the time event has expired.
  7776. */
  7777. QXTHREAD_CAST_(me)-&gt;timeEvt.super.sig = 0U;
  7778. QXThread_unblock_(QXTHREAD_CAST_(me));
  7779. QF_CRIT_X_();
  7780. status = true;
  7781. }
  7782. /* is the event queue provided? */
  7783. else if (me-&gt;eQueue.end != 0U) {
  7784. QEQueueCtr nFree;
  7785. /*! @pre event pointer must be valid */
  7786. Q_REQUIRE_ID(300, e != (QEvt *)0);
  7787. QF_CRIT_E_();
  7788. nFree = me-&gt;eQueue.nFree; /* get volatile into temporary */
  7789. /* test-probe#1 for faking queue overflow */
  7790. QS_TEST_PROBE_ID(1,
  7791. nFree = 0U;
  7792. )
  7793. if (margin == QF_NO_MARGIN) {
  7794. if (nFree &gt; 0U) {
  7795. status = true; /* can post */
  7796. }
  7797. else {
  7798. status = false; /* cannot post */
  7799. Q_ERROR_CRIT_(310); /* must be able to post the event */
  7800. }
  7801. }
  7802. else if (nFree &gt; (QEQueueCtr)margin) {
  7803. status = true; /* can post */
  7804. }
  7805. else {
  7806. status = false; /* cannot post, but don't assert */
  7807. }
  7808. /* is it a dynamic event? */
  7809. if (e-&gt;poolId_ != 0U) {
  7810. QEvt_refCtr_inc_(e); /* increment the reference counter */
  7811. }
  7812. if (status) { /* can post the event? */
  7813. --nFree; /* one free entry just used up */
  7814. me-&gt;eQueue.nFree = nFree; /* update the original */
  7815. if (me-&gt;eQueue.nMin &gt; nFree) {
  7816. me-&gt;eQueue.nMin = nFree; /* update minimum so far */
  7817. }
  7818. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST, me-&gt;prio)
  7819. QS_TIME_PRE_(); /* timestamp */
  7820. QS_OBJ_PRE_(sender); /* the sender object */
  7821. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  7822. QS_OBJ_PRE_(me); /* this active object (recipient) */
  7823. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  7824. QS_EQC_PRE_(nFree); /* number of free entries */
  7825. QS_EQC_PRE_(me-&gt;eQueue.nMin); /* min number of free entries */
  7826. QS_END_NOCRIT_PRE_()
  7827. /* queue empty? */
  7828. if (me-&gt;eQueue.frontEvt == (QEvt *)0) {
  7829. me-&gt;eQueue.frontEvt = e; /* deliver event directly */
  7830. /* is this thread blocked on the queue? */
  7831. if (me-&gt;super.temp.obj
  7832. == QXK_PTR_CAST_(QMState*, &amp;me-&gt;eQueue))
  7833. {
  7834. (void)QXThread_teDisarm_(QXTHREAD_CAST_(me));
  7835. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;prio);
  7836. if (!QXK_ISR_CONTEXT_()) {
  7837. (void)QXK_sched_(); /* schedule other threads */
  7838. }
  7839. }
  7840. }
  7841. /* queue is not empty, insert event into the ring-buffer */
  7842. else {
  7843. /* insert event into the ring buffer (FIFO) */
  7844. me-&gt;eQueue.ring[me-&gt;eQueue.head] = e;
  7845. /* need to wrap the head counter? */
  7846. if (me-&gt;eQueue.head == 0U) {
  7847. me-&gt;eQueue.head = me-&gt;eQueue.end; /* wrap around */
  7848. }
  7849. --me-&gt;eQueue.head; /* advance the head (counter clockwise) */
  7850. }
  7851. QF_CRIT_X_();
  7852. }
  7853. else { /* cannot post the event */
  7854. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, me-&gt;prio)
  7855. QS_TIME_PRE_(); /* timestamp */
  7856. QS_OBJ_PRE_(sender); /* the sender object */
  7857. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  7858. QS_OBJ_PRE_(me); /* this active object (recipient) */
  7859. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; ref Count */
  7860. QS_EQC_PRE_(nFree); /* number of free entries */
  7861. QS_EQC_PRE_(margin); /* margin requested */
  7862. QS_END_NOCRIT_PRE_()
  7863. QF_CRIT_X_();
  7864. #if (QF_MAX_EPOOL &gt; 0U)
  7865. QF_gc(e); /* recycle the event to avoid a leak */
  7866. #endif
  7867. }
  7868. }
  7869. else { /* the queue is not available */
  7870. #if (QF_MAX_EPOOL &gt; 0U)
  7871. QF_gc(e); /* make sure the event is not leaked */
  7872. #endif
  7873. status = false;
  7874. Q_ERROR_ID(320); /* this extended thread cannot accept events */
  7875. }
  7876. return status;</code>
  7877. </operation>
  7878. <!--${QXK::QXThread::postLIFO_}-->
  7879. <operation name="postLIFO_" type="void" visibility="0x01" properties="0x01">
  7880. <documentation>/*! post to the QXThread event queue (LIFO) private implementation
  7881. * @private @memberof QXThread
  7882. *
  7883. * @details
  7884. * Last-In-First-Out (LIFO) policy is not supported for extened threads.
  7885. *
  7886. * @param[in] me current instance pointer (see @ref oop)
  7887. * @param[in] e pointer to the event to post to the queue
  7888. *
  7889. * @sa
  7890. * QActive_postLIFO_()
  7891. */
  7892. /*! @private @memberof QXThread */</documentation>
  7893. <!--${QXK::QXThread::postLIFO_::me}-->
  7894. <parameter name="me" type="QActive * const"/>
  7895. <!--${QXK::QXThread::postLIFO_::e}-->
  7896. <parameter name="e" type="QEvt const * const"/>
  7897. <code>Q_UNUSED_PAR(me);
  7898. Q_UNUSED_PAR(e);
  7899. Q_ERROR_ID(410);</code>
  7900. </operation>
  7901. <!--${QXK::QXThread::block_}-->
  7902. <operation name="block_" type="void" visibility="0x02" properties="0x00">
  7903. <specifiers>const</specifiers>
  7904. <documentation>/*! block QXThread private implementation
  7905. * @private @memberof QXThread
  7906. *
  7907. * @details
  7908. * Internal implementation of blocking the given extended thread.
  7909. *
  7910. * @precondition{qxk_xthr,600}
  7911. * - the thread holding the lock cannot block!
  7912. *
  7913. * @note
  7914. * Must be called from within a critical section
  7915. */
  7916. /*! @private @memberof QXThread */</documentation>
  7917. <code>Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != me-&gt;super.prio));
  7918. QPSet_remove(&amp;QF_readySet_, (uint_fast8_t)me-&gt;super.prio);
  7919. (void)QXK_sched_(); /* schedule other threads */</code>
  7920. </operation>
  7921. <!--${QXK::QXThread::unblock_}-->
  7922. <operation name="unblock_" type="void" visibility="0x02" properties="0x00">
  7923. <specifiers>const</specifiers>
  7924. <documentation>/*! unblock QXThread private implementation
  7925. * @private @memberof QXThread
  7926. *
  7927. * @details
  7928. * Internal implementation of un-blocking the given extended thread.
  7929. *
  7930. * @note
  7931. * must be called from within a critical section
  7932. */
  7933. /*! @private @memberof QXThread */</documentation>
  7934. <code>QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;super.prio);
  7935. if ((!QXK_ISR_CONTEXT_()) /* not inside ISR? */
  7936. &amp;&amp; (QActive_registry_[0] != (QActive *)0)) /* kernel started? */
  7937. {
  7938. (void)QXK_sched_(); /* schedule other threads */
  7939. }</code>
  7940. </operation>
  7941. <!--${QXK::QXThread::teArm_}-->
  7942. <operation name="teArm_" type="void" visibility="0x02" properties="0x00">
  7943. <documentation>/*! arm internal time event private implementation
  7944. * @private @memberof QXThread
  7945. *
  7946. * @details
  7947. * Internal implementation of arming the private time event for a given
  7948. * timeout at a given system tick rate.
  7949. *
  7950. * @precondition{qxk_xthr,700}
  7951. * - the time event must be unused
  7952. *
  7953. * @note
  7954. * Must be called from within a critical section
  7955. */
  7956. /*! @private @memberof QXThread */</documentation>
  7957. <!--${QXK::QXThread::teArm_::sig}-->
  7958. <parameter name="sig" type="enum_t const"/>
  7959. <!--${QXK::QXThread::teArm_::nTicks}-->
  7960. <parameter name="nTicks" type="uint_fast16_t const"/>
  7961. <code>Q_REQUIRE_ID(700, me-&gt;timeEvt.ctr == 0U);
  7962. me-&gt;timeEvt.super.sig = (QSignal)sig;
  7963. if (nTicks != QXTHREAD_NO_TIMEOUT) {
  7964. me-&gt;timeEvt.ctr = (QTimeEvtCtr)nTicks;
  7965. me-&gt;timeEvt.interval = 0U;
  7966. /* is the time event unlinked?
  7967. * NOTE: For the duration of a single clock tick of the specified tick
  7968. * rate a time event can be disarmed and yet still linked in the list,
  7969. * because un-linking is performed exclusively in QTimeEvt_tick_().
  7970. */
  7971. if ((me-&gt;timeEvt.super.refCtr_ &amp; QTE_IS_LINKED) == 0U) {
  7972. uint_fast8_t const tickRate
  7973. = ((uint_fast8_t)me-&gt;timeEvt.super.refCtr_ &amp; QTE_TICK_RATE);
  7974. Q_ASSERT_ID(710, tickRate &lt; QF_MAX_TICK_RATE);
  7975. me-&gt;timeEvt.super.refCtr_ |= QTE_IS_LINKED;
  7976. /* The time event is initially inserted into the separate
  7977. * &quot;freshly armed&quot; list based on QTimeEvt_timeEvtHead_[tickRate].act.
  7978. * Only later, inside the QTimeEvt_tick_() function, the &quot;freshly
  7979. * armed&quot; list is appended to the main list of armed time events
  7980. * based on QTimeEvt_timeEvtHead_[tickRate].next. Again, this is
  7981. * to keep any changes to the main list exclusively inside
  7982. * QTimeEvt_tick_().
  7983. */
  7984. me-&gt;timeEvt.next
  7985. = QXK_PTR_CAST_(QTimeEvt*, QTimeEvt_timeEvtHead_[tickRate].act);
  7986. QTimeEvt_timeEvtHead_[tickRate].act = &amp;me-&gt;timeEvt;
  7987. }
  7988. }</code>
  7989. </operation>
  7990. <!--${QXK::QXThread::teDisarm_}-->
  7991. <operation name="teDisarm_" type="bool" visibility="0x02" properties="0x00">
  7992. <documentation>/*! disarm internal time event private implementation
  7993. * @private @memberof QXThread
  7994. *
  7995. * @details
  7996. * Internal implementation of disarming the private time event.
  7997. *
  7998. * @note
  7999. * Must be called from within a critical section
  8000. */
  8001. /*! @private @memberof QXThread */</documentation>
  8002. <code>bool wasArmed;
  8003. /* is the time evt running? */
  8004. if (me-&gt;timeEvt.ctr != 0U) {
  8005. wasArmed = true;
  8006. me-&gt;timeEvt.ctr = 0U; /* schedule removal from list */
  8007. }
  8008. /* the time event was already automatically disarmed */
  8009. else {
  8010. wasArmed = false;
  8011. }
  8012. return wasArmed;</code>
  8013. </operation>
  8014. </class>
  8015. <!--${QXK::QXThreadVtable}-->
  8016. <attribute name="QXThreadVtable" type="typedef QActiveVtable" visibility="0x04" properties="0x00">
  8017. <documentation>/*! @brief Virtual Table for the ::QXThread class
  8018. * (inherited from ::QActiveVtable)
  8019. *
  8020. * @note
  8021. * ::QXThread inherits ::QActive without adding any new virtual
  8022. * functions and therefore, ::QXThreadVtable is typedef'ed as ::QActiveVtable.
  8023. */</documentation>
  8024. </attribute>
  8025. <!--${QXK::QActive}-->
  8026. <class name="QActive">
  8027. <documentation>/*! QActive active object class customization for QK */</documentation>
  8028. <!--${QXK::QActive::start_}-->
  8029. <operation name="start_" type="void" visibility="0x00" properties="0x04">
  8030. <documentation>/*! Starts execution of an active object and registers the object
  8031. * with the framework customized for the QXK kernel
  8032. * @public @memberof QActive
  8033. *
  8034. * @precondition{qxk,300}
  8035. * - from an ISR;
  8036. * - the stack storage must NOT be provided (because the QXK kernel
  8037. * does not need per-AO stacks)
  8038. * - preemption-threshold is NOT provided (because QXK kernel
  8039. * does not support preemption-threshold scheduling)
  8040. */
  8041. /*! @public @memberof QActive */</documentation>
  8042. <!--${QXK::QActive::start_::prioSpec}-->
  8043. <parameter name="prioSpec" type="QPrioSpec const"/>
  8044. <!--${QXK::QActive::start_::qSto}-->
  8045. <parameter name="qSto" type="QEvt const * * const"/>
  8046. <!--${QXK::QActive::start_::qLen}-->
  8047. <parameter name="qLen" type="uint_fast16_t const"/>
  8048. <!--${QXK::QActive::start_::stkSto}-->
  8049. <parameter name="stkSto" type="void * const"/>
  8050. <!--${QXK::QActive::start_::stkSize}-->
  8051. <parameter name="stkSize" type="uint_fast16_t const"/>
  8052. <!--${QXK::QActive::start_::par}-->
  8053. <parameter name="par" type="void const * const"/>
  8054. <code>Q_UNUSED_PAR(stkSto); /* not needed in QXK */
  8055. Q_UNUSED_PAR(stkSize); /* not needed in QXK */
  8056. Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_())
  8057. &amp;&amp; (stkSto == (void *)0)
  8058. &amp;&amp; ((prioSpec &amp; 0xFF00U) == 0U));
  8059. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  8060. me-&gt;pthre = 0U; /* preemption-threshold NOT used */
  8061. QActive_register_(me); /* make QF aware of this active object */
  8062. QEQueue_init(&amp;me-&gt;eQueue, qSto, qLen); /* init the built-in queue */
  8063. me-&gt;osObject = (void *)0; /* no private stack for the AO */
  8064. QHSM_INIT(&amp;me-&gt;super, par, me-&gt;prio); /* top-most initial tran. */
  8065. QS_FLUSH(); /* flush the trace buffer to the host */
  8066. /* see if this AO needs to be scheduled if QXK is already running */
  8067. QF_CRIT_STAT_
  8068. QF_CRIT_E_();
  8069. if (QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE) { /* scheduler running? */
  8070. if (QXK_sched_() != 0U) { /* activation needed? */
  8071. QXK_activate_(); /* synchronously activate basic-thred(s) */
  8072. }
  8073. }
  8074. QF_CRIT_X_();</code>
  8075. </operation>
  8076. </class>
  8077. <!--${QXK::QXSemaphore}-->
  8078. <class name="QXSemaphore">
  8079. <documentation>/*! @brief Counting Semaphore of the QXK preemptive kernel
  8080. * @class QXSemaphore
  8081. *
  8082. * @details
  8083. * ::QXSemaphore is a blocking mechanism intended primarily for signaling
  8084. * @ref ::QXThread &quot;extended threads&quot;. The semaphore is initialized with
  8085. * the maximum count (see QXSemaphore_init()), which allows you to create
  8086. * a binary semaphore (when the maximum count is 1) and
  8087. * counting semaphore when the maximum count is &gt; 1.
  8088. *
  8089. * @usage
  8090. * The following example illustrates how to instantiate and use the semaphore
  8091. * in your application.
  8092. * @include qxk_sema.c
  8093. */</documentation>
  8094. <!--${QXK::QXSemaphore::waitSet}-->
  8095. <attribute name="waitSet" type="QPSet" visibility="0x02" properties="0x00">
  8096. <documentation>/*! set of extended threads waiting on this semaphore */</documentation>
  8097. </attribute>
  8098. <!--${QXK::QXSemaphore::count}-->
  8099. <attribute name="count" type="uint8_t volatile" visibility="0x02" properties="0x00">
  8100. <documentation>/*! semaphore up-down counter */</documentation>
  8101. </attribute>
  8102. <!--${QXK::QXSemaphore::max_count}-->
  8103. <attribute name="max_count" type="uint8_t" visibility="0x02" properties="0x00">
  8104. <documentation>/*! maximum value of the semaphore counter */</documentation>
  8105. </attribute>
  8106. <!--${QXK::QXSemaphore::init}-->
  8107. <operation name="init" type="void" visibility="0x00" properties="0x00">
  8108. <documentation>/*! initialize the counting semaphore
  8109. * @public @memberof QXSemaphore
  8110. *
  8111. * @details
  8112. * Initializes a semaphore with the specified count and maximum count.
  8113. * If the semaphore is used for resource sharing, both the initial count
  8114. * and maximum count should be set to the number of identical resources
  8115. * guarded by the semaphore. If the semaphore is used as a signaling
  8116. * mechanism, the initial count should set to 0 and maximum count to 1
  8117. * (binary semaphore).
  8118. *
  8119. * @param[in,out] me current instance pointer (see @ref oop)
  8120. * @param[in] count initial value of the semaphore counter
  8121. * @param[in] max_count maximum value of the semaphore counter.
  8122. * The purpose of the max_count is to limit the counter
  8123. * so that the semaphore cannot unblock more times than
  8124. * the maximum.
  8125. *
  8126. * @precondition{qxk_sema,100}
  8127. * - max_count must be greater than zero
  8128. *
  8129. * @note
  8130. * QXSemaphore_init() must be called **before** the semaphore can be used
  8131. * (signaled or waited on).
  8132. */
  8133. /*! @public @memberof QXSemaphore */</documentation>
  8134. <!--${QXK::QXSemaphore::init::count}-->
  8135. <parameter name="count" type="uint_fast8_t const"/>
  8136. <!--${QXK::QXSemaphore::init::max_count}-->
  8137. <parameter name="max_count" type="uint_fast8_t const"/>
  8138. <code>Q_REQUIRE_ID(100, max_count &gt; 0U);
  8139. me-&gt;count = (uint8_t)count;
  8140. me-&gt;max_count = (uint8_t)max_count;
  8141. QPSet_setEmpty(&amp;me-&gt;waitSet);</code>
  8142. </operation>
  8143. <!--${QXK::QXSemaphore::wait}-->
  8144. <operation name="wait" type="bool" visibility="0x00" properties="0x00">
  8145. <documentation>/*! wait (block) on the semaphore
  8146. * @public @memberof QXSemaphore
  8147. *
  8148. * @details
  8149. * When an extended thread calls QXSemaphore_wait() and the value of the
  8150. * semaphore counter is greater than 0, QXSemaphore_wait() decrements the
  8151. * semaphore counter and returns (true) to its caller. However, if the value
  8152. * of the semaphore counter is 0, the function places the calling thread in
  8153. * the waiting list for the semaphore. The thread waits until the semaphore
  8154. * is signaled by calling QXSemaphore_signal(), or the specified timeout
  8155. * expires. If the semaphore is signaled before the timeout expires, QXK
  8156. * resumes the highest-priority extended thread waiting for the semaphore.
  8157. *
  8158. * @param[in,out] me current instance pointer (see @ref oop)
  8159. * @param[in] nTicks number of clock ticks (at the associated rate)
  8160. * to wait for the semaphore. The value of
  8161. * ::QXTHREAD_NO_TIMEOUT indicates that no timeout will
  8162. * occur and the semaphore will wait indefinitely.
  8163. * @returns
  8164. * 'true' if the semaphore has been signaled and 'false' if a timeout
  8165. * occurred.
  8166. *
  8167. * @precondition{qxk_sema,200}
  8168. * - must NOT be called from an ISR;
  8169. * - the semaphore must be initialized
  8170. * - be called from an extended thread;
  8171. * - the thread must NOT be already blocked on any object.
  8172. *
  8173. * @precondition{qxk_sema,201}
  8174. * - the thread must NOT be holding a scheduler lock.
  8175. *
  8176. * @note
  8177. * Multiple extended threads can wait for a given semaphore.
  8178. */
  8179. /*! @public @memberof QXSemaphore */</documentation>
  8180. <!--${QXK::QXSemaphore::wait::nTicks}-->
  8181. <parameter name="nTicks" type="uint_fast16_t const"/>
  8182. <code>QF_CRIT_STAT_
  8183. QF_CRIT_E_();
  8184. QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_attr_.curr);
  8185. Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* can't wait inside an ISR */
  8186. &amp;&amp; (me-&gt;max_count &gt; 0U) /* sema must be initialized */
  8187. &amp;&amp; (curr != (QXThread *)0) /* curr must be extended */
  8188. &amp;&amp; (curr-&gt;super.super.temp.obj == (QMState *)0)); /* NOT blocked */
  8189. Q_REQUIRE_ID(201, QXK_attr_.lockHolder != curr-&gt;super.prio);
  8190. bool signaled = true; /* assume that the semaphore will be signaled */
  8191. if (me-&gt;count &gt; 0U) {
  8192. --me-&gt;count; /* semaphore taken: decrement the count */
  8193. QS_BEGIN_NOCRIT_PRE_(QS_SEM_TAKE, curr-&gt;super.prio)
  8194. QS_TIME_PRE_(); /* timestamp */
  8195. QS_OBJ_PRE_(me); /* this semaphore */
  8196. QS_2U8_PRE_(curr-&gt;super.prio,
  8197. me-&gt;count);
  8198. QS_END_NOCRIT_PRE_()
  8199. }
  8200. else {
  8201. uint_fast8_t const p = (uint_fast8_t)curr-&gt;super.prio;
  8202. /* remove the curr prio from the ready set (will block)
  8203. * and insert to the waiting set on this semaphore
  8204. */
  8205. QPSet_remove(&amp;QF_readySet_, p);
  8206. QPSet_insert(&amp;me-&gt;waitSet, p);
  8207. /* remember the blocking object (this semaphore) */
  8208. curr-&gt;super.super.temp.obj = QXK_PTR_CAST_(QMState*, me);
  8209. QXThread_teArm_(curr, (enum_t)QXK_TIMEOUT_SIG, nTicks);
  8210. QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK, curr-&gt;super.prio)
  8211. QS_TIME_PRE_(); /* timestamp */
  8212. QS_OBJ_PRE_(me); /* this semaphore */
  8213. QS_2U8_PRE_(curr-&gt;super.prio,
  8214. me-&gt;count);
  8215. QS_END_NOCRIT_PRE_()
  8216. /* schedule the next thread if multitasking started */
  8217. (void)QXK_sched_(); /* schedule other theads */
  8218. QF_CRIT_X_();
  8219. QF_CRIT_EXIT_NOP(); /* BLOCK here !!! */
  8220. QF_CRIT_E_(); /* AFTER unblocking... */
  8221. /* the blocking object must be this semaphore */
  8222. Q_ASSERT_ID(240, curr-&gt;super.super.temp.obj
  8223. == QXK_PTR_CAST_(QMState*, me));
  8224. /* did the blocking time-out? (signal of zero means that it did) */
  8225. if (curr-&gt;timeEvt.super.sig == 0U) {
  8226. if (QPSet_hasElement(&amp;me-&gt;waitSet, p)) { /* still waiting? */
  8227. QPSet_remove(&amp;me-&gt;waitSet, p); /* remove unblocked thread */
  8228. signaled = false; /* the semaphore was NOT signaled */
  8229. /* semaphore NOT taken: do NOT decrement the count */
  8230. }
  8231. else { /* semaphore was both signaled and timed out */
  8232. --me-&gt;count; /* semaphore taken: decrement the count */
  8233. }
  8234. }
  8235. else { /* blocking did NOT time out */
  8236. /* the thread must NOT be waiting on this semaphore */
  8237. Q_ASSERT_ID(250,!QPSet_hasElement(&amp;me-&gt;waitSet, p));
  8238. --me-&gt;count; /* semaphore taken: decrement the count */
  8239. }
  8240. curr-&gt;super.super.temp.obj = (QMState *)0; /* clear blocking obj. */
  8241. }
  8242. QF_CRIT_X_();
  8243. return signaled;</code>
  8244. </operation>
  8245. <!--${QXK::QXSemaphore::tryWait}-->
  8246. <operation name="tryWait" type="bool" visibility="0x00" properties="0x00">
  8247. <documentation>/*! try wait on the semaphore (non-blocking)
  8248. * @public @memberof QXSemaphore
  8249. *
  8250. * @details
  8251. * This function checks if the semaphore counter is greater than 0,
  8252. * in which case the counter is decremented.
  8253. *
  8254. * @param[in,out] me current instance pointer (see @ref oop)
  8255. *
  8256. * @returns
  8257. * 'true' if the semaphore has count available and 'false' NOT available.
  8258. *
  8259. * @precondition{qxk_sema,300}
  8260. * - the semaphore must be initialized
  8261. *
  8262. * @note
  8263. * This function can be called from any context, including ISRs and basic
  8264. * threads (active objects).
  8265. */
  8266. /*! @public @memberof QXSemaphore */</documentation>
  8267. <code>QF_CRIT_STAT_
  8268. QF_CRIT_E_();
  8269. Q_REQUIRE_ID(300, me-&gt;max_count &gt; 0U);
  8270. #ifdef Q_SPY
  8271. QActive const * const curr = QXK_PTR_CAST_(QActive*, QXK_attr_.curr);
  8272. #endif /* Q_SPY */
  8273. bool isAvailable;
  8274. /* is the semaphore available? */
  8275. if (me-&gt;count &gt; 0U) {
  8276. --me-&gt;count;
  8277. isAvailable = true;
  8278. QS_BEGIN_NOCRIT_PRE_(QS_SEM_TAKE, curr-&gt;prio)
  8279. QS_TIME_PRE_(); /* timestamp */
  8280. QS_OBJ_PRE_(me); /* this semaphore */
  8281. QS_2U8_PRE_(curr-&gt;prio,
  8282. me-&gt;count);
  8283. QS_END_NOCRIT_PRE_()
  8284. }
  8285. else { /* the semaphore is NOT available (would block) */
  8286. isAvailable = false;
  8287. QS_BEGIN_NOCRIT_PRE_(QS_SEM_BLOCK_ATTEMPT, curr-&gt;prio)
  8288. QS_TIME_PRE_(); /* timestamp */
  8289. QS_OBJ_PRE_(me); /* this semaphore */
  8290. QS_2U8_PRE_(curr-&gt;prio,
  8291. me-&gt;count);
  8292. QS_END_NOCRIT_PRE_()
  8293. }
  8294. QF_CRIT_X_();
  8295. return isAvailable;</code>
  8296. </operation>
  8297. <!--${QXK::QXSemaphore::signal}-->
  8298. <operation name="signal" type="bool" visibility="0x00" properties="0x00">
  8299. <documentation>/*! signal (unblock) the semaphore
  8300. * @public @memberof QXSemaphore
  8301. *
  8302. * @details
  8303. * If the semaphore counter value is 0 or more, it is incremented, and
  8304. * this function returns to its caller. If the extended threads are waiting
  8305. * for the semaphore to be signaled, QXSemaphore_signal() removes the highest-
  8306. * priority thread waiting for the semaphore from the waiting list and makes
  8307. * this thread ready-to-run. The QXK scheduler is then called to determine if
  8308. * the awakened thread is now the highest-priority thread that is ready-to-run.
  8309. *
  8310. * @param[in,out] me current instance pointer (see @ref oop)
  8311. *
  8312. * @returns
  8313. * 'true' when the semaphore signaled and 'false' when the semaphore count
  8314. * exceeded the maximum.
  8315. *
  8316. * @precondition{qxk_sema,400}
  8317. * - the semaphore must be initialized
  8318. *
  8319. * @note
  8320. * A semaphore can be signaled from many places, including from ISRs, basic
  8321. * threads (AOs), and extended threads.
  8322. */
  8323. /*! @public @memberof QXSemaphore */</documentation>
  8324. <code>Q_REQUIRE_ID(400, me-&gt;max_count &gt; 0U);
  8325. QF_CRIT_STAT_
  8326. QF_CRIT_E_();
  8327. bool signaled = true; /* assume that the semaphore will be signaled */
  8328. if (me-&gt;count &lt; me-&gt;max_count) {
  8329. ++me-&gt;count; /* increment the semaphore count */
  8330. #ifdef Q_SPY
  8331. QActive const * const curr = QXK_PTR_CAST_(QActive*, QXK_attr_.curr);
  8332. #endif /* Q_SPY */
  8333. QS_BEGIN_NOCRIT_PRE_(QS_SEM_SIGNAL, curr-&gt;prio)
  8334. QS_TIME_PRE_(); /* timestamp */
  8335. QS_OBJ_PRE_(me); /* this semaphore */
  8336. QS_2U8_PRE_(curr-&gt;prio,
  8337. me-&gt;count);
  8338. QS_END_NOCRIT_PRE_()
  8339. if (QPSet_notEmpty(&amp;me-&gt;waitSet)) {
  8340. /* find the highest-priority thread waiting on this semaphore */
  8341. uint_fast8_t const p = QPSet_findMax(&amp;me-&gt;waitSet);
  8342. QXThread * const thr =
  8343. QXK_PTR_CAST_(QXThread*, QActive_registry_[p]);
  8344. /* assert that the tread:
  8345. * - must be registered in QF;
  8346. * - must be extended; and
  8347. * - must be blocked on this semaphore;
  8348. */
  8349. Q_ASSERT_ID(410, (thr != (QXThread *)0)
  8350. &amp;&amp; (thr-&gt;super.osObject != (struct QActive *)0)
  8351. &amp;&amp; (thr-&gt;super.super.temp.obj
  8352. == QXK_PTR_CAST_(QMState*, me)));
  8353. /* disarm the internal time event */
  8354. (void)QXThread_teDisarm_(thr);
  8355. /* make the thread ready to run and remove from the wait-list */
  8356. QPSet_insert(&amp;QF_readySet_, p);
  8357. QPSet_remove(&amp;me-&gt;waitSet, p);
  8358. QS_BEGIN_NOCRIT_PRE_(QS_SEM_TAKE, thr-&gt;super.prio)
  8359. QS_TIME_PRE_(); /* timestamp */
  8360. QS_OBJ_PRE_(me); /* this semaphore */
  8361. QS_2U8_PRE_(thr-&gt;super.prio,
  8362. me-&gt;count);
  8363. QS_END_NOCRIT_PRE_()
  8364. if (!QXK_ISR_CONTEXT_()) { /* not inside ISR? */
  8365. (void)QXK_sched_(); /* schedule other threads */
  8366. }
  8367. }
  8368. }
  8369. else {
  8370. signaled = false; /* semaphore NOT signaled */
  8371. }
  8372. QF_CRIT_X_();
  8373. return signaled;</code>
  8374. </operation>
  8375. </class>
  8376. <!--${QXK::QXMutex}-->
  8377. <class name="QXMutex">
  8378. <documentation>/*! @brief Blocking Mutex the QXK preemptive kernel
  8379. * @class QXMutex
  8380. *
  8381. * @details
  8382. * ::QXMutex is a blocking mutual exclusion mechanism that can also apply
  8383. * the **priority-ceiling protocol** to avoid unbounded priority inversion
  8384. * (if initialized with a non-zero ceiling priority, see QXMutex_init()).
  8385. * In that case, ::QXMutex requires its own uinque QP priority level, which
  8386. * cannot be used by any thread or any other ::QXMutex.
  8387. * If initialized with preemption-ceiling of zero, ::QXMutex does **not**
  8388. * use the priority-ceiling protocol and does not require a unique QP
  8389. * priority (see QXMutex_init()).
  8390. * ::QXMutex is **recursive** (re-entrant), which means that it can be locked
  8391. * multiple times (up to 255 levels) by the *same* thread without causing
  8392. * deadlock.
  8393. * ::QXMutex is primarily intended for the @ref ::QXThread
  8394. * &quot;extened (blocking) threads&quot;, but can also be used by the @ref ::QActive
  8395. * &quot;basic threads&quot; through the non-blocking QXMutex_tryLock() API.
  8396. *
  8397. * @note
  8398. * ::QXMutex should be used in situations when at least one of the extended
  8399. * threads contending for the mutex blocks while holding the mutex (between
  8400. * the QXMutex_lock() and QXMutex_unlock() operations). If no blocking is
  8401. * needed while holding the mutex, the more efficient non-blocking mechanism
  8402. * of @ref srs_qxk_schedLock() &quot;selective QXK scheduler locking&quot; should be used
  8403. * instead. @ref srs_qxk_schedLock() &quot;Selective scheduler locking&quot; is available
  8404. * for both @ref ::QActive &quot;basic threads&quot; and @ref ::QXThread &quot;extended
  8405. * threads&quot;, so it is applicable to situations where resources are shared
  8406. * among all these threads.
  8407. *
  8408. * @usage
  8409. * The following example illustrates how to instantiate and use the mutex
  8410. * in your application.
  8411. * @include qxk_mutex.c
  8412. */</documentation>
  8413. <!--${QXK::QXMutex::ao}-->
  8414. <attribute name="ao" type="QActive" visibility="0x02" properties="0x00">
  8415. <documentation>/*! active object used as a placeholder AO for this mutex
  8416. * in QActive_registry_[]
  8417. */</documentation>
  8418. </attribute>
  8419. <!--${QXK::QXMutex::waitSet}-->
  8420. <attribute name="waitSet" type="QPSet" visibility="0x02" properties="0x00">
  8421. <documentation>/*! set of extended-threads waiting on this mutex */</documentation>
  8422. </attribute>
  8423. <!--${QXK::QXMutex::init}-->
  8424. <operation name="init" type="void" visibility="0x00" properties="0x00">
  8425. <documentation>/*! initialize the QXK priority-ceiling mutex ::QXMutex
  8426. * @public @memberof QXMutex
  8427. *
  8428. * @details
  8429. * Initialize the QXK priority ceiling mutex.
  8430. *
  8431. * @param[in,out] me current instance pointer (see @ref oop)
  8432. * @param[in] prioSpec the priority specification for the mutex
  8433. * (See also ::QPrioSpec). This value might
  8434. * also be zero.
  8435. *
  8436. * @precondition{qxk_mutex,100}
  8437. * - preemption-threshold must not be used
  8438. *
  8439. * @note
  8440. * `prioSpec == 0` means that the priority-ceiling protocol shall **not**
  8441. * be used by this mutex. Such mutex will **not** change (boost) the
  8442. * priority of the holding threads.&lt;br&gt;
  8443. *
  8444. * Conversely, `prioSpec != 0` means that the priority-ceiling protocol
  8445. * shall be used by this mutex. Such mutex **will** temporarily boost
  8446. * the priority and priority-threshold of the holding thread to the
  8447. * priority specification in `prioSpec` (see ::QPrioSpec).
  8448. *
  8449. * @usage
  8450. * @include qxk_mutex.c
  8451. */
  8452. /*! @public @memberof QXMutex */</documentation>
  8453. <!--${QXK::QXMutex::init::prioSpec}-->
  8454. <parameter name="prioSpec" type="QPrioSpec const"/>
  8455. <code>Q_REQUIRE_ID(100, (prioSpec &amp; 0xFF00U) == 0U);
  8456. me-&gt;ao.prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority */
  8457. me-&gt;ao.pthre = 0U; /* preemption-threshold (not used) */
  8458. if (prioSpec != 0U) { /* priority-ceiling protocol used? */
  8459. QActive_register_(&amp;me-&gt;ao); /* register this mutex as AO */
  8460. }</code>
  8461. </operation>
  8462. <!--${QXK::QXMutex::lock}-->
  8463. <operation name="lock" type="bool" visibility="0x00" properties="0x00">
  8464. <documentation>/*! lock the QXK priority-ceiling mutex ::QXMutex
  8465. * @public @memberof QXMutex
  8466. *
  8467. * @param[in,out] me current instance pointer (see @ref oop)
  8468. * @param[in] nTicks number of clock ticks (at the associated rate)
  8469. * to wait for the mutex. The value of
  8470. * ::QXTHREAD_NO_TIMEOUT indicates that no timeout will
  8471. * occur and the mutex could block indefinitely.
  8472. * @returns
  8473. * 'true' if the mutex has been acquired and 'false' if a timeout occurred.
  8474. *
  8475. * @precondition{qxk_mutex,200}
  8476. * - must NOT be called from an ISR;
  8477. * - must be called from an extended thread;
  8478. * - the mutex-priority must be in range;
  8479. * - the thread must NOT be already blocked on any object.
  8480. *
  8481. * @note
  8482. * The mutex locks are allowed to nest, meaning that the same extended thread
  8483. * can lock the same mutex multiple times (&lt; 255). However, each call to
  8484. * QXMutex_lock() must be balanced by the matching call to QXMutex_unlock().
  8485. *
  8486. * @usage
  8487. * @include qxk_mutex.c
  8488. */
  8489. /*! @public @memberof QXMutex */</documentation>
  8490. <!--${QXK::QXMutex::lock::nTicks}-->
  8491. <parameter name="nTicks" type="uint_fast16_t const"/>
  8492. <code>QF_CRIT_STAT_
  8493. QF_CRIT_E_();
  8494. QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_attr_.curr);
  8495. Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
  8496. &amp;&amp; (curr != (QXThread *)0) /* current thread must be extended */
  8497. &amp;&amp; (me-&gt;ao.prio &lt;= QF_MAX_ACTIVE)
  8498. &amp;&amp; (curr-&gt;super.super.temp.obj == (QMState *)0)); /* not blocked */
  8499. /*! @pre also: the thread must NOT be holding a scheduler lock. */
  8500. Q_REQUIRE_ID(201, QXK_attr_.lockHolder != curr-&gt;super.prio);
  8501. /* is the mutex available? */
  8502. bool locked = true; /* assume that the mutex will be locked */
  8503. if (me-&gt;ao.eQueue.nFree == 0U) {
  8504. me-&gt;ao.eQueue.nFree = 1U; /* mutex lock nesting */
  8505. /*! @pre also: the newly locked mutex must have no holder yet */
  8506. Q_REQUIRE_ID(202, me-&gt;ao.thread == (void *)0);
  8507. /* set the new mutex holder to the curr thread and
  8508. * save the thread's prio in the mutex
  8509. * NOTE: reuse the otherwise unused eQueue data member.
  8510. */
  8511. me-&gt;ao.thread = curr;
  8512. me-&gt;ao.eQueue.head = (QEQueueCtr)curr-&gt;super.prio;
  8513. QS_BEGIN_NOCRIT_PRE_(QS_MTX_LOCK, curr-&gt;super.prio)
  8514. QS_TIME_PRE_(); /* timestamp */
  8515. QS_OBJ_PRE_(me); /* this mutex */
  8516. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8517. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8518. QS_END_NOCRIT_PRE_()
  8519. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8520. /* the holder priority must be lower than that of the mutex
  8521. * and the priority slot must be occupied by this mutex
  8522. */
  8523. Q_ASSERT_ID(210, (curr-&gt;super.prio &lt; me-&gt;ao.prio)
  8524. &amp;&amp; (QActive_registry_[me-&gt;ao.prio] == &amp;me-&gt;ao));
  8525. /* remove the thread's original prio from the ready set
  8526. * and insert the mutex's prio into the ready set
  8527. */
  8528. QPSet_remove(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.eQueue.head);
  8529. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.prio);
  8530. /* put the thread into the AO registry in place of the mutex */
  8531. QActive_registry_[me-&gt;ao.prio] = &amp;curr-&gt;super;
  8532. /* set thread's prio to that of the mutex */
  8533. curr-&gt;super.prio = me-&gt;ao.prio;
  8534. }
  8535. }
  8536. /* is the mutex locked by this thread already (nested locking)? */
  8537. else if (me-&gt;ao.thread == &amp;curr-&gt;super) {
  8538. /* the nesting level beyond the arbitrary but high limit
  8539. * most likely means cyclic or recursive locking of a mutex.
  8540. */
  8541. Q_ASSERT_ID(220, me-&gt;ao.eQueue.nFree &lt; 0xFFU);
  8542. ++me-&gt;ao.eQueue.nFree; /* lock one more level */
  8543. QS_BEGIN_NOCRIT_PRE_(QS_MTX_LOCK, curr-&gt;super.prio)
  8544. QS_TIME_PRE_(); /* timestamp */
  8545. QS_OBJ_PRE_(me); /* this mutex */
  8546. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8547. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8548. QS_END_NOCRIT_PRE_()
  8549. }
  8550. else { /* the mutex is already locked by a different thread */
  8551. /* the mutex holder must be valid */
  8552. Q_ASSERT_ID(230, me-&gt;ao.thread != (void *)0);
  8553. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8554. /* the prio slot must be occupied by the thr. holding the mutex */
  8555. Q_ASSERT_ID(240, QActive_registry_[me-&gt;ao.prio]
  8556. == QXK_PTR_CAST_(QActive *, me-&gt;ao.thread));
  8557. }
  8558. /* remove the curr thread's prio from the ready set (will block)
  8559. * and insert it to the waiting set on this mutex
  8560. */
  8561. uint_fast8_t const p = (uint_fast8_t)curr-&gt;super.prio;
  8562. QPSet_remove(&amp;QF_readySet_, p);
  8563. QPSet_insert(&amp;me-&gt;waitSet, p);
  8564. /* set the blocking object (this mutex) */
  8565. curr-&gt;super.super.temp.obj = QXK_PTR_CAST_(QMState*, me);
  8566. QXThread_teArm_(curr, (enum_t)QXK_TIMEOUT_SIG, nTicks);
  8567. QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK, curr-&gt;super.prio)
  8568. QS_TIME_PRE_(); /* timestamp */
  8569. QS_OBJ_PRE_(me); /* this mutex */
  8570. QS_2U8_PRE_((uint8_t)me-&gt;ao.eQueue.head, /* holder prio */
  8571. curr-&gt;super.prio); /* blocked thread prio */
  8572. QS_END_NOCRIT_PRE_()
  8573. /* schedule the next thread if multitasking started */
  8574. (void)QXK_sched_(); /* schedule other threads */
  8575. QF_CRIT_X_();
  8576. QF_CRIT_EXIT_NOP(); /* BLOCK here !!! */
  8577. /* AFTER unblocking... */
  8578. QF_CRIT_E_();
  8579. /* the blocking object must be this mutex */
  8580. Q_ASSERT_ID(240, curr-&gt;super.super.temp.obj
  8581. == QXK_PTR_CAST_(QMState*, me));
  8582. /* did the blocking time-out? (signal of zero means that it did) */
  8583. if (curr-&gt;timeEvt.super.sig == 0U) {
  8584. if (QPSet_hasElement(&amp;me-&gt;waitSet, p)) { /* still waiting? */
  8585. QPSet_remove(&amp;me-&gt;waitSet, p); /* remove unblocked thread */
  8586. locked = false; /* the mutex was NOT locked */
  8587. }
  8588. }
  8589. else { /* blocking did NOT time out */
  8590. /* the thread must NOT be waiting on this mutex */
  8591. Q_ASSERT_ID(250, !QPSet_hasElement(&amp;me-&gt;waitSet, p));
  8592. }
  8593. curr-&gt;super.super.temp.obj = (QMState *)0; /* clear blocking obj. */
  8594. }
  8595. QF_CRIT_X_();
  8596. return locked;</code>
  8597. </operation>
  8598. <!--${QXK::QXMutex::tryLock}-->
  8599. <operation name="tryLock" type="bool" visibility="0x00" properties="0x00">
  8600. <documentation>/*! try to lock the QXK priority-ceiling mutex ::QXMutex
  8601. * @public @memberof QXMutex
  8602. *
  8603. * @param[in,out] me current instance pointer (see @ref oop)
  8604. *
  8605. * @returns
  8606. * 'true' if the mutex was successfully locked and 'false' if the mutex was
  8607. * unavailable and was NOT locked.
  8608. *
  8609. * @precondition{qxk_mutex,300}
  8610. * - must NOT be called from an ISR;
  8611. * - the calling thread must be valid;
  8612. * - the mutex-priority must be in range
  8613. *
  8614. * @precondition{qxk_mutex,301}
  8615. * - the thread must NOT be holding a scheduler lock.
  8616. *
  8617. * @note
  8618. * This function **can** be called from both basic threads (active objects)
  8619. * and extended threads.
  8620. *
  8621. * @note
  8622. * The mutex locks are allowed to nest, meaning that the same extended thread
  8623. * can lock the same mutex multiple times (&lt;= 255). However, each successful
  8624. * call to QXMutex_tryLock() must be balanced by the matching call to
  8625. * QXMutex_unlock().
  8626. */
  8627. /*! @public @memberof QXMutex */</documentation>
  8628. <code>QF_CRIT_STAT_
  8629. QF_CRIT_E_();
  8630. QActive *curr = QXK_attr_.curr;
  8631. if (curr == (QActive *)0) { /* called from a basic thread? */
  8632. curr = QActive_registry_[QXK_attr_.actPrio];
  8633. }
  8634. Q_REQUIRE_ID(300, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
  8635. &amp;&amp; (curr != (QActive *)0) /* current thread must be valid */
  8636. &amp;&amp; (me-&gt;ao.prio &lt;= QF_MAX_ACTIVE));
  8637. Q_REQUIRE_ID(301, QXK_attr_.lockHolder != curr-&gt;prio);
  8638. /* is the mutex available? */
  8639. if (me-&gt;ao.eQueue.nFree == 0U) {
  8640. me-&gt;ao.eQueue.nFree = 1U; /* mutex lock nesting */
  8641. /*! @pre also: the newly locked mutex must have no holder yet */
  8642. Q_REQUIRE_ID(302, me-&gt;ao.thread == (void *)0);
  8643. /* set the new mutex holder to the curr thread and
  8644. * save the thread's prio in the mutex
  8645. * NOTE: reuse the otherwise unused eQueue data member.
  8646. */
  8647. me-&gt;ao.thread = curr;
  8648. me-&gt;ao.eQueue.head = (QEQueueCtr)curr-&gt;prio;
  8649. QS_BEGIN_NOCRIT_PRE_(QS_MTX_LOCK, curr-&gt;prio)
  8650. QS_TIME_PRE_(); /* timestamp */
  8651. QS_OBJ_PRE_(me); /* this mutex */
  8652. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8653. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8654. QS_END_NOCRIT_PRE_()
  8655. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8656. /* the holder priority must be lower than that of the mutex
  8657. * and the priority slot must be occupied by this mutex
  8658. */
  8659. Q_ASSERT_ID(210, (curr-&gt;prio &lt; me-&gt;ao.prio)
  8660. &amp;&amp; (QActive_registry_[me-&gt;ao.prio] == &amp;me-&gt;ao));
  8661. /* remove the thread's original prio from the ready set
  8662. * and insert the mutex's prio into the ready set
  8663. */
  8664. QPSet_remove(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.eQueue.head);
  8665. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.prio);
  8666. /* put the thread into the AO registry in place of the mutex */
  8667. QActive_registry_[me-&gt;ao.prio] = curr;
  8668. /* set thread's prio to that of the mutex */
  8669. curr-&gt;prio = me-&gt;ao.prio;
  8670. }
  8671. }
  8672. /* is the mutex locked by this thread already (nested locking)? */
  8673. else if (me-&gt;ao.thread == curr) {
  8674. /* the nesting level must not exceed the specified limit */
  8675. Q_ASSERT_ID(320, me-&gt;ao.eQueue.nFree &lt; 0xFFU);
  8676. ++me-&gt;ao.eQueue.nFree; /* lock one more level */
  8677. QS_BEGIN_NOCRIT_PRE_(QS_MTX_LOCK, curr-&gt;prio)
  8678. QS_TIME_PRE_(); /* timestamp */
  8679. QS_OBJ_PRE_(me); /* this mutex */
  8680. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8681. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8682. QS_END_NOCRIT_PRE_()
  8683. }
  8684. else { /* the mutex is already locked by a different thread */
  8685. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8686. /* the prio slot must be occupied by the thr. holding the mutex */
  8687. Q_ASSERT_ID(340, QActive_registry_[me-&gt;ao.prio]
  8688. == QXK_PTR_CAST_(QActive *, me-&gt;ao.thread));
  8689. }
  8690. QS_BEGIN_NOCRIT_PRE_(QS_MTX_BLOCK_ATTEMPT, curr-&gt;prio)
  8691. QS_TIME_PRE_(); /* timestamp */
  8692. QS_OBJ_PRE_(me); /* this mutex */
  8693. QS_2U8_PRE_((uint8_t)me-&gt;ao.eQueue.head, /* holder prio */
  8694. curr-&gt;prio); /* trying thread prio */
  8695. QS_END_NOCRIT_PRE_()
  8696. curr = (QActive *)0; /* means that mutex is NOT available */
  8697. }
  8698. QF_CRIT_X_();
  8699. return curr != (QActive *)0;</code>
  8700. </operation>
  8701. <!--${QXK::QXMutex::unlock}-->
  8702. <operation name="unlock" type="void" visibility="0x00" properties="0x00">
  8703. <documentation>/*! unlock the QXK priority-ceiling mutex ::QXMutex
  8704. * @public @memberof QXMutex
  8705. *
  8706. * @param[in,out] me current instance pointer (see @ref oop)
  8707. *
  8708. * @precondition{qxk_mutex,400}
  8709. * - must NOT be called from an ISR;
  8710. * - the calling thread must be valid;
  8711. *
  8712. * @precondition{qxk_mutex,401}
  8713. * - the mutex must be already locked at least once.
  8714. *
  8715. * @precondition{qxk_mutex,402}
  8716. * - the mutex must be held by this thread.
  8717. *
  8718. * @note
  8719. * This function **can** be called from both basic threads (active objects)
  8720. * and extended threads.
  8721. *
  8722. * @note
  8723. * The mutex locks are allowed to nest, meaning that the same extended thread
  8724. * can lock the same mutex multiple times (&lt;= 225). However, each call to
  8725. * QXMutex_lock() or a *successful* call to QXMutex_tryLock() must be
  8726. * balanced by the matching call to QXMutex_unlock().
  8727. *
  8728. * @usage
  8729. * @include qxk_mutex.c
  8730. */
  8731. /*! @public @memberof QXMutex */</documentation>
  8732. <code>QF_CRIT_STAT_
  8733. QF_CRIT_E_();
  8734. QActive *curr = QXK_attr_.curr;
  8735. if (curr == (QActive *)0) { /* called from a basic thread? */
  8736. curr = QActive_registry_[QXK_attr_.actPrio];
  8737. }
  8738. Q_REQUIRE_ID(400, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
  8739. &amp;&amp; (curr != (QActive *)0)); /* current thread must be valid */
  8740. Q_REQUIRE_ID(401, me-&gt;ao.eQueue.nFree &gt; 0U);
  8741. Q_REQUIRE_ID(402, me-&gt;ao.thread == curr);
  8742. /* is this the last nesting level? */
  8743. if (me-&gt;ao.eQueue.nFree == 1U) {
  8744. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8745. /* restore the holding thread's prio from the mutex */
  8746. curr-&gt;prio = (uint8_t)me-&gt;ao.eQueue.head;
  8747. /* put the mutex back into the AO registry */
  8748. QActive_registry_[me-&gt;ao.prio] = &amp;me-&gt;ao;
  8749. /* remove the mutex' prio from the ready set
  8750. * and insert the original thread's priority
  8751. */
  8752. QPSet_remove(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.prio);
  8753. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)me-&gt;ao.eQueue.head);
  8754. }
  8755. QS_BEGIN_NOCRIT_PRE_(QS_MTX_UNLOCK, curr-&gt;prio)
  8756. QS_TIME_PRE_(); /* timestamp */
  8757. QS_OBJ_PRE_(me); /* this mutex */
  8758. QS_2U8_PRE_((uint8_t)me-&gt;ao.eQueue.head, /* holder prio */
  8759. 0U); /* nesting */
  8760. QS_END_NOCRIT_PRE_()
  8761. /* are any other threads waiting on this mutex? */
  8762. if (QPSet_notEmpty(&amp;me-&gt;waitSet)) {
  8763. /* find the highest-priority thread waiting on this mutex */
  8764. uint_fast8_t const p = QPSet_findMax(&amp;me-&gt;waitSet);
  8765. /* remove this thread from waiting on the mutex
  8766. * and insert it into the ready set.
  8767. */
  8768. QPSet_remove(&amp;me-&gt;waitSet, p);
  8769. QPSet_insert(&amp;QF_readySet_, p);
  8770. QXThread * const thr =
  8771. QXK_PTR_CAST_(QXThread*, QActive_registry_[p]);
  8772. /* the waiting thread must:
  8773. * - be registered in QF
  8774. * - have the priority corresponding to the registration
  8775. * - be an extended thread
  8776. * - be blocked on this mutex
  8777. */
  8778. Q_ASSERT_ID(410, (thr != (QXThread *)0)
  8779. &amp;&amp; (thr-&gt;super.prio == (uint8_t)p)
  8780. &amp;&amp; (thr-&gt;super.super.state.act == Q_ACTION_CAST(0))
  8781. &amp;&amp; (thr-&gt;super.super.temp.obj
  8782. == QXK_PTR_CAST_(QMState*, me)));
  8783. /* disarm the internal time event */
  8784. (void)QXThread_teDisarm_(thr);
  8785. /* set the new mutex holder to the curr thread and
  8786. * save the thread's prio in the mutex
  8787. * NOTE: reuse the otherwise unused eQueue data member.
  8788. */
  8789. me-&gt;ao.thread = thr;
  8790. me-&gt;ao.eQueue.head = (QEQueueCtr)thr-&gt;super.prio;
  8791. QS_BEGIN_NOCRIT_PRE_(QS_MTX_LOCK, thr-&gt;super.prio)
  8792. QS_TIME_PRE_(); /* timestamp */
  8793. QS_OBJ_PRE_(me); /* this mutex */
  8794. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8795. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8796. QS_END_NOCRIT_PRE_()
  8797. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8798. /* the holder priority must be lower than that of the mutex */
  8799. Q_ASSERT_ID(410, thr-&gt;super.prio &lt; me-&gt;ao.prio);
  8800. /* put the thread into AO registry in place of the mutex */
  8801. QActive_registry_[me-&gt;ao.prio] = &amp;thr-&gt;super;
  8802. }
  8803. }
  8804. else { /* no threads are waiting for this mutex */
  8805. me-&gt;ao.eQueue.nFree = 0U; /* free up the nesting count */
  8806. /* the mutex no longer held by any thread */
  8807. me-&gt;ao.thread = (void *)0;
  8808. me-&gt;ao.eQueue.head = 0U;
  8809. if (me-&gt;ao.prio != 0U) { /* priority-ceiling protocol used? */
  8810. /* put the mutex back at the original mutex slot */
  8811. QActive_registry_[me-&gt;ao.prio] =
  8812. QXK_PTR_CAST_(QActive*, me);
  8813. }
  8814. }
  8815. /* schedule the next thread if multitasking started */
  8816. if (QXK_sched_() != 0U) { /* activation needed? */
  8817. QXK_activate_(); /* synchronously activate basic-thred(s) */
  8818. }
  8819. }
  8820. else { /* releasing one level of nested mutex lock */
  8821. Q_ASSERT_ID(420, me-&gt;ao.eQueue.nFree &gt; 0U);
  8822. --me-&gt;ao.eQueue.nFree; /* unlock one level */
  8823. QS_BEGIN_NOCRIT_PRE_(QS_MTX_UNLOCK_ATTEMPT, curr-&gt;prio)
  8824. QS_TIME_PRE_(); /* timestamp */
  8825. QS_OBJ_PRE_(me); /* this mutex */
  8826. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.head); /* holder prio */
  8827. QS_U8_PRE_((uint8_t)me-&gt;ao.eQueue.nFree); /* nesting */
  8828. QS_END_NOCRIT_PRE_()
  8829. }
  8830. QF_CRIT_X_();</code>
  8831. </operation>
  8832. </class>
  8833. <!--${QXK::QXK-extern-C}-->
  8834. <package name="QXK-extern-C" stereotype="0x02" namespace="QXK_">
  8835. <!--${QXK::QXK-extern-C::Attr}-->
  8836. <attribute name="Attr" type="typedef struct" visibility="0x04" properties="0x00">
  8837. <documentation>/*! @brief The QXK kernel class
  8838. * @class QXK
  8839. *
  8840. * @note
  8841. * The order and alignment of the data members in this struct might
  8842. * be important in QXK ports, where the members might be accessed
  8843. * in assembly.
  8844. */</documentation>
  8845. <code>{
  8846. struct QActive * volatile curr; /*!&lt; current thread (NULL=basic) */
  8847. struct QActive * volatile next; /*!&lt; next thread to run */
  8848. struct QActive * volatile prev; /*!&lt; previous thread */
  8849. uint8_t volatile actPrio; /*!&lt; QF-prio of the active AO */
  8850. uint8_t volatile lockCeil; /*!&lt; lock-ceiling (0==no-lock) */
  8851. uint8_t volatile lockHolder; /*!&lt; prio of the lock holder */
  8852. } QXK;</code>
  8853. </attribute>
  8854. <!--${QXK::QXK-extern-C::attr_}-->
  8855. <attribute name="attr_" type="QXK" visibility="0x01" properties="0x00">
  8856. <documentation>/*! attributes of the QXK kernel
  8857. * @static @private @memberof QXK
  8858. */
  8859. /*! @static @private @memberof QXK */</documentation>
  8860. </attribute>
  8861. <!--${QXK::QXK-extern-C::sched_}-->
  8862. <operation name="sched_" type="uint_fast8_t" visibility="0x00" properties="0x00">
  8863. <documentation>/*! QXK scheduler finds the highest-priority thread ready to run
  8864. * @static @private @memberof QXK
  8865. *
  8866. * @details
  8867. * The QXK scheduler finds the priority of the highest-priority thread
  8868. * that is ready to run.
  8869. *
  8870. * @returns
  8871. * the 1-based priority of the the thread (basic or extended) run next,
  8872. * or zero if no eligible thread is found.
  8873. *
  8874. * @attention
  8875. * QXK_sched_() must be always called with interrupts **disabled** and
  8876. * returns with interrupts **disabled**.
  8877. */
  8878. /*! @static @private @memberof QXK */</documentation>
  8879. <code>uint_fast8_t p;
  8880. if (QPSet_isEmpty(&amp;QF_readySet_)) {
  8881. p = 0U; /* no activation needed */
  8882. }
  8883. else {
  8884. /* find the highest-prio thread ready to run */
  8885. p = QPSet_findMax(&amp;QF_readySet_);
  8886. if (p &lt;= QXK_attr_.lockCeil) {
  8887. /* priority of the thread holding the lock */
  8888. p = (uint_fast8_t)QActive_registry_[QXK_attr_.lockHolder]-&gt;prio;
  8889. if (p != 0U) {
  8890. Q_ASSERT_ID(610, QPSet_hasElement(&amp;QF_readySet_, p));
  8891. }
  8892. }
  8893. }
  8894. QActive const * const curr = QXK_attr_.curr;
  8895. QActive * const next = QActive_registry_[p];
  8896. /* the next thread found must be registered in QF */
  8897. Q_ASSERT_ID(620, next != (QActive *)0);
  8898. /* is the current thread a basic-thread? */
  8899. if (curr == (QActive *)0) {
  8900. /* is the new priority above the active priority? */
  8901. if (p &gt; QXK_attr_.actPrio) {
  8902. QXK_attr_.next = next; /* set the next AO to activate */
  8903. if (next-&gt;osObject != (void *)0) { /* is next extended? */
  8904. QXK_CONTEXT_SWITCH_();
  8905. p = 0U; /* no activation needed */
  8906. }
  8907. }
  8908. else { /* below the pre-thre */
  8909. QXK_attr_.next = (QActive *)0;
  8910. p = 0U; /* no activation needed */
  8911. }
  8912. }
  8913. else { /* currently executing an extended-thread */
  8914. /* is the current thread different from the next? */
  8915. if (curr != next) {
  8916. QXK_attr_.next = next;
  8917. QXK_CONTEXT_SWITCH_();
  8918. }
  8919. else { /* current is the same as next */
  8920. QXK_attr_.next = (QActive *)0; /* no need to context-switch */
  8921. }
  8922. p = 0U; /* no activation needed */
  8923. }
  8924. return p;</code>
  8925. </operation>
  8926. <!--${QXK::QXK-extern-C::activate_}-->
  8927. <operation name="activate_" type="void" visibility="0x00" properties="0x00">
  8928. <documentation>/*! QXK activator activates the next active object. The activated AO
  8929. * preempts the currently executing AOs.
  8930. * @static @private @memberof QXK
  8931. *
  8932. * @details
  8933. * QXK_activate_() activates ready-to run AOs that are above the initial
  8934. * active priority (QXK_attr_.actPrio).
  8935. *
  8936. * @precondition{qxk,700}
  8937. * - QXK_attr_.next must be valid and the prio must be in range
  8938. *
  8939. * @attention
  8940. * QXK_activate_() must be always called with interrupts **disabled** and
  8941. * returns with interrupts **disabled**.
  8942. */
  8943. /*! @static @private @memberof QXK */</documentation>
  8944. <code>uint8_t const prio_in = QXK_attr_.actPrio;
  8945. QActive *next = QXK_attr_.next; /* the next AO (basic-thread) to run */
  8946. Q_REQUIRE_ID(700, (next != (QActive *)0) &amp;&amp; (prio_in &lt;= QF_MAX_ACTIVE));
  8947. /* QXK Context switch callback defined or QS tracing enabled? */
  8948. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  8949. QXK_contextSw(next);
  8950. #endif /* QF_ON_CONTEXT_SW || Q_SPY */
  8951. QXK_attr_.next = (QActive *)0; /* clear the next AO */
  8952. QXK_attr_.curr = (QActive *)0; /* current is basic-thread */
  8953. /* priority of the next thread */
  8954. uint8_t p = next-&gt;prio;
  8955. /* loop until no more ready-to-run AOs of higher prio than the initial */
  8956. do {
  8957. QXK_attr_.actPrio = p; /* next active prio */
  8958. QF_INT_ENABLE(); /* unconditionally enable interrupts */
  8959. /* perform the run-to-completion (RTC) step...
  8960. * 1. retrieve the event from the AO's event queue, which by this
  8961. * time must be non-empty and QActive_get_() asserts it.
  8962. * 2. dispatch the event to the AO's state machine.
  8963. * 3. determine if event is garbage and collect it if so
  8964. */
  8965. QEvt const * const e = QActive_get_(next);
  8966. QHSM_DISPATCH(&amp;next-&gt;super, e, next-&gt;prio);
  8967. #if (QF_MAX_EPOOL &gt; 0U)
  8968. QF_gc(e);
  8969. #endif
  8970. QF_INT_DISABLE(); /* unconditionally disable interrupts */
  8971. if (next-&gt;eQueue.frontEvt == (QEvt *)0) { /* empty queue? */
  8972. QPSet_remove(&amp;QF_readySet_, p);
  8973. }
  8974. if (QPSet_isEmpty(&amp;QF_readySet_)) {
  8975. QXK_attr_.next = (QActive *)0;
  8976. next = QActive_registry_[0];
  8977. p = 0U; /* no activation needed */
  8978. }
  8979. else {
  8980. /* find next highest-prio below the lock ceiling */
  8981. p = (uint8_t)QPSet_findMax(&amp;QF_readySet_);
  8982. if (p &lt;= QXK_attr_.lockCeil) {
  8983. p = QXK_attr_.lockHolder; /* thread holding lock */
  8984. if (p != 0U) {
  8985. Q_ASSERT_ID(710, QPSet_hasElement(&amp;QF_readySet_, p));
  8986. }
  8987. }
  8988. /* set the next thread and ensure that it is registered */
  8989. next = QActive_registry_[p];
  8990. Q_ASSERT_ID(720, next != (QActive *)0);
  8991. /* is next a basic thread? */
  8992. if (next-&gt;osObject == (void *)0) {
  8993. /* is the next priority above the initial priority? */
  8994. if (p &gt; QActive_registry_[prio_in]-&gt;prio) {
  8995. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  8996. if (p != QXK_attr_.actPrio) { /* changing threads? */
  8997. QXK_contextSw(next);
  8998. }
  8999. #endif /* QF_ON_CONTEXT_SW || Q_SPY */
  9000. QXK_attr_.next = next;
  9001. }
  9002. else {
  9003. QXK_attr_.next = (QActive *)0;
  9004. p = 0U; /* no activation needed */
  9005. }
  9006. }
  9007. else { /* next is the extended-thread */
  9008. QXK_attr_.next = next;
  9009. QXK_CONTEXT_SWITCH_();
  9010. p = 0U; /* no activation needed */
  9011. }
  9012. }
  9013. } while (p != 0U); /* while activation needed */
  9014. /* restore the active priority */
  9015. QXK_attr_.actPrio = prio_in;
  9016. #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
  9017. if (next-&gt;osObject == (void *)0) {
  9018. QXK_contextSw((prio_in == 0U)
  9019. ? (QActive *)0
  9020. : QActive_registry_[prio_in]);
  9021. }
  9022. #endif /* QF_ON_CONTEXT_SW || Q_SPY */</code>
  9023. </operation>
  9024. <!--${QXK::QXK-extern-C::current}-->
  9025. <operation name="current" type="QActive *" visibility="0x00" properties="0x00">
  9026. <documentation>/*! obtain the currently executing active-object/thread
  9027. * @static @public @memberof QXK
  9028. *
  9029. * @returns
  9030. * pointer to the currently executing active-object/thread
  9031. *
  9032. * @precondition{qxk,800}
  9033. * - the QXK kernel must be running
  9034. *
  9035. * @postcondition{qxk,890}
  9036. * - the current thread must be valid
  9037. */
  9038. /*! @static @public @memberof QXK */</documentation>
  9039. <code>Q_REQUIRE_ID(800, QXK_attr_.lockCeil &lt;= QF_MAX_ACTIVE);
  9040. QF_CRIT_STAT_
  9041. QF_CRIT_E_();
  9042. struct QActive *curr = QXK_attr_.curr;
  9043. if (curr == (QActive *)0) { /* basic thread? */
  9044. curr = QActive_registry_[QXK_attr_.actPrio];
  9045. }
  9046. QF_CRIT_X_();
  9047. Q_ENSURE_ID(890, curr != (QActive *)0);
  9048. return curr;</code>
  9049. </operation>
  9050. <!--${QXK::QXK-extern-C::stackInit_}-->
  9051. <operation name="stackInit_" type="void" visibility="0x00" properties="0x00">
  9052. <documentation>/*! initialize the private stack of a given AO (defined in QXK port)
  9053. * @static @private @memberof QXK
  9054. */
  9055. /*! @static @private @memberof QXK */</documentation>
  9056. <!--${QXK::QXK-extern-C::stackInit_::thr}-->
  9057. <parameter name="thr" type="void *"/>
  9058. <!--${QXK::QXK-extern-C::stackInit_::handler}-->
  9059. <parameter name="handler" type=" QXThreadHandler const"/>
  9060. <!--${QXK::QXK-extern-C::stackInit_::stkSto}-->
  9061. <parameter name="stkSto" type="void * const"/>
  9062. <!--${QXK::QXK-extern-C::stackInit_::stkSize}-->
  9063. <parameter name="stkSize" type="uint_fast16_t const"/>
  9064. </operation>
  9065. <!--${QXK::QXK-extern-C::contextSw}-->
  9066. <operation name="contextSw? defined(Q_SPY) || defined(QF_ON_CONTEXT_SW)" type="void" visibility="0x00" properties="0x00">
  9067. <documentation>/*! QXK context switch management
  9068. * @static @public @memberof QXK
  9069. *
  9070. * @details
  9071. * This function performs software tracing (if #Q_SPY is defined)
  9072. * and calls QF_onContextSw() (if #QF_ON_CONTEXT_SW is defined)
  9073. *
  9074. * @param[in] next pointer to the next thread (NULL for basic-thread)
  9075. *
  9076. * @attention
  9077. * QXK_contextSw() is invoked with interrupts **disabled** and must also
  9078. * return with interrupts **disabled**.
  9079. */
  9080. /*! @static @public @memberof QXK */</documentation>
  9081. <!--${QXK::QXK-extern-C::contextSw::next}-->
  9082. <parameter name="next" type="QActive * const"/>
  9083. <code>#ifdef Q_SPY
  9084. uint8_t const prev_prio = (QXK_attr_.prev != (QActive *)0)
  9085. ? QXK_attr_.prev-&gt;prio
  9086. : 0U;
  9087. #endif /* Q_SPY */
  9088. if (next != (QActive *)0) { /* next is NOT idle? */
  9089. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_NEXT, next-&gt;prio)
  9090. QS_TIME_PRE_(); /* timestamp */
  9091. QS_2U8_PRE_(next-&gt;prio, prev_prio);
  9092. QS_END_NOCRIT_PRE_()
  9093. }
  9094. else { /* going to idle */
  9095. QS_BEGIN_NOCRIT_PRE_(QS_SCHED_IDLE, prev_prio)
  9096. QS_TIME_PRE_(); /* timestamp */
  9097. QS_U8_PRE_(prev_prio);
  9098. QS_END_NOCRIT_PRE_()
  9099. }
  9100. #ifdef QF_ON_CONTEXT_SW
  9101. QF_onContextSw(QXK_attr_.prev, next);
  9102. #endif /* QF_ON_CONTEXT_SW */
  9103. QXK_attr_.prev = next; /* update the previous thread */</code>
  9104. </operation>
  9105. </package>
  9106. </package>
  9107. <!--${QXK-macros}-->
  9108. <package name="QXK-macros" stereotype="0x02">
  9109. <!--${QXK-macros::QXTHREAD_START}-->
  9110. <operation name="QXTHREAD_START" type="void" visibility="0x03" properties="0x00">
  9111. <documentation>/*! Virtual call to start an extened thread
  9112. *
  9113. * @details
  9114. * Starts execution of the thread and registers the AO with the framework.
  9115. *
  9116. * @param[in,out] me_ current instance pointer (see @ref oop)
  9117. * @param[in] prioSpec_ priority specification at which to start the
  9118. * extended thread (see ::QPrioSpec)
  9119. * @param[in] qSto_ pointer to the storage for the ring buffer of the
  9120. * event queue (used only with the built-in ::QEQueue)
  9121. * @param[in] qLen_ length of the event queue (in events)
  9122. * @param[in] stkSto_ pointer to the stack storage (used only when
  9123. * per-AO stack is needed)
  9124. * @param[in] stkSize_ stack size (in bytes)
  9125. * @param[in] par_ pointer to the additional port-specific parameter(s)
  9126. * (might be NULL).
  9127. * @usage
  9128. * @include qxk_start.c
  9129. */</documentation>
  9130. <!--${QXK-macros::QXTHREAD_START::me_}-->
  9131. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  9132. <!--${QXK-macros::QXTHREAD_START::prioSpec_}-->
  9133. <parameter name="prioSpec_" type="QPrioSpec const"/>
  9134. <!--${QXK-macros::QXTHREAD_START::qSto_}-->
  9135. <parameter name="qSto_" type="QEvt const * *"/>
  9136. <!--${QXK-macros::QXTHREAD_START::qLen_}-->
  9137. <parameter name="qLen_" type="uint_fast16_t"/>
  9138. <!--${QXK-macros::QXTHREAD_START::stkSto_}-->
  9139. <parameter name="stkSto_" type="void *"/>
  9140. <!--${QXK-macros::QXTHREAD_START::stkSize_}-->
  9141. <parameter name="stkSize_" type="uint_fast16_t"/>
  9142. <!--${QXK-macros::QXTHREAD_START::par_}-->
  9143. <parameter name="par_" type="void const *"/>
  9144. <code>\
  9145. do { \
  9146. Q_ASSERT((me_)-&gt;super.super.vptr); \
  9147. ((*((QActiveVtable const *)((me_)-&gt;super.super.vptr))-&gt;start)( \
  9148. &amp;(me_)-&gt;super, (prioSpec_), (QEvt const **)(qSto_), (qLen_), \
  9149. (stkSto_), (stkSize_), (par_))); \
  9150. } while (false)</code>
  9151. </operation>
  9152. <!--${QXK-macros::QXTHREAD_NO_TIMEOUT}-->
  9153. <attribute name="QXTHREAD_NO_TIMEOUT" type="uint_fast16_t" visibility="0x03" properties="0x00">
  9154. <documentation>/*! No-timeout when blocking on semaphores, mutextes, and queues */</documentation>
  9155. <code>((uint_fast16_t)0)</code>
  9156. </attribute>
  9157. <!--${QXK-macros::QXTHREAD_POST_X}-->
  9158. <operation name="QXTHREAD_POST_X" type="void" visibility="0x03" properties="0x00">
  9159. <documentation>/*! Asynchronous posting events to the event queue of an eXtended thread
  9160. * @details
  9161. * This macro does not assert if the queue overflows and cannot accept
  9162. * the event with the specified margin of free slots remaining.
  9163. *
  9164. * @param[in,out] me_ current instance pointer (see @ref oop)
  9165. * @param[in] e_ pointer to the event to post
  9166. * @param[in] margin_ the minimum free slots in the queue, which
  9167. * must still be available after posting the event.
  9168. * The special value #QF_NO_MARGIN causes asserting
  9169. * failure in case event allocation fails.
  9170. * @param[in] sender_ pointer to the sender object (used in QS tracing)
  9171. *
  9172. * @returns
  9173. * 'true' if the posting succeeded, and 'false' if the posting failed due
  9174. * to insufficient margin of free slots available in the queue.
  9175. *
  9176. * @note
  9177. * The `sender_` parameter is actually only used when QS tracing is enabled
  9178. * (macro #Q_SPY is defined). When QS software tracing is disabled, the
  9179. * QXTHREAD_POST_X() macro does not pass the `sender_` parameter, so the
  9180. * overhead of passing this extra argument is entirely avoided.
  9181. *
  9182. * @note
  9183. * The pointer to the sender object is not necessarily a pointer to an
  9184. * active object. In fact, if QXTHREAD_POST_X() is called from an interrupt
  9185. * or other context, you can create a unique object just to unambiguously
  9186. * identify the sender of the event.
  9187. *
  9188. * @usage
  9189. * @include qf_postx.c
  9190. */</documentation>
  9191. <!--${QXK-macros::QXTHREAD_POST_X::me_}-->
  9192. <parameter name="me_" type="&lt;QActive subclass *&gt;"/>
  9193. <!--${QXK-macros::QXTHREAD_POST_X::e_}-->
  9194. <parameter name="e_" type="QEvt const *"/>
  9195. <!--${QXK-macros::QXTHREAD_POST_X::margin_}-->
  9196. <parameter name="margin_" type="uint16_t"/>
  9197. <!--${QXK-macros::QXTHREAD_POST_X::sender_}-->
  9198. <parameter name="sender_" type="&lt;sender *&gt;"/>
  9199. <code>\
  9200. QACTIVE_POST_X(&amp;(me_)-&gt;super, (e_), (margin_), (sender_))</code>
  9201. </operation>
  9202. </package>
  9203. <!--${QXK-impl}-->
  9204. <package name="QXK-impl" stereotype="0x02">
  9205. <!--${QXK-impl::QXK_ISR_CONTEXT_}-->
  9206. <operation name="QXK_ISR_CONTEXT_?ndef QXK_ISR_CONTEXT_" type="" visibility="0x03" properties="0x00">
  9207. <documentation>/*! Internal macro that reports the execution context (ISR vs. thread)
  9208. *
  9209. * @returns true if the code executes in the ISR context and false
  9210. * otherwise
  9211. */</documentation>
  9212. <code>(QF_intNest_ != 0U)</code>
  9213. </operation>
  9214. <!--${QXK-impl::QF_SCHED_STAT_}-->
  9215. <attribute name="QF_SCHED_STAT_" type="" visibility="0x03" properties="0x00">
  9216. <documentation>/*! QXK scheduler lock status */</documentation>
  9217. <code>QSchedStatus lockStat_;</code>
  9218. </attribute>
  9219. <!--${QXK-impl::QF_SCHED_LOCK_}-->
  9220. <operation name="QF_SCHED_LOCK_" type="" visibility="0x03" properties="0x00">
  9221. <documentation>/*! QXK selective scheduler locking */</documentation>
  9222. <!--${QXK-impl::QF_SCHED_LOCK_::ceil_}-->
  9223. <parameter name="ceil_" type="uint_fast8_t"/>
  9224. <code>do { \
  9225. if (QXK_ISR_CONTEXT_()) { \
  9226. lockStat_ = 0xFFU; \
  9227. } else { \
  9228. lockStat_ = QXK_schedLock((ceil_)); \
  9229. } \
  9230. } while (false)</code>
  9231. </operation>
  9232. <!--${QXK-impl::QF_SCHED_UNLOCK_}-->
  9233. <operation name="QF_SCHED_UNLOCK_" type="" visibility="0x03" properties="0x00">
  9234. <documentation>/*! QXK selective scheduler unlocking */</documentation>
  9235. <code>do { \
  9236. if (lockStat_ != 0xFFU) { \
  9237. QXK_schedUnlock(lockStat_); \
  9238. } \
  9239. } while (false)</code>
  9240. </operation>
  9241. <!--${QXK-impl::QACTIVE_EQUEUE_WAIT_}-->
  9242. <operation name="QACTIVE_EQUEUE_WAIT_" type="" visibility="0x03" properties="0x00">
  9243. <documentation>/*! QXK native event queue waiting */</documentation>
  9244. <!--${QXK-impl::QACTIVE_EQUEUE_W~::me_}-->
  9245. <parameter name="me_" type="QActive *"/>
  9246. <code>\
  9247. (Q_ASSERT_ID(110, (me_)-&gt;eQueue.frontEvt != (QEvt *)0))</code>
  9248. </operation>
  9249. <!--${QXK-impl::QACTIVE_EQUEUE_SIGNAL_}-->
  9250. <operation name="QACTIVE_EQUEUE_SIGNAL_" type="" visibility="0x03" properties="0x00">
  9251. <documentation>/*! QXK native event queue signaling */</documentation>
  9252. <!--${QXK-impl::QACTIVE_EQUEUE_S~::me_}-->
  9253. <parameter name="me_" type="QActive *"/>
  9254. <code>do { \
  9255. QPSet_insert(&amp;QF_readySet_, (uint_fast8_t)(me_)-&gt;prio); \
  9256. if (!QXK_ISR_CONTEXT_()) { \
  9257. if (QXK_sched_() != 0U) { \
  9258. QXK_activate_(); \
  9259. } \
  9260. } \
  9261. } while (false)</code>
  9262. </operation>
  9263. <!--${QXK-impl::QXK_PTR_CAST_}-->
  9264. <operation name="QXK_PTR_CAST_" type="QXThread *" visibility="0x03" properties="0x00">
  9265. <specifiers>&lt;type_&gt;</specifiers>
  9266. <documentation>/*! internal macro to encapsulate casting of pointers for MISRA deviations
  9267. *
  9268. * @details
  9269. * This macro is specifically and exclusively used for casting pointers
  9270. * that are never de-referenced, but only used for internal bookkeeping and
  9271. * checking (via assertions) the correct operation of the QXK kernel.
  9272. * Such pointer casting is not compliant with MISRA-2012-Rule 11.3(req)
  9273. * as well as other messages (e.g., PC-Lint-Plus warning 826).
  9274. * Defining this specific macro for this purpose allows to selectively
  9275. * disable the warnings for this particular case.
  9276. */</documentation>
  9277. <!--${QXK-impl::QXK_PTR_CAST_::type_}-->
  9278. <parameter name="type_" type="&lt;QXK obj&gt;"/>
  9279. <!--${QXK-impl::QXK_PTR_CAST_::ptr_}-->
  9280. <parameter name="ptr_" type="QActive *"/>
  9281. <code>((type_)(ptr_))</code>
  9282. </operation>
  9283. <!--${QXK-impl::QXTHREAD_CAST_}-->
  9284. <operation name="QXTHREAD_CAST_" type="QXThread *" visibility="0x03" properties="0x00">
  9285. <documentation>/*! internal macro to encapsulate casting of pointers for MISRA deviations
  9286. *
  9287. * @details
  9288. * This macro is specifically and exclusively used for downcasting pointers
  9289. * to QActive to pointers to QXThread in situations when it is known
  9290. * that such downcasting is correct.However, such pointer casting is not
  9291. * compliant with MISRA-2012-Rule 11.3(req) as well as other messages (e.g.,
  9292. * PC-Lint-Plus warning 826). Defining this specific macro for this purpose
  9293. * allows to selectively disable the warnings for this particular case.
  9294. */</documentation>
  9295. <!--${QXK-impl::QXTHREAD_CAST_::ptr_}-->
  9296. <parameter name="ptr_" type="QActive *"/>
  9297. <code>((QXThread *)(ptr_))</code>
  9298. </operation>
  9299. <!--${QXK-impl::QXK_threadExit_}-->
  9300. <operation name="QXK_threadExit_" type="void" visibility="0x00" properties="0x00">
  9301. <documentation>/*! called when QXThread exits
  9302. * @private @memberof QXThread
  9303. *
  9304. * @details
  9305. * Called when the extended-thread handler function returns.
  9306. *
  9307. * @precondition{qxk,900}
  9308. * - must NOT be called from an ISR;
  9309. * - must be called from an extended thread
  9310. * @precondition{qxk,901}
  9311. * - the thread must NOT be holding a scheduler lock
  9312. *
  9313. * @note
  9314. * Most thread handler functions are structured as endless loops that never
  9315. * return. But it is also possible to structure threads as one-shot functions
  9316. * that perform their job and return. In that case this function peforms
  9317. * cleanup after the thread.
  9318. */
  9319. /*! @private @memberof QXThread */</documentation>
  9320. <code>QF_CRIT_STAT_
  9321. QF_CRIT_E_();
  9322. QXThread const * const thr = QXTHREAD_CAST_(QXK_attr_.curr);
  9323. Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't be in the ISR context */
  9324. &amp;&amp; (thr != (QXThread *)0)); /* current thread must be extended */
  9325. Q_REQUIRE_ID(901, QXK_attr_.lockHolder != thr-&gt;super.prio);
  9326. uint_fast8_t const p = (uint_fast8_t)thr-&gt;super.prio;
  9327. /* remove this thread from the QF */
  9328. QActive_registry_[p] = (QActive *)0;
  9329. QPSet_remove(&amp;QF_readySet_, p);
  9330. (void)QXK_sched_(); /* schedule other threads */
  9331. QF_CRIT_X_();</code>
  9332. </operation>
  9333. </package>
  9334. <!--${QS-config}-->
  9335. <package name="QS-config" stereotype="0x02">
  9336. <!--${QS-config::QS_CTR_SIZE}-->
  9337. <attribute name="QS_CTR_SIZE?ndef QS_CTR_SIZE" type="unsigned" visibility="0x03" properties="0x00">
  9338. <documentation>/*! The size [bytes] of the internal QS buffer-counters. Valid values: 2U or 4U;
  9339. * default 2U.
  9340. *
  9341. * @details
  9342. * This macro can be defined in the QS port file (qs_port.h) to
  9343. * configure the ::QSCtr type. Here the macro is not defined so the
  9344. * default of 2 byte is chosen.
  9345. */</documentation>
  9346. <code>2U</code>
  9347. </attribute>
  9348. <!--${QS-config::QS_CTR_SIZE defined incorrectly,~}-->
  9349. <attribute name="QS_CTR_SIZE defined incorrectly, expected 2U or 4U? (QS_CTR_SIZE != 2U) &amp;&amp; (QS_CTR_SIZE != 4U)" type="#error" visibility="0x04" properties="0x00"/>
  9350. <!--${QS-config::QS_TIME_SIZE}-->
  9351. <attribute name="QS_TIME_SIZE?ndef QS_TIME_SIZE" type="unsigned" visibility="0x03" properties="0x00">
  9352. <documentation>/*! The size [bytes] of the QS time stamp. Valid values: 1U, 2U, or 4U;
  9353. * default 4U.
  9354. *
  9355. * @details
  9356. * This macro can be defined in the QS port file (qs_port.h) to
  9357. * configure the ::QSTimeCtr type. Here the macro is not defined so the
  9358. * default of 4 byte is chosen.
  9359. */</documentation>
  9360. <code>4U</code>
  9361. </attribute>
  9362. <!--${QS-config::QS_TIME_SIZE defined incorrectly~}-->
  9363. <attribute name="QS_TIME_SIZE defined incorrectly, expected 1U, 2U, or 4U? (QS_TIME_SIZE != 1U) &amp;&amp; (QS_TIME_SIZE != 2U) &amp;&amp; (QS_TIME_SIZE != 4U)" type="#error" visibility="0x04" properties="0x00"/>
  9364. </package>
  9365. <!--${QS-macros}-->
  9366. <package name="QS-macros" stereotype="0x02">
  9367. <!--${QS-macros::QS_INIT}-->
  9368. <operation name="QS_INIT" type="void" visibility="0x03" properties="0x00">
  9369. <documentation>/*! Initialize the QS facility
  9370. *
  9371. * @details
  9372. * This macro provides an indirection layer to invoke the QS initialization
  9373. * routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
  9374. * @sa QS_onStartup(), example of setting up a QS filter in
  9375. * QS_GLB_FILTER()
  9376. */</documentation>
  9377. <!--${QS-macros::QS_INIT::arg_}-->
  9378. <parameter name="arg_" type="void *"/>
  9379. <code>(QS_onStartup(arg_))</code>
  9380. </operation>
  9381. <!--${QS-macros::QS_EXIT}-->
  9382. <operation name="QS_EXIT" type="void" visibility="0x03" properties="0x00">
  9383. <documentation>/*! Cleanup the QS facility
  9384. *
  9385. * @details
  9386. * This macro provides an indirection layer to invoke the QS cleanup
  9387. * routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
  9388. * @sa QS_onCleanup()
  9389. */</documentation>
  9390. <code>(QS_onCleanup())</code>
  9391. </operation>
  9392. <!--${QS-macros::QS_OUTPUT}-->
  9393. <operation name="QS_OUTPUT" type="void" visibility="0x03" properties="0x00">
  9394. <documentation>/*! macro to handle the QS output from the application
  9395. *
  9396. * @note
  9397. * If this macro is used, the application must define QS_output().
  9398. */</documentation>
  9399. <code>(QS_output())</code>
  9400. </operation>
  9401. <!--${QS-macros::QS_RX_INPUT}-->
  9402. <operation name="QS_RX_INPUT" type="void" visibility="0x03" properties="0x00">
  9403. <documentation>/*! macro to handle the QS-RX input to the application
  9404. *
  9405. * @note
  9406. * If this macro is used, the application must define QS_doInput().
  9407. */</documentation>
  9408. <code>(QS_rx_input())</code>
  9409. </operation>
  9410. <!--${QS-macros::QS_GLB_FILTER}-->
  9411. <operation name="QS_GLB_FILTER" type="void" visibility="0x03" properties="0x00">
  9412. <documentation>/*! Global Filter ON for a given record type `rec_`
  9413. *
  9414. * @details
  9415. * This macro provides an indirection layer to call QS_filterOn()
  9416. * if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
  9417. *
  9418. * @sa
  9419. * - enum QSpyGroups - QS record groups that can be used as `rec_`
  9420. * - enum QSpyPre - predefined QS records that can be used as `rec_`
  9421. *
  9422. * @usage
  9423. * The following example shows how to use QS filters:
  9424. * @include qs_filter.c
  9425. */</documentation>
  9426. <!--${QS-macros::QS_GLB_FILTER::rec_}-->
  9427. <parameter name="rec_" type="uint8_t"/>
  9428. <code>(QS_glbFilter_((int_fast16_t)(rec_)))</code>
  9429. </operation>
  9430. <!--${QS-macros::QS_LOC_FILTER}-->
  9431. <operation name="QS_LOC_FILTER" type="void" visibility="0x03" properties="0x00">
  9432. <documentation>/*! Local Filter for a given state machine object `qs_id`
  9433. *
  9434. * @details
  9435. * This macro provides an indirection layer to call QS_locFilter_()
  9436. * if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
  9437. *
  9438. * @sa
  9439. * - enum QSpyIdGroups - QS ID groups that can be used as `qs_id_`
  9440. * - enum QSpyIdOffsets - QS ID offsets for `qs_id_` (e.g., QS_AP_IDS + 5)
  9441. *
  9442. * The following example shows how to use QS filters:
  9443. * @include qs_filter.c
  9444. */</documentation>
  9445. <!--${QS-macros::QS_LOC_FILTER::qs_id_}-->
  9446. <parameter name="qs_id_" type="uint8_t"/>
  9447. <code>(QS_locFilter_((int_fast16_t)(qs_id_)))</code>
  9448. </operation>
  9449. <!--${QS-macros::QS_BEGIN_ID}-->
  9450. <operation name="QS_BEGIN_ID" type="void" visibility="0x03" properties="0x00">
  9451. <documentation>/*! Begin an application-specific QS record with entering critical section
  9452. *
  9453. * @details
  9454. * The following example shows how to build a user QS record using the
  9455. * macros QS_BEGIN_ID(), QS_END(), and the formatted output macros:
  9456. * QS_U8(), QS_STR(), etc.
  9457. *
  9458. * @note
  9459. * Must always be used in pair with QS_END()
  9460. *
  9461. * @include qs_ap.c
  9462. */</documentation>
  9463. <!--${QS-macros::QS_BEGIN_ID::rec_}-->
  9464. <parameter name="rec_" type="uint8_t"/>
  9465. <!--${QS-macros::QS_BEGIN_ID::qs_id_}-->
  9466. <parameter name="qs_id_" type="uint8_t"/>
  9467. <code>\
  9468. if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qs_id_)) { \
  9469. QS_CRIT_STAT_ \
  9470. QS_CRIT_E_(); \
  9471. QS_beginRec_((uint_fast8_t)(rec_)); \
  9472. QS_TIME_PRE_(); {</code>
  9473. </operation>
  9474. <!--${QS-macros::QS_END}-->
  9475. <operation name="QS_END" type="void" visibility="0x03" properties="0x00">
  9476. <documentation>/*! End an application-specific QS record with exiting critical section.
  9477. *
  9478. * @sa example for QS_BEGIN_ID()
  9479. * @note Must always be used in pair with QS_BEGIN_ID()
  9480. */</documentation>
  9481. <code>} \
  9482. QS_endRec_(); \
  9483. QS_CRIT_X_(); \
  9484. }</code>
  9485. </operation>
  9486. <!--${QS-macros::QS_FLUSH}-->
  9487. <operation name="QS_FLUSH" type="void" visibility="0x03" properties="0x00">
  9488. <documentation>/*! Flush the QS trace data to the host
  9489. *
  9490. * @details
  9491. * This macro invokes the QS_flush() platform-dependent callback
  9492. * function to flush the QS trace buffer to the host. The function
  9493. * typically busy-waits until all the data in the buffer is sent to
  9494. * the host. This is acceptable only in the initial transient.
  9495. */</documentation>
  9496. <code>(QS_onFlush())</code>
  9497. </operation>
  9498. <!--${QS-macros::QS_BEGIN_NOCRIT}-->
  9499. <operation name="QS_BEGIN_NOCRIT" type="void" visibility="0x03" properties="0x00">
  9500. <documentation>/*! Begin an application-specific QS record WITHOUT entering critical section */</documentation>
  9501. <!--${QS-macros::QS_BEGIN_NOCRIT::rec_}-->
  9502. <parameter name="rec_" type="uint8_t"/>
  9503. <!--${QS-macros::QS_BEGIN_NOCRIT::qs_id_}-->
  9504. <parameter name="qs_id_" type="uint8_t"/>
  9505. <code>\
  9506. if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qs_id_)) { \
  9507. QS_beginRec_((uint_fast8_t)(rec_)); \
  9508. QS_TIME_PRE_(); {</code>
  9509. </operation>
  9510. <!--${QS-macros::QS_END_NOCRIT}-->
  9511. <operation name="QS_END_NOCRIT" type="void" visibility="0x03" properties="0x00">
  9512. <documentation>/*! End an application-specific QS record WITHOUT exiting critical section */</documentation>
  9513. <code>} \
  9514. QS_endRec_();\
  9515. }</code>
  9516. </operation>
  9517. <!--${QS-macros::QS_GLB_CHECK_}-->
  9518. <operation name="QS_GLB_CHECK_" type="void" visibility="0x03" properties="0x00">
  9519. <documentation>/*! Helper macro for checking the global QS filter */</documentation>
  9520. <!--${QS-macros::QS_GLB_CHECK_::rec_}-->
  9521. <parameter name="rec_" type="uint8_t"/>
  9522. <code>\
  9523. (((uint_fast8_t)QS_priv_.glbFilter[(uint_fast8_t)(rec_) &gt;&gt; 3U] \
  9524. &amp; ((uint_fast8_t)1U &lt;&lt; ((uint_fast8_t)(rec_) &amp; 7U))) != 0U)</code>
  9525. </operation>
  9526. <!--${QS-macros::QS_LOC_CHECK_}-->
  9527. <operation name="QS_LOC_CHECK_" type="void" visibility="0x03" properties="0x00">
  9528. <documentation>/*! Helper macro for checking the local QS filter */</documentation>
  9529. <!--${QS-macros::QS_LOC_CHECK_::qs_id_}-->
  9530. <parameter name="qs_id_" type="uint8_t"/>
  9531. <code>\
  9532. (((uint_fast8_t)QS_priv_.locFilter[(uint_fast8_t)(qs_id_) &gt;&gt; 3U] \
  9533. &amp; ((uint_fast8_t)1U &lt;&lt; ((uint_fast8_t)(qs_id_) &amp; 7U))) != 0U)</code>
  9534. </operation>
  9535. <!--${QS-macros::QS_REC_DONE}-->
  9536. <operation name="QS_REC_DONE?ndef QS_REC_DONE" type="void" visibility="0x03" properties="0x00">
  9537. <documentation>/*! Macro to execute user code when a QS record is produced
  9538. *
  9539. * @note
  9540. * This is a dummy definition in case this macro is undefined.
  9541. */</documentation>
  9542. <code>((void)0)</code>
  9543. </operation>
  9544. <!--${QS-macros::QS_I8}-->
  9545. <operation name="QS_I8" type="void" visibility="0x03" properties="0x00">
  9546. <documentation>/*! Output formatted int8_t to the QS record */</documentation>
  9547. <!--${QS-macros::QS_I8::width_}-->
  9548. <parameter name="width_" type="uint8_t"/>
  9549. <!--${QS-macros::QS_I8::data_}-->
  9550. <parameter name="data_" type="int8_t"/>
  9551. <code>\
  9552. (QS_u8_fmt_((uint8_t)(((width_) &lt;&lt; 4U) &amp; 0x7U) | (uint8_t)QS_I8_ENUM_T, \
  9553. (data_)))</code>
  9554. </operation>
  9555. <!--${QS-macros::QS_U8}-->
  9556. <operation name="QS_U8" type="void" visibility="0x03" properties="0x00">
  9557. <documentation>/*! Output formatted uint8_t to the QS record */</documentation>
  9558. <!--${QS-macros::QS_U8::width_}-->
  9559. <parameter name="width_" type="uint8_t"/>
  9560. <!--${QS-macros::QS_U8::data_}-->
  9561. <parameter name="data_" type="std:u:int8_t"/>
  9562. <code>\
  9563. (QS_u8_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_U8_T, (data_)))</code>
  9564. </operation>
  9565. <!--${QS-macros::QS_I16}-->
  9566. <operation name="QS_I16" type="void" visibility="0x03" properties="0x00">
  9567. <documentation>/*! Output formatted int16_t to the QS record */</documentation>
  9568. <!--${QS-macros::QS_I16::width_}-->
  9569. <parameter name="width_" type="uint8_t"/>
  9570. <!--${QS-macros::QS_I16::data_}-->
  9571. <parameter name="data_" type="int16_t"/>
  9572. <code>\
  9573. (QS_u16_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_I16_T, (data_)))</code>
  9574. </operation>
  9575. <!--${QS-macros::QS_U16}-->
  9576. <operation name="QS_U16" type="void" visibility="0x03" properties="0x00">
  9577. <documentation>/*! Output formatted uint16_t to the QS record */</documentation>
  9578. <!--${QS-macros::QS_U16::width_}-->
  9579. <parameter name="width_" type="uint8_t"/>
  9580. <!--${QS-macros::QS_U16::data_}-->
  9581. <parameter name="data_" type="std:u:int16_t"/>
  9582. <code>\
  9583. (QS_u16_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_U16_T, (data_)))</code>
  9584. </operation>
  9585. <!--${QS-macros::QS_I32}-->
  9586. <operation name="QS_I32" type="void" visibility="0x03" properties="0x00">
  9587. <documentation>/*! Output formatted int32_t to the QS record */</documentation>
  9588. <!--${QS-macros::QS_I32::width_}-->
  9589. <parameter name="width_" type="uint8_t"/>
  9590. <!--${QS-macros::QS_I32::data_}-->
  9591. <parameter name="data_" type="int32_t"/>
  9592. <code>\
  9593. (QS_u32_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_I32_T, (data_)))</code>
  9594. </operation>
  9595. <!--${QS-macros::QS_U32}-->
  9596. <operation name="QS_U32" type="void" visibility="0x03" properties="0x00">
  9597. <documentation>/*! Output formatted uint32_t to the QS record */</documentation>
  9598. <!--${QS-macros::QS_U32::width_}-->
  9599. <parameter name="width_" type="uint8_t"/>
  9600. <!--${QS-macros::QS_U32::data_}-->
  9601. <parameter name="data_" type="std:u:int32_t"/>
  9602. <code>\
  9603. (QS_u32_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_U32_T, (data_)))</code>
  9604. </operation>
  9605. <!--${QS-macros::QS_I64}-->
  9606. <operation name="QS_I64" type="void" visibility="0x03" properties="0x00">
  9607. <documentation>/*! Output formatted int64_t to the QS record */</documentation>
  9608. <!--${QS-macros::QS_I64::width_}-->
  9609. <parameter name="width_" type="uint8_t"/>
  9610. <!--${QS-macros::QS_I64::data_}-->
  9611. <parameter name="data_" type="int64_t"/>
  9612. <code>\
  9613. (QS_u64_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_I64_T, (data_)))</code>
  9614. </operation>
  9615. <!--${QS-macros::QS_U64}-->
  9616. <operation name="QS_U64" type="void" visibility="0x03" properties="0x00">
  9617. <documentation>/*! Output formatted uint64_t to the QS record */</documentation>
  9618. <!--${QS-macros::QS_U64::width_}-->
  9619. <parameter name="width_" type="uint8_t"/>
  9620. <!--${QS-macros::QS_U64::data_}-->
  9621. <parameter name="data_" type="std:u:int64_t"/>
  9622. <code>\
  9623. (QS_u64_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_U64_T, (data_)))</code>
  9624. </operation>
  9625. <!--${QS-macros::QS_F32}-->
  9626. <operation name="QS_F32" type="void" visibility="0x03" properties="0x00">
  9627. <documentation>/*! Output formatted 32-bit floating point number to the QS record */</documentation>
  9628. <!--${QS-macros::QS_F32::width_}-->
  9629. <parameter name="width_" type="uint8_t"/>
  9630. <!--${QS-macros::QS_F32::data_}-->
  9631. <parameter name="data_" type="float32_t"/>
  9632. <code>\
  9633. (QS_f32_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_F32_T, (data_)))</code>
  9634. </operation>
  9635. <!--${QS-macros::QS_F64}-->
  9636. <operation name="QS_F64" type="void" visibility="0x03" properties="0x00">
  9637. <documentation>/*! Output formatted 64-bit floating point number to the QS record */</documentation>
  9638. <!--${QS-macros::QS_F64::width_}-->
  9639. <parameter name="width_" type="uint8_t"/>
  9640. <!--${QS-macros::QS_F64::data_}-->
  9641. <parameter name="data_" type="float64_t"/>
  9642. <code>\
  9643. (QS_f64_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | (uint8_t)QS_F64_T, (data_)))</code>
  9644. </operation>
  9645. <!--${QS-macros::QS_STR}-->
  9646. <operation name="QS_STR" type="void" visibility="0x03" properties="0x00">
  9647. <documentation>/*! Output formatted zero-terminated ASCII string to the QS record */</documentation>
  9648. <!--${QS-macros::QS_STR::str_}-->
  9649. <parameter name="str_" type="char const *"/>
  9650. <code>(QS_str_fmt_((str_)))</code>
  9651. </operation>
  9652. <!--${QS-macros::QS_MEM}-->
  9653. <operation name="QS_MEM" type="void" visibility="0x03" properties="0x00">
  9654. <documentation>/*! Output formatted memory block of up to 255 bytes to the QS record */</documentation>
  9655. <!--${QS-macros::QS_MEM::mem_}-->
  9656. <parameter name="mem_" type="void *"/>
  9657. <!--${QS-macros::QS_MEM::size_}-->
  9658. <parameter name="size_" type="std:u:int8_t"/>
  9659. <code>(QS_mem_fmt_((mem_), (size_)))</code>
  9660. </operation>
  9661. <!--${QS-macros::QS_ENUM}-->
  9662. <operation name="QS_ENUM" type="void" visibility="0x03" properties="0x00">
  9663. <documentation>/*! Output formatted enumeration to the QS record */</documentation>
  9664. <!--${QS-macros::QS_ENUM::group_}-->
  9665. <parameter name="group_" type="uint8_t const"/>
  9666. <!--${QS-macros::QS_ENUM::value_}-->
  9667. <parameter name="value_" type="enum_t const"/>
  9668. <code>\
  9669. (QS_u8_fmt_((uint8_t)(0x80U | ((group_) &lt;&lt; 4U)) | (uint8_t)QS_I8_ENUM_T,\
  9670. (uint8_t)(value_)))</code>
  9671. </operation>
  9672. <!--${QS-macros::QS_TIME_PRE_}-->
  9673. <operation name="QS_TIME_PRE_? (QS_TIME_SIZE == 4U)" type="void" visibility="0x03" properties="0x00">
  9674. <documentation>/*! Output time stamp to a QS record (used in predefined
  9675. * and application-specific trace records)
  9676. */</documentation>
  9677. <code>(QS_u32_raw_(QS_onGetTime()))</code>
  9678. </operation>
  9679. <!--${QS-macros::QS_TIME_PRE_}-->
  9680. <operation name="QS_TIME_PRE_? (QS_TIME_SIZE == 2U)" type="void" visibility="0x03" properties="0x00">
  9681. <code>(QS_u16_raw_(QS_onGetTime()))</code>
  9682. </operation>
  9683. <!--${QS-macros::QS_TIME_PRE_}-->
  9684. <operation name="QS_TIME_PRE_? (QS_TIME_SIZE == 1U)" type="void" visibility="0x03" properties="0x00">
  9685. <code>(QS_u8_raw_(QS_onGetTime()))</code>
  9686. </operation>
  9687. <!--${QS-macros::QS_OBJ}-->
  9688. <operation name="QS_OBJ? (QS_OBJ_PTR_SIZE == 4U)" type="void" visibility="0x03" properties="0x00">
  9689. <documentation>/*! Output formatted object pointer to the QS record */</documentation>
  9690. <!--${QS-macros::QS_OBJ::obj_}-->
  9691. <parameter name="obj_" type="void const *"/>
  9692. <code>(QS_u32_fmt_(QS_OBJ_T, (uint32_t)(obj_)))</code>
  9693. </operation>
  9694. <!--${QS-macros::QS_OBJ}-->
  9695. <operation name="QS_OBJ? (QS_OBJ_PTR_SIZE == 2U)" type="void" visibility="0x03" properties="0x00">
  9696. <!--${QS-macros::QS_OBJ::obj_}-->
  9697. <parameter name="obj_" type="void const *"/>
  9698. <code>(QS_u16_fmt_(QS_OBJ_T, (uint16_t)(obj_)))</code>
  9699. </operation>
  9700. <!--${QS-macros::QS_OBJ}-->
  9701. <operation name="QS_OBJ? (QS_OBJ_PTR_SIZE == 1U)" type="void" visibility="0x03" properties="0x00">
  9702. <!--${QS-macros::QS_OBJ::obj_}-->
  9703. <parameter name="obj_" type="void const *"/>
  9704. <code>(QS_u8_fmt_(QS_OBJ_T, (uint8_t)(obj_)))</code>
  9705. </operation>
  9706. <!--${QS-macros::QS_OBJ}-->
  9707. <operation name="QS_OBJ? (QS_OBJ_PTR_SIZE == 8U)" type="void" visibility="0x03" properties="0x00">
  9708. <!--${QS-macros::QS_OBJ::obj_}-->
  9709. <parameter name="obj_" type="void const *"/>
  9710. <code>(QS_u64_fmt_(QS_OBJ_T, (uint64_t)(obj_)))</code>
  9711. </operation>
  9712. <!--${QS-macros::QS_FUN}-->
  9713. <operation name="QS_FUN? (QS_FUN_PTR_SIZE == 4U)" type="void" visibility="0x03" properties="0x00">
  9714. <documentation>/* Output formatted function pointer to the QS record */</documentation>
  9715. <!--${QS-macros::QS_FUN::fun_}-->
  9716. <parameter name="fun_" type="QSpyFunPtr"/>
  9717. <code>(QS_u32_fmt_(QS_FUN_T, (uint32_t)(fun_)))</code>
  9718. </operation>
  9719. <!--${QS-macros::QS_FUN}-->
  9720. <operation name="QS_FUN? (QS_FUN_PTR_SIZE == 2U)" type="void" visibility="0x03" properties="0x00">
  9721. <!--${QS-macros::QS_FUN::fun_}-->
  9722. <parameter name="fun_" type="QSpyFunPtr"/>
  9723. <code>(QS_u16_fmt_(QS_FUN_T, (uint16_t)(fun_)))</code>
  9724. </operation>
  9725. <!--${QS-macros::QS_FUN}-->
  9726. <operation name="QS_FUN? (QS_FUN_PTR_SIZE == 1U)" type="void" visibility="0x03" properties="0x00">
  9727. <!--${QS-macros::QS_FUN::fun_}-->
  9728. <parameter name="fun_" type="QSpyFunPtr"/>
  9729. <code>(QS_u8_fmt_(QS_FUN_T, (uint8_t)(fun_)))</code>
  9730. </operation>
  9731. <!--${QS-macros::QS_FUN}-->
  9732. <operation name="QS_FUN? (QS_FUN_PTR_SIZE == 8U)" type="void" visibility="0x03" properties="0x00">
  9733. <!--${QS-macros::QS_FUN::fun_}-->
  9734. <parameter name="fun_" type="QSpyFunPtr"/>
  9735. <code>(QS_u64_fmt_(QS_FUN_T, (uint64_t)(fun_)))</code>
  9736. </operation>
  9737. <!--${QS-macros::QS_SIG}-->
  9738. <operation name="QS_SIG? (Q_SIGNAL_SIZE == 4U)" type="void" visibility="0x03" properties="0x00">
  9739. <documentation>/*! Output formatted event signal (of type ::QSignal) and
  9740. * the state machine object to the user QS record
  9741. */</documentation>
  9742. <!--${QS-macros::QS_SIG::sig_}-->
  9743. <parameter name="sig_" type="QSignal"/>
  9744. <!--${QS-macros::QS_SIG::obj_}-->
  9745. <parameter name="obj_" type="void const *"/>
  9746. <code>\
  9747. QS_u32_fmt_(QS_SIG_T, (sig_)); \
  9748. QS_obj_raw_(obj_)</code>
  9749. </operation>
  9750. <!--${QS-macros::QS_SIG}-->
  9751. <operation name="QS_SIG? (Q_SIGNAL_SIZE == 2U)" type="void" visibility="0x03" properties="0x00">
  9752. <!--${QS-macros::QS_SIG::sig_}-->
  9753. <parameter name="sig_" type="QSignal"/>
  9754. <!--${QS-macros::QS_SIG::obj_}-->
  9755. <parameter name="obj_" type="void const *"/>
  9756. <code>\
  9757. QS_u16_fmt_(QS_SIG_T, (sig_)); \
  9758. QS_obj_raw_(obj_)</code>
  9759. </operation>
  9760. <!--${QS-macros::QS_SIG}-->
  9761. <operation name="QS_SIG? (Q_SIGNAL_SIZE == 1U)" type="void" visibility="0x03" properties="0x00">
  9762. <!--${QS-macros::QS_SIG::sig_}-->
  9763. <parameter name="sig_" type="QSignal"/>
  9764. <!--${QS-macros::QS_SIG::obj_}-->
  9765. <parameter name="obj_" type="void const *"/>
  9766. <code>\
  9767. QS_u8_fmt_(QS_SIG_T, (sig_)); \
  9768. QS_obj_raw_(obj_)</code>
  9769. </operation>
  9770. <!--${QS-macros::QS_SIG_DICTIONARY}-->
  9771. <operation name="QS_SIG_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9772. <documentation>/*! Output QS signal dictionary record
  9773. *
  9774. * @details
  9775. * A signal dictionary record associates the numerical value of the signal
  9776. * and the binary address of the state machine that consumes that signal
  9777. * with the human-readable name of the signal.
  9778. *
  9779. * @param[in] sig_ event signal (typically enumerated, e.g. `TIMEOUT_SIG`)
  9780. * @param[in] obj_ pointer to the associated state machine object
  9781. * (might be `(void*)0` for globally recognized signals)
  9782. *
  9783. * A signal dictionary entry is associated with both the signal value `sig_`
  9784. * and the state machine `obj_`, because signals are required to be unique
  9785. * only within a given state machine and therefore the same numerical values
  9786. * can represent different signals in different state machines.
  9787. *
  9788. * For the &quot;global&quot; signals that have the same meaning in many state machines
  9789. * (such as globally published signals), you can specify a signal dictionary
  9790. * entry with the `obj_` parameter set to `(void*)0`.
  9791. *
  9792. * The following example shows the definition of signal dictionary entries
  9793. * in the initial transition of the Table active object. Please note that
  9794. * signals HUNGRY_SIG and DONE_SIG are associated with the Table state
  9795. * machine only (&quot;me&quot; `obj_` pointer). The EAT_SIG signal, on the other
  9796. * hand, is global (0 `obj_` pointer):
  9797. * @include qs_sigDic.c
  9798. *
  9799. * The following QSpy log example shows the signal dictionary records
  9800. * generated from the Table initial transition and subsequent records that
  9801. * show human-readable names of the signals:
  9802. * @include qs_sigLog.txt
  9803. */</documentation>
  9804. <!--${QS-macros::QS_SIG_DICTIONAR~::sig_}-->
  9805. <parameter name="sig_" type="QSignal"/>
  9806. <!--${QS-macros::QS_SIG_DICTIONAR~::obj_}-->
  9807. <parameter name="obj_" type="void const *"/>
  9808. <code>\
  9809. (QS_sig_dict_pre_((sig_), (obj_), #sig_))</code>
  9810. </operation>
  9811. <!--${QS-macros::QS_OBJ_DICTIONARY}-->
  9812. <operation name="QS_OBJ_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9813. <documentation>/*! Output object dictionary record
  9814. *
  9815. * @details
  9816. * An object dictionary record associates the binary address of an object
  9817. * in the target's memory with the human-readable name of the object.
  9818. *
  9819. * @param[in] obj_ pointer to the object (any object)
  9820. *
  9821. * The following example shows the definition of object dictionary entry
  9822. * for the Table active object:
  9823. * @include qs_objDic.c
  9824. */</documentation>
  9825. <!--${QS-macros::QS_OBJ_DICTIONAR~::obj_}-->
  9826. <parameter name="obj_" type="void const *"/>
  9827. <code>\
  9828. (QS_obj_dict_pre_((obj_), #obj_))</code>
  9829. </operation>
  9830. <!--${QS-macros::QS_OBJ_ARR_DICTIONARY}-->
  9831. <operation name="QS_OBJ_ARR_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9832. <documentation>/*! Output object-array dictionary record
  9833. *
  9834. * @details
  9835. * An object array dictionary record associates the binary address of the
  9836. * object element in the target's memory with the human-readable name
  9837. * of the object.
  9838. *
  9839. * @param[in] obj_ pointer to the object (any object)
  9840. * @param[in] idx_ array index
  9841. *
  9842. * The following example shows the definition of object array dictionary
  9843. * for `Philo::inst[n]` and `Philo::inst[n].m_timeEvt`:
  9844. * @include qs_objArrDic.c
  9845. */</documentation>
  9846. <!--${QS-macros::QS_OBJ_ARR_DICTI~::obj_}-->
  9847. <parameter name="obj_" type="void const *"/>
  9848. <!--${QS-macros::QS_OBJ_ARR_DICTI~::idx_}-->
  9849. <parameter name="idx_" type="unsigned"/>
  9850. <code>\
  9851. (QS_obj_arr_dict_pre_((obj_), (idx_), #obj_))</code>
  9852. </operation>
  9853. <!--${QS-macros::QS_FUN_DICTIONARY}-->
  9854. <operation name="QS_FUN_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9855. <documentation>/*! Output function dictionary record
  9856. *
  9857. * @details
  9858. * A function dictionary record associates the binary address of a function
  9859. * in the target's memory with the human-readable name of the function.
  9860. *
  9861. * Providing a function dictionary QS record can vastly improve readability
  9862. * of the QS log, because instead of dealing with cryptic machine addresses
  9863. * the QSpy host utility can display human-readable function names.
  9864. *
  9865. * The example from #QS_SIG_DICTIONARY shows the definition of a function
  9866. * dictionary.
  9867. */</documentation>
  9868. <!--${QS-macros::QS_FUN_DICTIONAR~::fun_}-->
  9869. <parameter name="fun_" type="QSpyFunPtr"/>
  9870. <code>\
  9871. (QS_fun_dict_pre_((void (*)(void))(fun_), #fun_))</code>
  9872. </operation>
  9873. <!--${QS-macros::QS_USR_DICTIONARY}-->
  9874. <operation name="QS_USR_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9875. <documentation>/*! Output user QS record dictionary record
  9876. *
  9877. * @details
  9878. * A user QS record dictionary record associates the numerical value of a
  9879. * user record with the human-readable identifier.
  9880. */</documentation>
  9881. <!--${QS-macros::QS_USR_DICTIONAR~::rec_}-->
  9882. <parameter name="rec_" type="unit8_t"/>
  9883. <code>\
  9884. (QS_usr_dict_pre_((rec_), #rec_))</code>
  9885. </operation>
  9886. <!--${QS-macros::QS_ENUM_DICTIONARY}-->
  9887. <operation name="QS_ENUM_DICTIONARY" type="void" visibility="0x03" properties="0x00">
  9888. <documentation>/*! Output enumeration dictionary record
  9889. *
  9890. * @details
  9891. * An enum QS record dictionary record associates the numerical value of
  9892. * an enumeration with the human-readable identifier.
  9893. */</documentation>
  9894. <!--${QS-macros::QS_ENUM_DICTIONA~::value_}-->
  9895. <parameter name="value_" type="enum_t const"/>
  9896. <!--${QS-macros::QS_ENUM_DICTIONA~::group_}-->
  9897. <parameter name="group_" type="uint8_t const"/>
  9898. <code>\
  9899. (QS_enum_dict_pre_((value_), (group_), #value_))</code>
  9900. </operation>
  9901. <!--${QS-macros::QF_QS_CRIT_ENTRY}-->
  9902. <operation name="QF_QS_CRIT_ENTRY" type="void" visibility="0x00" properties="0x00">
  9903. <documentation>/*! Output the critical section entry record */</documentation>
  9904. </operation>
  9905. <!--${QS-macros::QF_QS_CRIT_EXIT}-->
  9906. <operation name="QF_QS_CRIT_EXIT" type="void" visibility="0x00" properties="0x00">
  9907. <documentation>/*! Output the critical section exit record */</documentation>
  9908. </operation>
  9909. <!--${QS-macros::QF_QS_ISR_ENTRY}-->
  9910. <operation name="QF_QS_ISR_ENTRY" type="void" visibility="0x00" properties="0x00">
  9911. <documentation>/*! Output the interrupt entry record *//*! Output the ISR entry */</documentation>
  9912. <!--${QS-macros::QF_QS_ISR_ENTRY::isrnest}-->
  9913. <parameter name="isrnest" type="uint_fast8_t const"/>
  9914. <!--${QS-macros::QF_QS_ISR_ENTRY::prio_}-->
  9915. <parameter name="prio_" type="uint_fast8_t const"/>
  9916. <code>QS_BEGIN_NOCRIT_PRE_(QS_QF_ISR_ENTRY, 0U)
  9917. QS_TIME_PRE_();
  9918. QS_2u8_raw_(isrnest, prio);
  9919. QS_END_NOCRIT_PRE_()</code>
  9920. </operation>
  9921. <!--${QS-macros::QF_QS_ISR_EXIT}-->
  9922. <operation name="QF_QS_ISR_EXIT" type="void" visibility="0x00" properties="0x00">
  9923. <documentation>/*! Output the ISR exit trace record */</documentation>
  9924. <!--${QS-macros::QF_QS_ISR_EXIT::isrnest}-->
  9925. <parameter name="isrnest" type="uint_fast8_t"/>
  9926. <!--${QS-macros::QF_QS_ISR_EXIT::prio}-->
  9927. <parameter name="prio" type="uint_fast8_t"/>
  9928. <code>QS_BEGIN_NOCRIT_PRE_(QS_QF_ISR_EXIT, 0U)
  9929. QS_TIME_PRE_();
  9930. QS_2u8_raw_(isrnest, prio);
  9931. QS_END_NOCRIT_PRE_()</code>
  9932. </operation>
  9933. <!--${QS-macros::QF_QS_ACTION}-->
  9934. <operation name="QF_QS_ACTION" type="void" visibility="0x03" properties="0x00">
  9935. <documentation>/*! Execute an action that is only necessary for QS output */</documentation>
  9936. <!--${QS-macros::QF_QS_ACTION::act_}-->
  9937. <parameter name="act_" type="&lt;action code&gt;"/>
  9938. <code>(act_)</code>
  9939. </operation>
  9940. <!--${QS-macros::QS_EOD}-->
  9941. <attribute name="QS_EOD" type="uint16_t" visibility="0x03" properties="0x00">
  9942. <documentation>/*! Constant representing End-Of-Data condition returned from the
  9943. * QS_getByte() function.
  9944. */</documentation>
  9945. <code>((uint16_t)0xFFFFU)</code>
  9946. </attribute>
  9947. <!--${QS-macros::QS_CMD}-->
  9948. <attribute name="QS_CMD" type="uint8_t" visibility="0x03" properties="0x00">
  9949. <documentation>/*! Constant representing command enumeration group
  9950. * in QS_ENUM_DICTIONARY() and QS_ENUM()
  9951. * @sa QS_onCommand()
  9952. */</documentation>
  9953. <code>((uint8_t)7U)</code>
  9954. </attribute>
  9955. <!--${QS-macros::QS_HEX_FMT}-->
  9956. <attribute name="QS_HEX_FMT" type="uint8_t" visibility="0x03" properties="0x00">
  9957. <documentation>/*! Constant representing HEX format for the &quot;width&quot; filed
  9958. * in QS_U8(), QS_U16(), QS_U32(), and QS_U64().
  9959. */</documentation>
  9960. <code>((uint8_t)0x0FU)</code>
  9961. </attribute>
  9962. </package>
  9963. <!--${QS}-->
  9964. <package name="QS" stereotype="0x05">
  9965. <!--${QS::QSCtr}-->
  9966. <attribute name="QSCtr? (QS_CTR_SIZE == 2U)" type="typedef uint_fast16_t" visibility="0x04" properties="0x00">
  9967. <documentation>/*! QS ring buffer counter and offset type */</documentation>
  9968. </attribute>
  9969. <!--${QS::QSCtr}-->
  9970. <attribute name="QSCtr? (QS_CTR_SIZE == 4U)" type="typedef uint_fast32_t" visibility="0x04" properties="0x00"/>
  9971. <!--${QS::QSTimeCtr}-->
  9972. <attribute name="QSTimeCtr? (QS_TIME_SIZE == 4U)" type="typedef uint32_t" visibility="0x04" properties="0x00">
  9973. <documentation>/*! QS time stamp type, which determines the dynamic range of QS time stamps */</documentation>
  9974. </attribute>
  9975. <!--${QS::QSTimeCtr}-->
  9976. <attribute name="QSTimeCtr? (QS_TIME_SIZE == 2U)" type="typedef uint16_t" visibility="0x04" properties="0x00"/>
  9977. <!--${QS::QSTimeCtr}-->
  9978. <attribute name="QSTimeCtr? (QS_TIME_SIZE == 1U)" type="typedef uint8_t" visibility="0x04" properties="0x00"/>
  9979. <!--${QS::QSFun}-->
  9980. <attribute name="QSFun? (QS_FUN_PTR_SIZE == 4U)" type="typedef uint32_t" visibility="0x04" properties="0x00">
  9981. <documentation>/*! QS function pointer type (for serializing function pointers) */</documentation>
  9982. </attribute>
  9983. <!--${QS::QSFun}-->
  9984. <attribute name="QSFun? (QS_FUN_PTR_SIZE == 8U)" type="typedef uint64_t" visibility="0x04" properties="0x00"/>
  9985. <!--${QS::QSFun}-->
  9986. <attribute name="QSFun? (QS_FUN_PTR_SIZE == 2U)" type="typedef uint16_t" visibility="0x04" properties="0x00"/>
  9987. <!--${QS::QSFun}-->
  9988. <attribute name="QSFun? (QS_FUN_PTR_SIZE == 1U)" type="typedef uint8_t" visibility="0x04" properties="0x00"/>
  9989. <!--${QS::QSpyPre}-->
  9990. <attribute name="QSpyPre" type="enum" visibility="0x04" properties="0x00">
  9991. <documentation>/*! QS pre-defined record types (TX channel)
  9992. * @static @public @memberof QS
  9993. *
  9994. * @details
  9995. * This enumeration specifies the record types used in the QP components.
  9996. * You can specify your own record types starting from ::QS_USER offset.
  9997. * Currently, the maximum of all records cannot exceed 125.
  9998. *
  9999. * @note
  10000. * The QS records labeled as &quot;not maskable&quot; are always enabled and cannot
  10001. * be turend off with the QS_GLB_FILTER() macro. Other QS trace records
  10002. * can be disabled by means of the &quot;global filters&quot;
  10003. *
  10004. * @sa QS_GLB_FILTER() macro
  10005. */</documentation>
  10006. <code>{
  10007. /* [0] QS session (not maskable) */
  10008. QS_EMPTY, /*!&lt; QS record for cleanly starting a session */
  10009. /* [1] SM records */
  10010. QS_QEP_STATE_ENTRY, /*!&lt; a state was entered */
  10011. QS_QEP_STATE_EXIT, /*!&lt; a state was exited */
  10012. QS_QEP_STATE_INIT, /*!&lt; an initial transition was taken in a state */
  10013. QS_QEP_INIT_TRAN, /*!&lt; the top-most initial transition was taken */
  10014. QS_QEP_INTERN_TRAN, /*!&lt; an internal transition was taken */
  10015. QS_QEP_TRAN, /*!&lt; a regular transition was taken */
  10016. QS_QEP_IGNORED, /*!&lt; an event was ignored (silently discarded) */
  10017. QS_QEP_DISPATCH, /*!&lt; an event was dispatched (begin of RTC step) */
  10018. QS_QEP_UNHANDLED, /*!&lt; an event was un-handled due to a guard */
  10019. /* [10] Active Object (AO) records */
  10020. QS_QF_ACTIVE_DEFER, /*!&lt; AO deferred an event */
  10021. QS_QF_ACTIVE_RECALL, /*!&lt; AO recalled an event */
  10022. QS_QF_ACTIVE_SUBSCRIBE, /*!&lt; an AO subscribed to an event */
  10023. QS_QF_ACTIVE_UNSUBSCRIBE, /*!&lt; an AO unsubscribed to an event */
  10024. QS_QF_ACTIVE_POST, /*!&lt; an event was posted (FIFO) directly to AO */
  10025. QS_QF_ACTIVE_POST_LIFO, /*!&lt; an event was posted (LIFO) directly to AO */
  10026. QS_QF_ACTIVE_GET, /*!&lt; AO got an event and its queue is not empty */
  10027. QS_QF_ACTIVE_GET_LAST,/*!&lt; AO got an event and its queue is empty */
  10028. QS_QF_ACTIVE_RECALL_ATTEMPT, /*!&lt; AO attempted to recall an event */
  10029. /* [19] Event Queue (EQ) records */
  10030. QS_QF_EQUEUE_POST, /*!&lt; an event was posted (FIFO) to a raw queue */
  10031. QS_QF_EQUEUE_POST_LIFO, /*!&lt; an event was posted (LIFO) to a raw queue */
  10032. QS_QF_EQUEUE_GET, /*!&lt; get an event and queue still not empty */
  10033. QS_QF_EQUEUE_GET_LAST,/*!&lt; get the last event from the queue */
  10034. /* [23] Framework (QF) records */
  10035. QS_QF_NEW_ATTEMPT, /*!&lt; an attempt to allocate an event failed */
  10036. /* [24] Memory Pool (MP) records */
  10037. QS_QF_MPOOL_GET, /*!&lt; a memory block was removed from memory pool */
  10038. QS_QF_MPOOL_PUT, /*!&lt; a memory block was returned to memory pool */
  10039. /* [26] Additional Framework (QF) records */
  10040. QS_QF_PUBLISH, /*!&lt; an event was published to active objects */
  10041. QS_QF_NEW_REF, /*!&lt; new event reference was created */
  10042. QS_QF_NEW, /*!&lt; new event was created */
  10043. QS_QF_GC_ATTEMPT, /*!&lt; garbage collection attempt */
  10044. QS_QF_GC, /*!&lt; garbage collection */
  10045. QS_QF_TICK, /*!&lt; QTimeEvt_tick_() was called */
  10046. /* [32] Time Event (TE) records */
  10047. QS_QF_TIMEEVT_ARM, /*!&lt; a time event was armed */
  10048. QS_QF_TIMEEVT_AUTO_DISARM, /*!&lt; a time event expired and was disarmed */
  10049. QS_QF_TIMEEVT_DISARM_ATTEMPT,/*!&lt; attempt to disarm a disarmed QTimeEvt */
  10050. QS_QF_TIMEEVT_DISARM, /*!&lt; true disarming of an armed time event */
  10051. QS_QF_TIMEEVT_REARM, /*!&lt; rearming of a time event */
  10052. QS_QF_TIMEEVT_POST, /*!&lt; a time event posted itself directly to an AO */
  10053. /* [38] Additional Framework (QF) records */
  10054. QS_QF_DELETE_REF, /*!&lt; an event reference is about to be deleted */
  10055. QS_QF_CRIT_ENTRY, /*!&lt; critical section was entered */
  10056. QS_QF_CRIT_EXIT, /*!&lt; critical section was exited */
  10057. QS_QF_ISR_ENTRY, /*!&lt; an ISR was entered */
  10058. QS_QF_ISR_EXIT, /*!&lt; an ISR was exited */
  10059. QS_QF_INT_DISABLE, /*!&lt; interrupts were disabled */
  10060. QS_QF_INT_ENABLE, /*!&lt; interrupts were enabled */
  10061. /* [45] Additional Active Object (AO) records */
  10062. QS_QF_ACTIVE_POST_ATTEMPT,/*!&lt; attempt to post an evt to AO failed */
  10063. /* [46] Additional Event Queue (EQ) records */
  10064. QS_QF_EQUEUE_POST_ATTEMPT,/*!&lt; attempt to post evt to QEQueue failed */
  10065. /* [47] Additional Memory Pool (MP) records */
  10066. QS_QF_MPOOL_GET_ATTEMPT, /*!&lt; attempt to get a memory block failed */
  10067. /* [48] Scheduler (SC) records */
  10068. QS_SCHED_PREEMPT, /*!&lt; scheduler asynchronously preempted a task */
  10069. QS_SCHED_RESTORE, /*!&lt; scheduler restored preempted task */
  10070. QS_SCHED_LOCK, /*!&lt; scheduler was locked */
  10071. QS_SCHED_UNLOCK, /*!&lt; scheduler was unlocked */
  10072. QS_SCHED_NEXT, /*!&lt; scheduler started new task */
  10073. QS_SCHED_IDLE, /*!&lt; scheduler restored the idle task */
  10074. /* [54] Miscellaneous QS records (not maskable) */
  10075. QS_ENUM_DICT, /*!&lt; enumeration dictionary entry */
  10076. /* [55] Additional QEP records */
  10077. QS_QEP_TRAN_HIST, /*!&lt; a tran to history was taken */
  10078. QS_QEP_TRAN_EP, /*!&lt; a tran to entry point into a submachine */
  10079. QS_QEP_TRAN_XP, /*!&lt; a tran to exit point out of a submachine */
  10080. /* [58] Miscellaneous QS records (not maskable) */
  10081. QS_TEST_PAUSED, /*!&lt; test has been paused */
  10082. QS_TEST_PROBE_GET, /*!&lt; reports that Test-Probe has been used */
  10083. QS_SIG_DICT, /*!&lt; signal dictionary entry */
  10084. QS_OBJ_DICT, /*!&lt; object dictionary entry */
  10085. QS_FUN_DICT, /*!&lt; function dictionary entry */
  10086. QS_USR_DICT, /*!&lt; user QS record dictionary entry */
  10087. QS_TARGET_INFO, /*!&lt; reports the Target information */
  10088. QS_TARGET_DONE, /*!&lt; reports completion of a user callback */
  10089. QS_RX_STATUS, /*!&lt; reports QS data receive status */
  10090. QS_QUERY_DATA, /*!&lt; reports the data from &quot;current object&quot; query */
  10091. QS_PEEK_DATA, /*!&lt; reports the data from the PEEK query */
  10092. QS_ASSERT_FAIL, /*!&lt; assertion failed in the code */
  10093. QS_QF_RUN, /*!&lt; QF_run() was entered */
  10094. /* [71] Semaphore (SEM) records */
  10095. QS_SEM_TAKE, /*!&lt; a semaphore was taken by a thread */
  10096. QS_SEM_BLOCK, /*!&lt; a semaphore blocked a thread */
  10097. QS_SEM_SIGNAL, /*!&lt; a semaphore was signaled */
  10098. QS_SEM_BLOCK_ATTEMPT, /*!&lt; a semaphore blocked was attempted */
  10099. /* [75] Mutex (MTX) records */
  10100. QS_MTX_LOCK, /*!&lt; a mutex was locked */
  10101. QS_MTX_BLOCK, /*!&lt; a mutex blocked a thread */
  10102. QS_MTX_UNLOCK, /*!&lt; a mutex was unlocked */
  10103. QS_MTX_LOCK_ATTEMPT, /*!&lt; a mutex lock was attempted */
  10104. QS_MTX_BLOCK_ATTEMPT, /*!&lt; a mutex blocking was attempted */
  10105. QS_MTX_UNLOCK_ATTEMPT,/*!&lt; a mutex unlock was attempted */
  10106. /* [81] */
  10107. QS_PRE_MAX /*!&lt; the number of predefined signals */
  10108. };</code>
  10109. </attribute>
  10110. <!--${QS::QSpyGroups}-->
  10111. <attribute name="QSpyGroups" type="enum" visibility="0x04" properties="0x00">
  10112. <documentation>/*! QS record groups for QS_GLB_FILTER()
  10113. * @static @public @memberof QS
  10114. */</documentation>
  10115. <code>{
  10116. QS_ALL_RECORDS = 0xF0,/*!&lt; all maskable QS records */
  10117. QS_SM_RECORDS, /*!&lt; State Machine QS records */
  10118. QS_AO_RECORDS, /*!&lt; Active Object QS records */
  10119. QS_EQ_RECORDS, /*!&lt; Event Queues QS records */
  10120. QS_MP_RECORDS, /*!&lt; Memory Pools QS records */
  10121. QS_TE_RECORDS, /*!&lt; Time Events QS records */
  10122. QS_QF_RECORDS, /*!&lt; QF QS records */
  10123. QS_SC_RECORDS, /*!&lt; Scheduler QS records */
  10124. QS_SEM_RECORDS, /*!&lt; Semaphore QS records */
  10125. QS_MTX_RECORDS, /*!&lt; Mutex QS records */
  10126. QS_U0_RECORDS, /*!&lt; User Group 100-104 records */
  10127. QS_U1_RECORDS, /*!&lt; User Group 105-109 records */
  10128. QS_U2_RECORDS, /*!&lt; User Group 110-114 records */
  10129. QS_U3_RECORDS, /*!&lt; User Group 115-119 records */
  10130. QS_U4_RECORDS, /*!&lt; User Group 120-124 records */
  10131. QS_UA_RECORDS /*!&lt; All User records */
  10132. };</code>
  10133. </attribute>
  10134. <!--${QS::QSpyUserOffsets}-->
  10135. <attribute name="QSpyUserOffsets" type="enum" visibility="0x04" properties="0x00">
  10136. <documentation>/*! QS user record group offsets for QS_GLB_FILTER()
  10137. * @static @public @memberof QS
  10138. */</documentation>
  10139. <code>{
  10140. QS_USER = 100, /*!&lt; the first record available to QS users */
  10141. QS_USER0 = (enum_t)QS_USER, /*!&lt; offset for User Group 0 */
  10142. QS_USER1 = (enum_t)QS_USER0 + 5, /*!&lt; offset for User Group 1 */
  10143. QS_USER2 = (enum_t)QS_USER1 + 5, /*!&lt; offset for User Group 2 */
  10144. QS_USER3 = (enum_t)QS_USER2 + 5, /*!&lt; offset for User Group 3 */
  10145. QS_USER4 = (enum_t)QS_USER3 + 5 /*!&lt; offset for User Group 4 */
  10146. };</code>
  10147. </attribute>
  10148. <!--${QS::QSpyIdOffsets}-->
  10149. <attribute name="QSpyIdOffsets" type="enum" visibility="0x04" properties="0x00">
  10150. <documentation>/*! QS ID offsets for QS_LOC_FILTER()
  10151. * @static @public @memberof QS
  10152. */</documentation>
  10153. <code>{
  10154. QS_AO_ID = 0, /*!&lt; offset for AO priorities */
  10155. QS_EP_ID = 64, /*!&lt; offset for event-pool IDs */
  10156. QS_EQ_ID = 80, /*!&lt; offset for event-queue IDs */
  10157. QS_AP_ID = 96 /*!&lt; offset for Application-specific IDs */
  10158. };</code>
  10159. </attribute>
  10160. <!--${QS::QSpyIdGroups}-->
  10161. <attribute name="QSpyIdGroups" type="enum" visibility="0x04" properties="0x00">
  10162. <documentation>/*! QS ID groups for QS_LOC_FILTER()
  10163. * @static @public @memberof QS
  10164. */</documentation>
  10165. <code>{
  10166. QS_ALL_IDS = 0xF0, /*!&lt; all QS IDs */
  10167. QS_AO_IDS = (0x80 + (enum_t)QS_AO_ID), /*!&lt; AO IDs (priorities) */
  10168. QS_EP_IDS = (0x80 + (enum_t)QS_EP_ID), /*!&lt; event-pool IDs */
  10169. QS_EQ_IDS = (0x80 + (enum_t)QS_EQ_ID), /*!&lt; event-queue IDs */
  10170. QS_AP_IDS = (0x80 + (enum_t)QS_AP_ID) /*!&lt; Application-specific IDs */
  10171. };</code>
  10172. </attribute>
  10173. <!--${QS::QSpyFunPtr}-->
  10174. <attribute name="QSpyFunPtr" type="typedef void (*" visibility="0x04" properties="0x01">
  10175. <documentation>/*! function pointer type for QS_fun_dict_pre_()
  10176. * @static @private @memberof QS
  10177. */</documentation>
  10178. <code>)(void);</code>
  10179. </attribute>
  10180. <!--${QS::QSpyId}-->
  10181. <attribute name="QSpyId" type="typedef struct { uint8_t prio; }" visibility="0x04" properties="0x00">
  10182. <documentation>/*! @brief QS ID type for applying local filtering
  10183. * @static @public @memberof QS
  10184. */</documentation>
  10185. </attribute>
  10186. <!--${QS::QS-tx}-->
  10187. <package name="QS-tx" stereotype="0x02" namespace="QS_">
  10188. <!--${QS::QS-tx::tx}-->
  10189. <class name="tx">
  10190. <documentation>/*! @brief Software tracing, output (QS-TX)
  10191. * @class QS
  10192. *
  10193. * @details
  10194. * This class groups together QS services.
  10195. */</documentation>
  10196. <!--${QS::QS-tx::tx::glbFilter[16]}-->
  10197. <attribute name="glbFilter[16]" type="uint8_t" visibility="0x00" properties="0x00">
  10198. <documentation>/*! global on/off QS filter */</documentation>
  10199. </attribute>
  10200. <!--${QS::QS-tx::tx::locFilter[16]}-->
  10201. <attribute name="locFilter[16]" type="uint8_t" visibility="0x00" properties="0x00">
  10202. <documentation>/*! local on/off QS filter */</documentation>
  10203. </attribute>
  10204. <!--${QS::QS-tx::tx::locFilter_AP}-->
  10205. <attribute name="locFilter_AP" type="void const *" visibility="0x00" properties="0x00">
  10206. <documentation>/*! @deprecated old local QS filter */</documentation>
  10207. </attribute>
  10208. <!--${QS::QS-tx::tx::buf}-->
  10209. <attribute name="buf" type="uint8_t *" visibility="0x00" properties="0x00">
  10210. <documentation>/*! pointer to the start of the QS-TX ring buffer */</documentation>
  10211. </attribute>
  10212. <!--${QS::QS-tx::tx::end}-->
  10213. <attribute name="end" type="QSCtr" visibility="0x00" properties="0x00">
  10214. <documentation>/*! offset of the end of the ring buffer */</documentation>
  10215. </attribute>
  10216. <!--${QS::QS-tx::tx::head}-->
  10217. <attribute name="head" type="QSCtr volatile" visibility="0x00" properties="0x00">
  10218. <documentation>/*! offset to where next byte will be inserted */</documentation>
  10219. </attribute>
  10220. <!--${QS::QS-tx::tx::tail}-->
  10221. <attribute name="tail" type="QSCtr volatile" visibility="0x00" properties="0x00">
  10222. <documentation>/*! offset of where next record will be extracted */</documentation>
  10223. </attribute>
  10224. <!--${QS::QS-tx::tx::used}-->
  10225. <attribute name="used" type="QSCtr volatile" visibility="0x00" properties="0x00">
  10226. <documentation>/*! number of bytes currently in the ring buffer */</documentation>
  10227. </attribute>
  10228. <!--${QS::QS-tx::tx::seq}-->
  10229. <attribute name="seq" type="uint8_t volatile" visibility="0x00" properties="0x00">
  10230. <documentation>/*! sequence number of the last inserted QS record */</documentation>
  10231. </attribute>
  10232. <!--${QS::QS-tx::tx::chksum}-->
  10233. <attribute name="chksum" type="uint8_t volatile" visibility="0x00" properties="0x00">
  10234. <documentation>/*! checksum of the currently inserted record */</documentation>
  10235. </attribute>
  10236. <!--${QS::QS-tx::tx::critNest}-->
  10237. <attribute name="critNest" type="uint8_t volatile" visibility="0x00" properties="0x00">
  10238. <documentation>/*! critical section nesting level */</documentation>
  10239. </attribute>
  10240. <!--${QS::QS-tx::tx::flags}-->
  10241. <attribute name="flags" type="uint8_t" visibility="0x00" properties="0x00">
  10242. <documentation>/* flags for internal use */</documentation>
  10243. </attribute>
  10244. </class>
  10245. <!--${QS::QS-tx::preType}-->
  10246. <attribute name="preType" type="enum" visibility="0x04" properties="0x01">
  10247. <documentation>/*! Enumerates data elements for app-specific trace records */</documentation>
  10248. <code>{
  10249. QS_I8_ENUM_T, /*!&lt; signed 8-bit integer or enum format */
  10250. QS_U8_T, /*!&lt; unsigned 8-bit integer format */
  10251. QS_I16_T, /*!&lt; signed 16-bit integer format */
  10252. QS_U16_T, /*!&lt; unsigned 16-bit integer format */
  10253. QS_I32_T, /*!&lt; signed 32-bit integer format */
  10254. QS_U32_T, /*!&lt; unsigned 32-bit integer format */
  10255. QS_F32_T, /*!&lt; 32-bit floating point format */
  10256. QS_F64_T, /*!&lt; 64-bit floating point format */
  10257. QS_STR_T, /*!&lt; zero-terminated ASCII string format */
  10258. QS_MEM_T, /*!&lt; up to 255-bytes memory block format */
  10259. QS_SIG_T, /*!&lt; event signal format */
  10260. QS_OBJ_T, /*!&lt; object pointer format */
  10261. QS_FUN_T, /*!&lt; function pointer format */
  10262. QS_I64_T, /*!&lt; signed 64-bit integer format */
  10263. QS_U64_T /*!&lt; unsigned 64-bit integer format */
  10264. };</code>
  10265. </attribute>
  10266. <!--${QS::QS-tx::priv_}-->
  10267. <attribute name="priv_" type="QS_tx" visibility="0x00" properties="0x01">
  10268. <documentation>/*! the only instance of the QS-TX object (Singleton) */</documentation>
  10269. </attribute>
  10270. <!--${QS::QS-tx::initBuf}-->
  10271. <operation name="initBuf" type="void" visibility="0x00" properties="0x01">
  10272. <documentation>/*! Initialize the QS-TX data buffer
  10273. * @static @public @memberof QS_tx
  10274. *
  10275. * @details
  10276. * This function should be called from QS_onStartup() to provide
  10277. * QS with the data buffer. The first argument `sto` is the address
  10278. * of the memory block, and the second argument `stoSize` is the size
  10279. * of this block [in bytes]. Currently the size of the QS buffer cannot
  10280. * exceed 64KB.
  10281. *
  10282. * @param[in] sto pointer to the storage for the transmit buffer
  10283. * @param[in] stoSize size in [bytes] of the storage buffer
  10284. *
  10285. * @remark
  10286. * QS can work with quite small data buffers, but you will start losing
  10287. * data if the buffer is too small for the bursts of tracing activity.
  10288. * The right size of the buffer depends on the data production rate and
  10289. * the data output rate. QS offers flexible filtering to reduce the data
  10290. * production rate.
  10291. *
  10292. * @note
  10293. * If the data output rate cannot keep up with the production rate,
  10294. * QS will start overwriting the older data with newer data. This is
  10295. * consistent with the &quot;last-is-best&quot; QS policy. The record sequence
  10296. * counters and check sums on each record allow the QSPY host utility
  10297. * to easily detect any data loss.
  10298. */
  10299. /*! @static @public @memberof QS_tx */</documentation>
  10300. <!--${QS::QS-tx::initBuf::sto}-->
  10301. <parameter name="sto" type="uint8_t * const"/>
  10302. <!--${QS::QS-tx::initBuf::stoSize}-->
  10303. <parameter name="stoSize" type="uint_fast32_t const"/>
  10304. <code>/* the provided buffer must be at least 8 bytes long */
  10305. Q_REQUIRE_ID(100, stoSize &gt; 8U);
  10306. QS_priv_.buf = &amp;sto[0];
  10307. QS_priv_.end = (QSCtr)stoSize;
  10308. QS_priv_.head = 0U;
  10309. QS_priv_.tail = 0U;
  10310. QS_priv_.used = 0U;
  10311. QS_priv_.seq = 0U;
  10312. QS_priv_.chksum = 0U;
  10313. QS_priv_.critNest = 0U;
  10314. QS_glbFilter_(-(int_fast16_t)QS_ALL_RECORDS); /* all global filters OFF */
  10315. QS_locFilter_((int_fast16_t)QS_ALL_IDS); /* all local filters ON */
  10316. QS_priv_.locFilter_AP = (void *)0; /* deprecated &quot;AP-filter&quot; */
  10317. /* produce an empty record to &quot;flush&quot; the QS trace buffer */
  10318. QS_beginRec_((uint_fast8_t)QS_EMPTY);
  10319. QS_endRec_();
  10320. /* produce the reset record to inform QSPY of a new session */
  10321. QS_target_info_pre_(0xFFU); /* send Reset and Target info */
  10322. /* hold off flushing after successfull initialization (see QS_INIT()) */</code>
  10323. </operation>
  10324. <!--${QS::QS-tx::getByte}-->
  10325. <operation name="getByte" type="uint16_t" visibility="0x00" properties="0x00">
  10326. <documentation>/*! Byte-oriented interface to the QS-TX data buffer
  10327. * @static @public @memberof QS_tx
  10328. *
  10329. * @details
  10330. * This function delivers one byte at a time from the QS data buffer.
  10331. *
  10332. * @returns
  10333. * the byte in the least-significant 8-bits of the 16-bit return
  10334. * value if the byte is available. If no more data is available at the
  10335. * time, the function returns ::QS_EOD (End-Of-Data).
  10336. *
  10337. * @note
  10338. * QS_getByte() is NOT protected with a critical section.
  10339. */
  10340. /*! @static @public @memberof QS_tx */</documentation>
  10341. <code>uint16_t ret;
  10342. if (QS_priv_.used == 0U) {
  10343. ret = QS_EOD; /* set End-Of-Data */
  10344. }
  10345. else {
  10346. uint8_t const * const buf = QS_priv_.buf; /* put in a temporary */
  10347. QSCtr tail = QS_priv_.tail; /* put in a temporary (register) */
  10348. ret = (uint16_t)buf[tail]; /* set the byte to return */
  10349. ++tail; /* advance the tail */
  10350. if (tail == QS_priv_.end) { /* tail wrap around? */
  10351. tail = 0U;
  10352. }
  10353. QS_priv_.tail = tail; /* update the tail */
  10354. --QS_priv_.used; /* one less byte used */
  10355. }
  10356. return ret; /* return the byte or EOD */</code>
  10357. </operation>
  10358. <!--${QS::QS-tx::getBlock}-->
  10359. <operation name="getBlock" type="uint8_t const *" visibility="0x00" properties="0x00">
  10360. <documentation>/*! Block-oriented interface to the QS-TX data buffer
  10361. * @static @public @memberof QS_tx
  10362. *
  10363. * @details
  10364. * This function delivers a contiguous block of data from the QS data
  10365. * buffer. The function returns the pointer to the beginning of the
  10366. * block, and writes the number of bytes in the block to the location
  10367. * pointed to by `pNbytes`. The argument `pNbytes` is also used as
  10368. * input to provide the maximum size of the data block that the caller
  10369. * can accept.
  10370. *
  10371. * @param[in,out] pNbytes pointer to the number of bytes to send.
  10372. * On input, `pNbytes` specifies the maximum number
  10373. * of bytes that the function can provide.
  10374. * On output, `pNbytes` contains the actual number
  10375. * of bytes available.
  10376. * @returns
  10377. * if data is available, the function returns pointer to the
  10378. * contiguous block of data and sets the value pointed to by `pNbytes`
  10379. * to the # available bytes. If data is available at the time the
  10380. * function is called, the function returns NULL pointer and sets the
  10381. * value pointed to by `pNbytes` to zero.
  10382. *
  10383. * @note
  10384. * Only the NULL return from QS_getBlock() indicates that the QS
  10385. * buffer is empty at the time of the call. The non-NULL return often
  10386. * means that the block is at the end of the buffer and you need to call
  10387. * QS_getBlock() again to obtain the rest of the data that
  10388. * &quot;wrapped around&quot; to the beginning of the QS data buffer.
  10389. *
  10390. * @note QS_getBlock() is **not** protected with a critical section.
  10391. */
  10392. /*! @static @public @memberof QS_tx */</documentation>
  10393. <!--${QS::QS-tx::getBlock::pNbytes}-->
  10394. <parameter name="pNbytes" type="uint16_t * const"/>
  10395. <code>QSCtr const used = QS_priv_.used; /* put in a temporary (register) */
  10396. uint8_t const *buf;
  10397. /* any bytes used in the ring buffer? */
  10398. if (used != 0U) {
  10399. QSCtr tail = QS_priv_.tail; /* put in a temporary (register) */
  10400. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10401. QSCtr n = (QSCtr)(end - tail);
  10402. if (n &gt; used) {
  10403. n = used;
  10404. }
  10405. if (n &gt; (QSCtr)(*pNbytes)) {
  10406. n = (QSCtr)(*pNbytes);
  10407. }
  10408. *pNbytes = (uint16_t)n; /* n-bytes available */
  10409. buf = &amp;QS_priv_.buf[tail]; /* the bytes are at the tail */
  10410. QS_priv_.used = (QSCtr)(used - n);
  10411. tail += n;
  10412. if (tail == end) {
  10413. tail = 0U;
  10414. }
  10415. QS_priv_.tail = tail;
  10416. }
  10417. else { /* no bytes available */
  10418. *pNbytes = 0U; /* no bytes available right now */
  10419. buf = (uint8_t *)0; /* no bytes available right now */
  10420. }
  10421. return buf;</code>
  10422. </operation>
  10423. <!--${QS::QS-tx::glbFilter_}-->
  10424. <operation name="glbFilter_" type="void" visibility="0x00" properties="0x01">
  10425. <documentation>/*! Set/clear the global Filter for a given QS record or a group
  10426. * of records
  10427. * @static @public @memberof QS_tx
  10428. *
  10429. * @details
  10430. * This function sets up the QS filter to enable record types specified
  10431. * in the `filter` parameter. The value #QS_ALL_RECORDS specifies to
  10432. * filter-in all records. This function should be called indirectly
  10433. * through the macro QS_GLB_FILTER()
  10434. *
  10435. * @param[in] filter the QS record-d or group to enable in the filter,
  10436. * if positive or disable, if negative. The record-id
  10437. * numbers must be in the range -127..127.
  10438. * @note
  10439. * Filtering based on the record-type is only the first layer of
  10440. * filtering. The second layer is based on the object-type. Both filter
  10441. * layers must be enabled for the QS record to be inserted in the
  10442. * QS buffer.
  10443. *
  10444. * @sa QS_locFilter_()
  10445. */
  10446. /*! @static @public @memberof QS_tx */</documentation>
  10447. <!--${QS::QS-tx::glbFilter_::filter}-->
  10448. <parameter name="filter" type="int_fast16_t const"/>
  10449. <code>bool const isRemove = (filter &lt; 0);
  10450. uint8_t const rec = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
  10451. switch (rec) {
  10452. case (uint8_t)QS_ALL_RECORDS: {
  10453. uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
  10454. /* set all global filters (partially unrolled loop) */
  10455. for (uint_fast8_t i = 0U;
  10456. i &lt; Q_DIM(QS_priv_.glbFilter);
  10457. i += 4U)
  10458. {
  10459. QS_priv_.glbFilter[i ] = tmp;
  10460. QS_priv_.glbFilter[i + 1U] = tmp;
  10461. QS_priv_.glbFilter[i + 2U] = tmp;
  10462. QS_priv_.glbFilter[i + 3U] = tmp;
  10463. }
  10464. if (isRemove) {
  10465. /* leave the &quot;not maskable&quot; filters enabled,
  10466. * see qs.h, Miscellaneous QS records (not maskable)
  10467. */
  10468. QS_priv_.glbFilter[0] = 0x01U;
  10469. QS_priv_.glbFilter[6] = 0x40U;
  10470. QS_priv_.glbFilter[7] = 0xFCU;
  10471. QS_priv_.glbFilter[8] = 0x7FU;
  10472. }
  10473. else {
  10474. /* never turn the last 3 records on (0x7D, 0x7E, 0x7F) */
  10475. QS_priv_.glbFilter[15] = 0x1FU;
  10476. }
  10477. break;
  10478. }
  10479. case (uint8_t)QS_SM_RECORDS:
  10480. if (isRemove) {
  10481. QS_priv_.glbFilter[0] &amp;= (uint8_t)(~0xFEU &amp; 0xFFU);
  10482. QS_priv_.glbFilter[1] &amp;= (uint8_t)(~0x03U &amp; 0xFFU);
  10483. QS_priv_.glbFilter[6] &amp;= (uint8_t)(~0x80U &amp; 0xFFU);
  10484. QS_priv_.glbFilter[7] &amp;= (uint8_t)(~0x03U &amp; 0xFFU);
  10485. }
  10486. else {
  10487. QS_priv_.glbFilter[0] |= 0xFEU;
  10488. QS_priv_.glbFilter[1] |= 0x03U;
  10489. QS_priv_.glbFilter[6] |= 0x80U;
  10490. QS_priv_.glbFilter[7] |= 0x03U;
  10491. }
  10492. break;
  10493. case (uint8_t)QS_AO_RECORDS:
  10494. if (isRemove) {
  10495. QS_priv_.glbFilter[1] &amp;= (uint8_t)(~0xFCU &amp; 0xFFU);
  10496. QS_priv_.glbFilter[2] &amp;= (uint8_t)(~0x07U &amp; 0xFFU);
  10497. QS_priv_.glbFilter[5] &amp;= (uint8_t)(~0x20U &amp; 0xFFU);
  10498. }
  10499. else {
  10500. QS_priv_.glbFilter[1] |= 0xFCU;
  10501. QS_priv_.glbFilter[2] |= 0x07U;
  10502. QS_priv_.glbFilter[5] |= 0x20U;
  10503. }
  10504. break;
  10505. case (uint8_t)QS_EQ_RECORDS:
  10506. if (isRemove) {
  10507. QS_priv_.glbFilter[2] &amp;= (uint8_t)(~0x78U &amp; 0xFFU);
  10508. QS_priv_.glbFilter[5] &amp;= (uint8_t)(~0x40U &amp; 0xFFU);
  10509. }
  10510. else {
  10511. QS_priv_.glbFilter[2] |= 0x78U;
  10512. QS_priv_.glbFilter[5] |= 0x40U;
  10513. }
  10514. break;
  10515. case (uint8_t)QS_MP_RECORDS:
  10516. if (isRemove) {
  10517. QS_priv_.glbFilter[3] &amp;= (uint8_t)(~0x03U &amp; 0xFFU);
  10518. QS_priv_.glbFilter[5] &amp;= (uint8_t)(~0x80U &amp; 0xFFU);
  10519. }
  10520. else {
  10521. QS_priv_.glbFilter[3] |= 0x03U;
  10522. QS_priv_.glbFilter[5] |= 0x80U;
  10523. }
  10524. break;
  10525. case (uint8_t)QS_QF_RECORDS:
  10526. if (isRemove) {
  10527. QS_priv_.glbFilter[2] &amp;= (uint8_t)(~0x80U &amp; 0xFFU);
  10528. QS_priv_.glbFilter[3] &amp;= (uint8_t)(~0xFCU &amp; 0xFFU);
  10529. QS_priv_.glbFilter[4] &amp;= (uint8_t)(~0xC0U &amp; 0xFFU);
  10530. QS_priv_.glbFilter[5] &amp;= (uint8_t)(~0x1FU &amp; 0xFFU);
  10531. }
  10532. else {
  10533. QS_priv_.glbFilter[2] |= 0x80U;
  10534. QS_priv_.glbFilter[3] |= 0xFCU;
  10535. QS_priv_.glbFilter[4] |= 0xC0U;
  10536. QS_priv_.glbFilter[5] |= 0x1FU;
  10537. }
  10538. break;
  10539. case (uint8_t)QS_TE_RECORDS:
  10540. if (isRemove) {
  10541. QS_priv_.glbFilter[4] &amp;= (uint8_t)(~0x3FU &amp; 0xFFU);
  10542. }
  10543. else {
  10544. QS_priv_.glbFilter[4] |= 0x3FU;
  10545. }
  10546. break;
  10547. case (uint8_t)QS_SC_RECORDS:
  10548. if (isRemove) {
  10549. QS_priv_.glbFilter[6] &amp;= (uint8_t)(~0x3FU &amp; 0xFFU);
  10550. }
  10551. else {
  10552. QS_priv_.glbFilter[6] |= 0x3FU;
  10553. }
  10554. break;
  10555. case (uint8_t)QS_SEM_RECORDS:
  10556. if (isRemove) {
  10557. QS_priv_.glbFilter[8] &amp;= (uint8_t)(~0x80U &amp; 0xFFU);
  10558. QS_priv_.glbFilter[9] &amp;= (uint8_t)(~0x07U &amp; 0xFFU);
  10559. }
  10560. else {
  10561. QS_priv_.glbFilter[8] |= 0x80U;
  10562. QS_priv_.glbFilter[9] |= 0x07U;
  10563. }
  10564. break;
  10565. case (uint8_t)QS_MTX_RECORDS:
  10566. if (isRemove) {
  10567. QS_priv_.glbFilter[9] &amp;= (uint8_t)(~0xF8U &amp; 0xFFU);
  10568. QS_priv_.glbFilter[10] &amp;= (uint8_t)(~0x01U &amp; 0xFFU);
  10569. }
  10570. else {
  10571. QS_priv_.glbFilter[9] |= 0xF8U;
  10572. QS_priv_.glbFilter[10] |= 0x01U;
  10573. }
  10574. break;
  10575. case (uint8_t)QS_U0_RECORDS:
  10576. if (isRemove) {
  10577. QS_priv_.glbFilter[12] &amp;= (uint8_t)(~0xF0U &amp; 0xFFU);
  10578. QS_priv_.glbFilter[13] &amp;= (uint8_t)(~0x01U &amp; 0xFFU);
  10579. }
  10580. else {
  10581. QS_priv_.glbFilter[12] |= 0xF0U;
  10582. QS_priv_.glbFilter[13] |= 0x01U;
  10583. }
  10584. break;
  10585. case (uint8_t)QS_U1_RECORDS:
  10586. if (isRemove) {
  10587. QS_priv_.glbFilter[13] &amp;= (uint8_t)(~0x3EU &amp; 0xFFU);
  10588. }
  10589. else {
  10590. QS_priv_.glbFilter[13] |= 0x3EU;
  10591. }
  10592. break;
  10593. case (uint8_t)QS_U2_RECORDS:
  10594. if (isRemove) {
  10595. QS_priv_.glbFilter[13] &amp;= (uint8_t)(~0xC0U &amp; 0xFFU);
  10596. QS_priv_.glbFilter[14] &amp;= (uint8_t)(~0x07U &amp; 0xFFU);
  10597. }
  10598. else {
  10599. QS_priv_.glbFilter[13] |= 0xC0U;
  10600. QS_priv_.glbFilter[14] |= 0x07U;
  10601. }
  10602. break;
  10603. case (uint8_t)QS_U3_RECORDS:
  10604. if (isRemove) {
  10605. QS_priv_.glbFilter[14] &amp;= (uint8_t)(~0xF8U &amp; 0xFFU);
  10606. }
  10607. else {
  10608. QS_priv_.glbFilter[14] |= 0xF8U;
  10609. }
  10610. break;
  10611. case (uint8_t)QS_U4_RECORDS:
  10612. if (isRemove) {
  10613. QS_priv_.glbFilter[15] &amp;= 0x1FU;
  10614. }
  10615. else {
  10616. QS_priv_.glbFilter[15] |= 0x1FU;
  10617. }
  10618. break;
  10619. case (uint8_t)QS_UA_RECORDS:
  10620. if (isRemove) {
  10621. QS_priv_.glbFilter[12] &amp;= (uint8_t)(~0xF0U &amp; 0xFFU);
  10622. QS_priv_.glbFilter[13] = 0U;
  10623. QS_priv_.glbFilter[14] = 0U;
  10624. QS_priv_.glbFilter[15] &amp;= (uint8_t)(~0x1FU &amp; 0xFFU);
  10625. }
  10626. else {
  10627. QS_priv_.glbFilter[12] |= 0xF0U;
  10628. QS_priv_.glbFilter[13] |= 0xFFU;
  10629. QS_priv_.glbFilter[14] |= 0xFFU;
  10630. QS_priv_.glbFilter[15] |= 0x1FU;
  10631. }
  10632. break;
  10633. default:
  10634. /* QS rec number can't exceed 0x7D, so no need for escaping */
  10635. Q_ASSERT_ID(210, rec &lt; 0x7DU);
  10636. if (isRemove) {
  10637. QS_priv_.glbFilter[rec &gt;&gt; 3U]
  10638. &amp;= (uint8_t)(~(1U &lt;&lt; (rec &amp; 7U)) &amp; 0xFFU);
  10639. }
  10640. else {
  10641. QS_priv_.glbFilter[rec &gt;&gt; 3U]
  10642. |= (1U &lt;&lt; (rec &amp; 7U));
  10643. /* never turn the last 3 records on (0x7D, 0x7E, 0x7F) */
  10644. QS_priv_.glbFilter[15] &amp;= 0x1FU;
  10645. }
  10646. break;
  10647. }</code>
  10648. </operation>
  10649. <!--${QS::QS-tx::locFilter_}-->
  10650. <operation name="locFilter_" type="void" visibility="0x00" properties="0x01">
  10651. <documentation>/*! Set/clear the local Filter for a given object-id
  10652. * or a group of object-ids
  10653. * @static @public @memberof QS_tx
  10654. *
  10655. * @details
  10656. * This function sets up the local QS filter to enable or disable the
  10657. * given QS object-id or a group of object-ids @a filter.
  10658. * This function should be called indirectly through the macro
  10659. * QS_LOC_FILTER()
  10660. *
  10661. * @param[in] filter the QS object-id or group to enable in the filter,
  10662. * if positive or disable, if negative. The qs_id numbers
  10663. * must be in the range 1..127.
  10664. * @note
  10665. * Filtering based on the object-id (local filter) is the second layer
  10666. * of filtering. The first layer is based on the QS record-type (global
  10667. * filter). Both filter layers must be enabled for the QS record to be
  10668. * inserted into the QS buffer.
  10669. *
  10670. * @sa QS_glbFilter_()
  10671. */
  10672. /*! @static @public @memberof QS_tx */</documentation>
  10673. <!--${QS::QS-tx::locFilter_::filter}-->
  10674. <parameter name="filter" type="int_fast16_t const"/>
  10675. <code>bool const isRemove = (filter &lt; 0);
  10676. uint8_t const qs_id = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
  10677. uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
  10678. uint_fast8_t i;
  10679. switch (qs_id) {
  10680. case (uint8_t)QS_ALL_IDS:
  10681. /* set all local filters (partially unrolled loop) */
  10682. for (i = 0U; i &lt; Q_DIM(QS_priv_.locFilter); i += 4U) {
  10683. QS_priv_.locFilter[i ] = tmp;
  10684. QS_priv_.locFilter[i + 1U] = tmp;
  10685. QS_priv_.locFilter[i + 2U] = tmp;
  10686. QS_priv_.locFilter[i + 3U] = tmp;
  10687. }
  10688. break;
  10689. case (uint8_t)QS_AO_IDS:
  10690. for (i = 0U; i &lt; 8U; i += 4U) {
  10691. QS_priv_.locFilter[i ] = tmp;
  10692. QS_priv_.locFilter[i + 1U] = tmp;
  10693. QS_priv_.locFilter[i + 2U] = tmp;
  10694. QS_priv_.locFilter[i + 3U] = tmp;
  10695. }
  10696. break;
  10697. case (uint8_t)QS_EP_IDS:
  10698. i = 8U;
  10699. QS_priv_.locFilter[i ] = tmp;
  10700. QS_priv_.locFilter[i + 1U] = tmp;
  10701. break;
  10702. case (uint8_t)QS_AP_IDS:
  10703. i = 12U;
  10704. QS_priv_.locFilter[i ] = tmp;
  10705. QS_priv_.locFilter[i + 1U] = tmp;
  10706. QS_priv_.locFilter[i + 2U] = tmp;
  10707. QS_priv_.locFilter[i + 3U] = tmp;
  10708. break;
  10709. default:
  10710. if (qs_id &lt; 0x7FU) {
  10711. if (isRemove) {
  10712. QS_priv_.locFilter[qs_id &gt;&gt; 3U]
  10713. &amp;= (uint8_t)(~(1U &lt;&lt; (qs_id &amp; 7U)) &amp; 0xFFU);
  10714. }
  10715. else {
  10716. QS_priv_.locFilter[qs_id &gt;&gt; 3U]
  10717. |= (1U &lt;&lt; (qs_id &amp; 7U));
  10718. }
  10719. }
  10720. else {
  10721. Q_ERROR_ID(310); /* incorrect qs_id */
  10722. }
  10723. break;
  10724. }
  10725. QS_priv_.locFilter[0] |= 0x01U; /* leave QS_ID == 0 always on */</code>
  10726. </operation>
  10727. <!--${QS::QS-tx::doOutput}-->
  10728. <operation name="doOutput" type="void" visibility="0x00" properties="0x00">
  10729. <documentation>/*! Perform the QS-TX output (implemented in some QS ports)
  10730. * @static @public @memberof QS_tx
  10731. */
  10732. /*! @static @public @memberof QS_tx */</documentation>
  10733. </operation>
  10734. <!--${QS::QS-tx::beginRec_}-->
  10735. <operation name="beginRec_" type="void" visibility="0x00" properties="0x01">
  10736. <documentation>/*! Mark the begin of a QS record `rec`
  10737. * @static @private @memberof QS_tx
  10738. *
  10739. * @details
  10740. * This function must be called at the beginning of each QS record.
  10741. * This function should be called indirectly through the macro QS_BEGIN_ID(),
  10742. * or QS_BEGIN_NOCRIT(), depending if it's called in a normal code or from
  10743. * a critical section.
  10744. */
  10745. /*! @static @private @memberof QS_tx */</documentation>
  10746. <!--${QS::QS-tx::beginRec_::rec}-->
  10747. <parameter name="rec" type="uint_fast8_t const"/>
  10748. <code>uint8_t const b = (uint8_t)(QS_priv_.seq + 1U);
  10749. uint8_t chksum = 0U; /* reset the checksum */
  10750. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10751. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10752. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10753. QS_priv_.seq = b; /* store the incremented sequence num */
  10754. QS_priv_.used += 2U; /* 2 bytes about to be added */
  10755. QS_INSERT_ESC_BYTE_(b)
  10756. chksum = (uint8_t)(chksum + rec); /* update checksum */
  10757. QS_INSERT_BYTE_((uint8_t)rec) /* rec byte does not need escaping */
  10758. QS_priv_.head = head; /* save the head */
  10759. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10760. </operation>
  10761. <!--${QS::QS-tx::endRec_}-->
  10762. <operation name="endRec_" type="void" visibility="0x00" properties="0x01">
  10763. <documentation>/*! Mark the end of a QS record `rec`
  10764. * @static @private @memberof QS_tx
  10765. *
  10766. * @details
  10767. * This function must be called at the end of each QS record.
  10768. * This function should be called indirectly through the macro QS_END(),
  10769. * or QS_END_NOCRIT(), depending if it's called in a normal code or from
  10770. * a critical section.
  10771. */
  10772. /*! @static @private @memberof QS_tx */</documentation>
  10773. <code>uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10774. QSCtr head = QS_priv_.head;
  10775. QSCtr const end = QS_priv_.end;
  10776. uint8_t b = QS_priv_.chksum;
  10777. b ^= 0xFFU; /* invert the bits in the checksum */
  10778. QS_priv_.used += 2U; /* 2 bytes about to be added */
  10779. if ((b != QS_FRAME) &amp;&amp; (b != QS_ESC)) {
  10780. QS_INSERT_BYTE_(b)
  10781. }
  10782. else {
  10783. QS_INSERT_BYTE_(QS_ESC)
  10784. QS_INSERT_BYTE_(b ^ QS_ESC_XOR)
  10785. ++QS_priv_.used; /* account for the ESC byte */
  10786. }
  10787. QS_INSERT_BYTE_(QS_FRAME) /* do not escape this QS_FRAME */
  10788. QS_priv_.head = head; /* save the head */
  10789. /* overrun over the old data? */
  10790. if (QS_priv_.used &gt; end) {
  10791. QS_priv_.used = end; /* the whole buffer is used */
  10792. QS_priv_.tail = head; /* shift the tail to the old data */
  10793. }</code>
  10794. </operation>
  10795. <!--${QS::QS-tx::u8_raw_}-->
  10796. <operation name="u8_raw_" type="void" visibility="0x00" properties="0x01">
  10797. <documentation>/*! output uint8_t data element without format information
  10798. * @static @private @memberof QS_tx
  10799. */
  10800. /*! @static @private @memberof QS_tx */</documentation>
  10801. <!--${QS::QS-tx::u8_raw_::d}-->
  10802. <parameter name="d" type="uint8_t const"/>
  10803. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10804. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10805. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10806. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10807. QS_priv_.used += 1U; /* 1 byte about to be added */
  10808. QS_INSERT_ESC_BYTE_(d)
  10809. QS_priv_.head = head; /* save the head */
  10810. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10811. </operation>
  10812. <!--${QS::QS-tx::2u8_raw_}-->
  10813. <operation name="2u8_raw_" type="void" visibility="0x00" properties="0x01">
  10814. <documentation>/*! output two uint8_t data elements without format information
  10815. * @static @private @memberof QS_tx
  10816. */
  10817. /*! @static @private @memberof QS_tx */</documentation>
  10818. <!--${QS::QS-tx::2u8_raw_::d1}-->
  10819. <parameter name="d1" type="uint8_t const"/>
  10820. <!--${QS::QS-tx::2u8_raw_::d2}-->
  10821. <parameter name="d2" type="uint8_t const"/>
  10822. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10823. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10824. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10825. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10826. QS_priv_.used += 2U; /* 2 bytes are about to be added */
  10827. QS_INSERT_ESC_BYTE_(d1)
  10828. QS_INSERT_ESC_BYTE_(d2)
  10829. QS_priv_.head = head; /* save the head */
  10830. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10831. </operation>
  10832. <!--${QS::QS-tx::u16_raw_}-->
  10833. <operation name="u16_raw_" type="void" visibility="0x00" properties="0x01">
  10834. <documentation>/*! output uint16_t data element without format information
  10835. * @static @private @memberof QS_tx
  10836. */
  10837. /*! @static @private @memberof QS_tx */</documentation>
  10838. <!--${QS::QS-tx::u16_raw_::d}-->
  10839. <parameter name="d" type="uint16_t const"/>
  10840. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10841. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10842. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10843. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10844. uint16_t x = d;
  10845. QS_priv_.used += 2U; /* 2 bytes are about to be added */
  10846. QS_INSERT_ESC_BYTE_((uint8_t)x)
  10847. x &gt;&gt;= 8U;
  10848. QS_INSERT_ESC_BYTE_((uint8_t)x)
  10849. QS_priv_.head = head; /* save the head */
  10850. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10851. </operation>
  10852. <!--${QS::QS-tx::u32_raw_}-->
  10853. <operation name="u32_raw_" type="void" visibility="0x00" properties="0x01">
  10854. <documentation>/*! output uint32_t data element without format information
  10855. * @static @private @memberof QS_tx
  10856. */
  10857. /*! @static @private @memberof QS_tx */</documentation>
  10858. <!--${QS::QS-tx::u32_raw_::d}-->
  10859. <parameter name="d" type="uint32_t const"/>
  10860. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10861. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10862. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10863. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10864. uint32_t x = d;
  10865. QS_priv_.used += 4U; /* 4 bytes are about to be added */
  10866. for (uint_fast8_t i = 4U; i != 0U; --i) {
  10867. QS_INSERT_ESC_BYTE_((uint8_t)x)
  10868. x &gt;&gt;= 8U;
  10869. }
  10870. QS_priv_.head = head; /* save the head */
  10871. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10872. </operation>
  10873. <!--${QS::QS-tx::obj_raw_}-->
  10874. <operation name="obj_raw_" type="void" visibility="0x00" properties="0x01">
  10875. <documentation>/*! Output obj pointer data element without format information
  10876. * @static @private @memberof QS_tx
  10877. *
  10878. * @note This function is only to be used through macros, never in the
  10879. * client code directly.
  10880. */
  10881. /*! @static @private @memberof QS_tx */</documentation>
  10882. <!--${QS::QS-tx::obj_raw_::obj}-->
  10883. <parameter name="obj" type="void const * const"/>
  10884. <code>#if (QS_OBJ_PTR_SIZE == 1U)
  10885. QS_u8_raw_((uint8_t)obj);
  10886. #elif (QS_OBJ_PTR_SIZE == 2U)
  10887. QS_u16_raw_((uint16_t)obj);
  10888. #elif (QS_OBJ_PTR_SIZE == 4U)
  10889. QS_u32_raw_((uint32_t)obj);
  10890. #elif (QS_OBJ_PTR_SIZE == 8U)
  10891. QS_u64_raw_((uint64_t)obj);
  10892. #else
  10893. QS_u32_raw_((uint32_t)obj);
  10894. #endif</code>
  10895. </operation>
  10896. <!--${QS::QS-tx::str_raw_}-->
  10897. <operation name="str_raw_" type="void" visibility="0x00" properties="0x01">
  10898. <documentation>/*! Output raw zero-terminated string element (without format information)
  10899. * @static @private @memberof QS_tx
  10900. *
  10901. * @note This function is only to be used through macros, never in the
  10902. * client code directly.
  10903. */
  10904. /*! @static @private @memberof QS_tx */</documentation>
  10905. <!--${QS::QS-tx::str_raw_::str}-->
  10906. <parameter name="str" type="char const * const"/>
  10907. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10908. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10909. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10910. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10911. QSCtr used = QS_priv_.used; /* put in a temporary (register) */
  10912. for (char const *s = str; *s != '\0'; ++s) {
  10913. chksum += (uint8_t)*s; /* update checksum */
  10914. QS_INSERT_BYTE_((uint8_t)*s) /* ASCII char doesn't need escaping */
  10915. ++used;
  10916. }
  10917. QS_INSERT_BYTE_((uint8_t)'\0') /* zero-terminate the string */
  10918. ++used;
  10919. QS_priv_.head = head; /* save the head */
  10920. QS_priv_.chksum = chksum; /* save the checksum */
  10921. QS_priv_.used = used; /* save # of used buffer space */</code>
  10922. </operation>
  10923. <!--${QS::QS-tx::u8_fmt_}-->
  10924. <operation name="u8_fmt_" type="void" visibility="0x00" properties="0x01">
  10925. <documentation>/*! Output uint8_t data element with format information
  10926. * @static @private @memberof QS_tx
  10927. *
  10928. * @details
  10929. * @note This function is only to be used through macros, never in the
  10930. * client code directly.
  10931. */
  10932. /*! @static @private @memberof QS_tx */</documentation>
  10933. <!--${QS::QS-tx::u8_fmt_::format}-->
  10934. <parameter name="format" type="uint8_t const"/>
  10935. <!--${QS::QS-tx::u8_fmt_::d}-->
  10936. <parameter name="d" type="uint8_t const"/>
  10937. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10938. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10939. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10940. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10941. QS_priv_.used += 2U; /* 2 bytes about to be added */
  10942. QS_INSERT_ESC_BYTE_(format)
  10943. QS_INSERT_ESC_BYTE_(d)
  10944. QS_priv_.head = head; /* save the head */
  10945. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10946. </operation>
  10947. <!--${QS::QS-tx::u16_fmt_}-->
  10948. <operation name="u16_fmt_" type="void" visibility="0x00" properties="0x01">
  10949. <documentation>/*! output uint16_t data element with format information
  10950. * @static @private @memberof QS_tx
  10951. *
  10952. * @details
  10953. * This function is only to be used through macros, never in the
  10954. * client code directly.
  10955. */
  10956. /*! @static @private @memberof QS_tx */</documentation>
  10957. <!--${QS::QS-tx::u16_fmt_::format}-->
  10958. <parameter name="format" type="uint8_t const"/>
  10959. <!--${QS::QS-tx::u16_fmt_::d}-->
  10960. <parameter name="d" type="uint16_t const"/>
  10961. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10962. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10963. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10964. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10965. uint8_t b = (uint8_t)d;
  10966. QS_priv_.used += 3U; /* 3 bytes about to be added */
  10967. QS_INSERT_ESC_BYTE_(format)
  10968. QS_INSERT_ESC_BYTE_(b)
  10969. b = (uint8_t)(d &gt;&gt; 8U);
  10970. QS_INSERT_ESC_BYTE_(b)
  10971. QS_priv_.head = head; /* save the head */
  10972. QS_priv_.chksum = chksum; /* save the checksum */</code>
  10973. </operation>
  10974. <!--${QS::QS-tx::u32_fmt_}-->
  10975. <operation name="u32_fmt_" type="void" visibility="0x00" properties="0x01">
  10976. <documentation>/*! Output uint32_t data element with format information
  10977. * @static @private @memberof QS_tx
  10978. *
  10979. * @note This function is only to be used through macros, never in the
  10980. * client code directly.
  10981. */
  10982. /*! @static @private @memberof QS_tx */</documentation>
  10983. <!--${QS::QS-tx::u32_fmt_::format}-->
  10984. <parameter name="format" type="uint8_t const"/>
  10985. <!--${QS::QS-tx::u32_fmt_::d}-->
  10986. <parameter name="d" type="uint32_t const"/>
  10987. <code>uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  10988. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  10989. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  10990. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  10991. uint32_t x = d;
  10992. QS_priv_.used += 5U; /* 5 bytes about to be added */
  10993. QS_INSERT_ESC_BYTE_(format) /* insert the format byte */
  10994. /* insert 4 bytes... */
  10995. for (uint_fast8_t i = 4U; i != 0U; --i) {
  10996. QS_INSERT_ESC_BYTE_((uint8_t)x)
  10997. x &gt;&gt;= 8U;
  10998. }
  10999. QS_priv_.head = head; /* save the head */
  11000. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11001. </operation>
  11002. <!--${QS::QS-tx::str_fmt_}-->
  11003. <operation name="str_fmt_" type="void" visibility="0x00" properties="0x01">
  11004. <documentation>/*! Output formatted zero-terminated ASCII string to the QS record
  11005. * @static @private @memberof QS_tx
  11006. */
  11007. /*! @static @private @memberof QS_tx */</documentation>
  11008. <!--${QS::QS-tx::str_fmt_::str}-->
  11009. <parameter name="str" type="char const * const"/>
  11010. <code>uint8_t chksum = QS_priv_.chksum;
  11011. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  11012. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  11013. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  11014. QSCtr used = QS_priv_.used; /* put in a temporary (register) */
  11015. used += 2U; /* account for the format byte and the terminating-0 */
  11016. QS_INSERT_BYTE_((uint8_t)QS_STR_T)
  11017. chksum += (uint8_t)QS_STR_T;
  11018. for (char const *s = str; *s != '\0'; ++s) {
  11019. QS_INSERT_BYTE_((uint8_t)*s) /* ASCII char doesn't need escaping */
  11020. chksum += (uint8_t)*s; /* update checksum */
  11021. ++used;
  11022. }
  11023. QS_INSERT_BYTE_(0U) /* zero-terminate the string */
  11024. QS_priv_.head = head; /* save the head */
  11025. QS_priv_.chksum = chksum; /* save the checksum */
  11026. QS_priv_.used = used; /* save # of used buffer space */</code>
  11027. </operation>
  11028. <!--${QS::QS-tx::mem_fmt_}-->
  11029. <operation name="mem_fmt_" type="void" visibility="0x00" properties="0x01">
  11030. <documentation>/*! Output formatted memory block of up to 255 bytes to the QS record
  11031. * @static @private @memberof QS_tx
  11032. */
  11033. /*! @static @private @memberof QS_tx */</documentation>
  11034. <!--${QS::QS-tx::mem_fmt_::blk}-->
  11035. <parameter name="blk" type="uint8_t const * const"/>
  11036. <!--${QS::QS-tx::mem_fmt_::size}-->
  11037. <parameter name="size" type="uint8_t const"/>
  11038. <code>uint8_t chksum = QS_priv_.chksum;
  11039. uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
  11040. QSCtr head = QS_priv_.head; /* put in a temporary (register) */
  11041. QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
  11042. uint8_t const *pb = blk;
  11043. QS_priv_.used += ((QSCtr)size + 2U); /* size+2 bytes to be added */
  11044. QS_INSERT_BYTE_((uint8_t)QS_MEM_T)
  11045. chksum += (uint8_t)QS_MEM_T;
  11046. QS_INSERT_ESC_BYTE_(size)
  11047. /* output the 'size' number of bytes */
  11048. for (uint8_t len = size; len &gt; 0U; --len) {
  11049. QS_INSERT_ESC_BYTE_(*pb)
  11050. ++pb;
  11051. }
  11052. QS_priv_.head = head; /* save the head */
  11053. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11054. </operation>
  11055. <!--${QS::QS-tx::sig_dict_pre_}-->
  11056. <operation name="sig_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11057. <documentation>/*! Output predefined signal-dictionary record
  11058. * @static @private @memberof QS_tx
  11059. *
  11060. * @note This function is only to be used through macro QS_SIG_DICTIONARY()
  11061. */
  11062. /*! @static @private @memberof QS_tx */</documentation>
  11063. <!--${QS::QS-tx::sig_dict_pre_::sig}-->
  11064. <parameter name="sig" type="enum_t const"/>
  11065. <!--${QS::QS-tx::sig_dict_pre_::obj}-->
  11066. <parameter name="obj" type="void const * const"/>
  11067. <!--${QS::QS-tx::sig_dict_pre_::name}-->
  11068. <parameter name="name" type="char const * const"/>
  11069. <code>QS_CRIT_STAT_
  11070. QS_CRIT_E_();
  11071. QS_beginRec_((uint_fast8_t)QS_SIG_DICT);
  11072. QS_SIG_PRE_(sig);
  11073. QS_OBJ_PRE_(obj);
  11074. QS_str_raw_((*name == '&amp;') ? &amp;name[1] : name);
  11075. QS_endRec_();
  11076. QS_CRIT_X_();
  11077. QS_onFlush();</code>
  11078. </operation>
  11079. <!--${QS::QS-tx::obj_dict_pre_}-->
  11080. <operation name="obj_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11081. <documentation>/*! Output predefined object-dictionary record
  11082. * @static @private @memberof QS_tx
  11083. *
  11084. * @note This function is only to be used through macro QS_OBJ_DICTIONARY()
  11085. */
  11086. /*! @static @private @memberof QS_tx */</documentation>
  11087. <!--${QS::QS-tx::obj_dict_pre_::obj}-->
  11088. <parameter name="obj" type="void const * const"/>
  11089. <!--${QS::QS-tx::obj_dict_pre_::name}-->
  11090. <parameter name="name" type="char const * const"/>
  11091. <code>QS_CRIT_STAT_
  11092. QS_CRIT_E_();
  11093. QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
  11094. QS_OBJ_PRE_(obj);
  11095. QS_str_raw_((*name == '&amp;') ? &amp;name[1] : name);
  11096. QS_endRec_();
  11097. QS_CRIT_X_();
  11098. QS_onFlush();</code>
  11099. </operation>
  11100. <!--${QS::QS-tx::obj_arr_dict_pre_}-->
  11101. <operation name="obj_arr_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11102. <documentation>/*! Output predefined object-array dictionary record
  11103. * @static @private @memberof QS_tx
  11104. *
  11105. * @note This function is only to be used through macro QS_OBJ_ARR_DICTIONARY()
  11106. */
  11107. /*! @static @private @memberof QS_tx */</documentation>
  11108. <!--${QS::QS-tx::obj_arr_dict_pre~::obj}-->
  11109. <parameter name="obj" type="void const * const"/>
  11110. <!--${QS::QS-tx::obj_arr_dict_pre~::idx}-->
  11111. <parameter name="idx" type="uint_fast16_t const"/>
  11112. <!--${QS::QS-tx::obj_arr_dict_pre~::name}-->
  11113. <parameter name="name" type="char const * const"/>
  11114. <code>Q_REQUIRE_ID(400, idx &lt; 1000U);
  11115. /* format idx into a char buffer as &quot;xxx\0&quot; */
  11116. uint8_t idx_str[4];
  11117. uint_fast16_t tmp = idx;
  11118. uint8_t i;
  11119. idx_str[3] = 0U; /* zero-terminate */
  11120. idx_str[2] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
  11121. tmp /= 10U;
  11122. idx_str[1] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
  11123. if (idx_str[1] == (uint8_t)'0') {
  11124. i = 2U;
  11125. }
  11126. else {
  11127. tmp /= 10U;
  11128. idx_str[0] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
  11129. if (idx_str[0] == (uint8_t)'0') {
  11130. i = 1U;
  11131. }
  11132. else {
  11133. i = 0U;
  11134. }
  11135. }
  11136. QS_CRIT_STAT_
  11137. uint8_t j = ((*name == '&amp;') ? 1U : 0U);
  11138. QS_CRIT_E_();
  11139. QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
  11140. QS_OBJ_PRE_(obj);
  11141. for (; name[j] != '\0'; ++j) {
  11142. QS_U8_PRE_(name[j]);
  11143. if (name[j] == '[') {
  11144. ++j;
  11145. break;
  11146. }
  11147. }
  11148. for (; idx_str[i] != 0U; ++i) {
  11149. QS_U8_PRE_(idx_str[i]);
  11150. }
  11151. /* skip chars until ']' */
  11152. for (; name[j] != '\0'; ++j) {
  11153. if (name[j] == ']') {
  11154. break;
  11155. }
  11156. }
  11157. for (; name[j] != '\0'; ++j) {
  11158. QS_U8_PRE_(name[j]);
  11159. }
  11160. QS_U8_PRE_(0U); /* zero-terminate */
  11161. QS_endRec_();
  11162. QS_CRIT_X_();
  11163. QS_onFlush();</code>
  11164. </operation>
  11165. <!--${QS::QS-tx::fun_dict_pre_}-->
  11166. <operation name="fun_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11167. <documentation>/*! Output predefined function-dictionary record
  11168. * @static @private @memberof QS_tx
  11169. *
  11170. * @note This function is only to be used through macro QS_FUN_DICTIONARY()
  11171. */
  11172. /*! @static @private @memberof QS_tx */</documentation>
  11173. <!--${QS::QS-tx::fun_dict_pre_::fun}-->
  11174. <parameter name="fun" type="QSpyFunPtr const"/>
  11175. <!--${QS::QS-tx::fun_dict_pre_::name}-->
  11176. <parameter name="name" type="char const * const"/>
  11177. <code>QS_CRIT_STAT_
  11178. QS_CRIT_E_();
  11179. QS_beginRec_((uint_fast8_t)QS_FUN_DICT);
  11180. QS_FUN_PRE_(fun);
  11181. QS_str_raw_((*name == '&amp;') ? &amp;name[1] : name);
  11182. QS_endRec_();
  11183. QS_CRIT_X_();
  11184. QS_onFlush();</code>
  11185. </operation>
  11186. <!--${QS::QS-tx::usr_dict_pre_}-->
  11187. <operation name="usr_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11188. <documentation>/*! Output predefined user-dictionary record
  11189. * @static @private @memberof QS_tx
  11190. *
  11191. * @note This function is only to be used through macro QS_USR_DICTIONARY()
  11192. */
  11193. /*! @static @private @memberof QS_tx */</documentation>
  11194. <!--${QS::QS-tx::usr_dict_pre_::rec}-->
  11195. <parameter name="rec" type="enum_t const"/>
  11196. <!--${QS::QS-tx::usr_dict_pre_::name}-->
  11197. <parameter name="name" type="char const * const"/>
  11198. <code>QS_CRIT_STAT_
  11199. QS_CRIT_E_();
  11200. QS_beginRec_((uint_fast8_t)QS_USR_DICT);
  11201. QS_u8_raw_((uint8_t)rec);
  11202. QS_str_raw_(name);
  11203. QS_endRec_();
  11204. QS_CRIT_X_();
  11205. QS_onFlush();</code>
  11206. </operation>
  11207. <!--${QS::QS-tx::enum_dict_pre_}-->
  11208. <operation name="enum_dict_pre_" type="void" visibility="0x00" properties="0x01">
  11209. <documentation>/*! Output predefined enum-dictionary record
  11210. * @static @private @memberof QS_tx
  11211. *
  11212. * @note This function is only to be used through macro QS_ENUM_DICTIONARY()
  11213. */
  11214. /*! @static @private @memberof QS_tx */</documentation>
  11215. <!--${QS::QS-tx::enum_dict_pre_::value}-->
  11216. <parameter name="value" type="enum_t const"/>
  11217. <!--${QS::QS-tx::enum_dict_pre_::group}-->
  11218. <parameter name="group" type="uint8_t const"/>
  11219. <!--${QS::QS-tx::enum_dict_pre_::name}-->
  11220. <parameter name="name" type="char const * const"/>
  11221. <code>QS_CRIT_STAT_
  11222. QS_CRIT_E_();
  11223. QS_beginRec_((uint_fast8_t)QS_ENUM_DICT);
  11224. QS_2U8_PRE_((uint8_t)value, group);
  11225. QS_str_raw_(name);
  11226. QS_endRec_();
  11227. QS_CRIT_X_();
  11228. QS_onFlush();</code>
  11229. </operation>
  11230. <!--${QS::QS-tx::ASSERTION}-->
  11231. <operation name="ASSERTION" type="void" visibility="0x00" properties="0x01">
  11232. <documentation>/*! Output the predefined assertion failure trace record
  11233. * @static @public @memberof QS_tx
  11234. *
  11235. * @details
  11236. * This trace record is intended to use from the Q_onAssert() callback.
  11237. */
  11238. /*! @static @public @memberof QS_tx */</documentation>
  11239. <!--${QS::QS-tx::ASSERTION::module}-->
  11240. <parameter name="module" type="char const * const"/>
  11241. <!--${QS::QS-tx::ASSERTION::loc}-->
  11242. <parameter name="loc" type="int_t const"/>
  11243. <!--${QS::QS-tx::ASSERTION::delay}-->
  11244. <parameter name="delay" type="uint32_t const"/>
  11245. <code>QS_BEGIN_NOCRIT_PRE_(QS_ASSERT_FAIL, 0U)
  11246. QS_TIME_PRE_();
  11247. QS_U16_PRE_(loc);
  11248. QS_STR_PRE_((module != (char *)0) ? module : &quot;?&quot;);
  11249. QS_END_NOCRIT_PRE_()
  11250. QS_onFlush();
  11251. for (uint32_t volatile delay_ctr = delay; delay_ctr &gt; 0U; --delay_ctr) {
  11252. }
  11253. QS_onCleanup();</code>
  11254. </operation>
  11255. <!--${QS::QS-tx::target_info_pre_}-->
  11256. <operation name="target_info_pre_" type="void" visibility="0x00" properties="0x00">
  11257. <documentation>/*! Helper function to output the predefined Target-info trace record
  11258. * @static @private @memberof QS_tx
  11259. */
  11260. /*! @static @private @memberof QS_tx */</documentation>
  11261. <!--${QS::QS-tx::target_info_pre_::isReset}-->
  11262. <parameter name="isReset" type="uint8_t const"/>
  11263. <code>static uint8_t const ZERO = (uint8_t)'0';
  11264. static uint8_t const * const TIME = (uint8_t const *)&amp;Q_BUILD_TIME[0];
  11265. static uint8_t const * const DATE = (uint8_t const *)&amp;Q_BUILD_DATE[0];
  11266. static union {
  11267. uint16_t u16;
  11268. uint8_t u8[2];
  11269. } endian_test;
  11270. endian_test.u16 = 0x0102U;
  11271. QS_beginRec_((uint_fast8_t)QS_TARGET_INFO);
  11272. QS_U8_PRE_(isReset);
  11273. QS_U16_PRE_(((endian_test.u8[0] == 0x01U) /* big endian? */
  11274. ? (0x8000U | QP_VERSION)
  11275. : QP_VERSION)); /* target endianness + version number */
  11276. /* send the object sizes... */
  11277. QS_U8_PRE_(Q_SIGNAL_SIZE | (QF_EVENT_SIZ_SIZE &lt;&lt; 4U));
  11278. #ifdef QF_EQUEUE_CTR_SIZE
  11279. QS_U8_PRE_(QF_EQUEUE_CTR_SIZE | (QF_TIMEEVT_CTR_SIZE &lt;&lt; 4U));
  11280. #else
  11281. QS_U8_PRE_(QF_TIMEEVT_CTR_SIZE &lt;&lt; 4U);
  11282. #endif /* QF_EQUEUE_CTR_SIZE */
  11283. #ifdef QF_MPOOL_CTR_SIZE
  11284. QS_U8_PRE_(QF_MPOOL_SIZ_SIZE | (QF_MPOOL_CTR_SIZE &lt;&lt; 4U));
  11285. #else
  11286. QS_U8_PRE_(0U);
  11287. #endif /* QF_MPOOL_CTR_SIZE */
  11288. QS_U8_PRE_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE &lt;&lt; 4U));
  11289. QS_U8_PRE_(QS_TIME_SIZE);
  11290. /* send the limits... */
  11291. QS_U8_PRE_(QF_MAX_ACTIVE);
  11292. QS_U8_PRE_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE &lt;&lt; 4U));
  11293. /* send the build time in three bytes (sec, min, hour)... */
  11294. QS_U8_PRE_((10U * (uint8_t)(TIME[6] - ZERO))
  11295. + (uint8_t)(TIME[7] - ZERO));
  11296. QS_U8_PRE_((10U * (uint8_t)(TIME[3] - ZERO))
  11297. + (uint8_t)(TIME[4] - ZERO));
  11298. if (Q_BUILD_TIME[0] == ' ') {
  11299. QS_U8_PRE_(TIME[1] - ZERO);
  11300. }
  11301. else {
  11302. QS_U8_PRE_((10U * (uint8_t)(TIME[0] - ZERO))
  11303. + (uint8_t)(TIME[1] - ZERO));
  11304. }
  11305. /* send the build date in three bytes (day, month, year) ... */
  11306. if (Q_BUILD_DATE[4] == ' ') {
  11307. QS_U8_PRE_(DATE[5] - ZERO);
  11308. }
  11309. else {
  11310. QS_U8_PRE_((10U * (uint8_t)(DATE[4] - ZERO))
  11311. + (uint8_t)(DATE[5] - ZERO));
  11312. }
  11313. /* convert the 3-letter month to a number 1-12 ... */
  11314. uint8_t b;
  11315. switch ((int_t)DATE[0] + (int_t)DATE[1] + (int_t)DATE[2]) {
  11316. case (int_t)'J' + (int_t)'a' + (int_t)'n':
  11317. b = 1U;
  11318. break;
  11319. case (int_t)'F' + (int_t)'e' + (int_t)'b':
  11320. b = 2U;
  11321. break;
  11322. case (int_t)'M' + (int_t)'a' + (int_t)'r':
  11323. b = 3U;
  11324. break;
  11325. case (int_t)'A' + (int_t)'p' + (int_t)'r':
  11326. b = 4U;
  11327. break;
  11328. case (int_t)'M' + (int_t)'a' + (int_t)'y':
  11329. b = 5U;
  11330. break;
  11331. case (int_t)'J' + (int_t)'u' + (int_t)'n':
  11332. b = 6U;
  11333. break;
  11334. case (int_t)'J' + (int_t)'u' + (int_t)'l':
  11335. b = 7U;
  11336. break;
  11337. case (int_t)'A' + (int_t)'u' + (int_t)'g':
  11338. b = 8U;
  11339. break;
  11340. case (int_t)'S' + (int_t)'e' + (int_t)'p':
  11341. b = 9U;
  11342. break;
  11343. case (int_t)'O' + (int_t)'c' + (int_t)'t':
  11344. b = 10U;
  11345. break;
  11346. case (int_t)'N' + (int_t)'o' + (int_t)'v':
  11347. b = 11U;
  11348. break;
  11349. case (int_t)'D' + (int_t)'e' + (int_t)'c':
  11350. b = 12U;
  11351. break;
  11352. default:
  11353. b = 0U;
  11354. break;
  11355. }
  11356. QS_U8_PRE_(b); /* store the month */
  11357. QS_U8_PRE_((10U * (uint8_t)(DATE[9] - ZERO))
  11358. + (uint8_t)(DATE[10] - ZERO));
  11359. QS_endRec_();</code>
  11360. </operation>
  11361. <!--${QS::QS-tx::onStartup}-->
  11362. <operation name="onStartup" type="uint8_t" visibility="0x00" properties="0x00">
  11363. <documentation>/*! Callback to startup the QS facility
  11364. * @static @public @memberof QS_tx
  11365. */
  11366. /*! @static @public @memberof QS_tx */</documentation>
  11367. <!--${QS::QS-tx::onStartup::arg}-->
  11368. <parameter name="arg" type="void const *"/>
  11369. </operation>
  11370. <!--${QS::QS-tx::onCleanup}-->
  11371. <operation name="onCleanup" type="void" visibility="0x00" properties="0x00">
  11372. <documentation>/*! Callback to cleanup the QS facility
  11373. * @static @public @memberof QS_tx
  11374. */
  11375. /*! @static @public @memberof QS_tx */</documentation>
  11376. </operation>
  11377. <!--${QS::QS-tx::onFlush}-->
  11378. <operation name="onFlush" type="void" visibility="0x00" properties="0x00">
  11379. <documentation>/*! Callback to flush the QS trace data to the host
  11380. * @static @public @memberof QS_tx
  11381. */
  11382. /*! @static @public @memberof QS_tx */</documentation>
  11383. </operation>
  11384. <!--${QS::QS-tx::onGetTime}-->
  11385. <operation name="onGetTime" type="QSTimeCtr" visibility="0x00" properties="0x00">
  11386. <documentation>/*! Callback to obtain a timestamp for a QS record
  11387. * @static @public @memberof QS_tx
  11388. */
  11389. /*! @static @public @memberof QS_tx */</documentation>
  11390. </operation>
  11391. </package>
  11392. <!--${QS::QS-tx-64bit}-->
  11393. <package name="QS-tx-64bit" stereotype="0x02" namespace="QS_">
  11394. <!--${QS::QS-tx-64bit::u64_raw_}-->
  11395. <operation name="u64_raw_" type="void" visibility="0x00" properties="0x01">
  11396. <documentation>/*! Output uint64_t data element without format information
  11397. * @static @private @memberof QS_tx
  11398. */
  11399. /*! @static @private @memberof QS_tx */</documentation>
  11400. <!--${QS::QS-tx-64bit::u64_raw_::d}-->
  11401. <parameter name="d" type="uint64_t"/>
  11402. <code>uint8_t chksum = QS_priv_.chksum;
  11403. uint8_t * const buf = QS_priv_.buf;
  11404. QSCtr head = QS_priv_.head;
  11405. QSCtr const end = QS_priv_.end;
  11406. QS_priv_.used += 8U; /* 8 bytes are about to be added */
  11407. uint_fast8_t i;
  11408. for (i = 8U; i != 0U; --i) {
  11409. uint8_t const b = (uint8_t)d;
  11410. QS_INSERT_ESC_BYTE_(b)
  11411. d &gt;&gt;= 8U;
  11412. }
  11413. QS_priv_.head = head; /* save the head */
  11414. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11415. </operation>
  11416. <!--${QS::QS-tx-64bit::u64_fmt_}-->
  11417. <operation name="u64_fmt_" type="void" visibility="0x00" properties="0x01">
  11418. <documentation>/*! Output uint64_t data element with format information
  11419. * @static @private @memberof QS_tx
  11420. *
  11421. * @sa QS_U64(), QS_I64()
  11422. */
  11423. /*! @static @private @memberof QS_tx */</documentation>
  11424. <!--${QS::QS-tx-64bit::u64_fmt_::format}-->
  11425. <parameter name="format" type="uint8_t"/>
  11426. <!--${QS::QS-tx-64bit::u64_fmt_::d}-->
  11427. <parameter name="d" type="uint64_t"/>
  11428. <code>uint8_t chksum = QS_priv_.chksum;
  11429. uint8_t * const buf = QS_priv_.buf;
  11430. QSCtr head = QS_priv_.head;
  11431. QSCtr const end = QS_priv_.end;
  11432. QS_priv_.used += 9U; /* 9 bytes are about to be added */
  11433. QS_INSERT_ESC_BYTE_(format) /* insert the format byte */
  11434. /* output 8 bytes of data... */
  11435. uint_fast8_t i;
  11436. for (i = 8U; i != 0U; --i) {
  11437. format = (uint8_t)d;
  11438. QS_INSERT_ESC_BYTE_(format)
  11439. d &gt;&gt;= 8U;
  11440. }
  11441. QS_priv_.head = head; /* save the head */
  11442. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11443. </operation>
  11444. </package>
  11445. <!--${QS::QS-tx-fp}-->
  11446. <package name="QS-tx-fp" stereotype="0x02" namespace="QS_">
  11447. <!--${QS::QS-tx-fp::f32_fmt_}-->
  11448. <operation name="f32_fmt_" type="void" visibility="0x00" properties="0x01">
  11449. <documentation>/*! Output 32-bit floating point data element with format information
  11450. * @static @private @memberof QS_tx
  11451. *
  11452. * @sa QS_F32()
  11453. */
  11454. /*! @static @private @memberof QS_tx */</documentation>
  11455. <!--${QS::QS-tx-fp::f32_fmt_::format}-->
  11456. <parameter name="format" type="uint8_t const"/>
  11457. <!--${QS::QS-tx-fp::f32_fmt_::d}-->
  11458. <parameter name="d" type="float32_t const"/>
  11459. <code>union F32Rep {
  11460. float32_t f;
  11461. uint32_t u;
  11462. } fu32; /* the internal binary representation */
  11463. uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
  11464. uint8_t * const buf = QS_priv_.buf;
  11465. QSCtr head = QS_priv_.head;
  11466. QSCtr const end = QS_priv_.end;
  11467. uint_fast8_t i;
  11468. fu32.f = d; /* assign the binary representation */
  11469. QS_priv_.used += 5U; /* 5 bytes about to be added */
  11470. QS_INSERT_ESC_BYTE_(format) /* insert the format byte */
  11471. /* insert 4 bytes... */
  11472. for (i = 4U; i != 0U; --i) {
  11473. QS_INSERT_ESC_BYTE_((uint8_t)fu32.u)
  11474. fu32.u &gt;&gt;= 8U;
  11475. }
  11476. QS_priv_.head = head; /* save the head */
  11477. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11478. </operation>
  11479. <!--${QS::QS-tx-fp::f64_fmt_}-->
  11480. <operation name="f64_fmt_" type="void" visibility="0x00" properties="0x01">
  11481. <documentation>/*! Output 64-bit floating point data element with format information
  11482. * @static @private @memberof QS_tx
  11483. *
  11484. * @sa QS_F64()
  11485. */
  11486. /*! @static @private @memberof QS_tx */</documentation>
  11487. <!--${QS::QS-tx-fp::f64_fmt_::format}-->
  11488. <parameter name="format" type="uint8_t const"/>
  11489. <!--${QS::QS-tx-fp::f64_fmt_::d}-->
  11490. <parameter name="d" type="float64_t const"/>
  11491. <code>union F64Rep {
  11492. float64_t d;
  11493. uint32_t u[2];
  11494. } fu64; /* the internal binary representation */
  11495. uint8_t chksum = QS_priv_.chksum;
  11496. uint8_t * const buf = QS_priv_.buf;
  11497. QSCtr head = QS_priv_.head;
  11498. QSCtr const end = QS_priv_.end;
  11499. uint32_t i;
  11500. /* static constant untion to detect endianness of the machine */
  11501. static union U32Rep {
  11502. uint32_t u32;
  11503. uint8_t u8;
  11504. } const endian = { 1U };
  11505. fu64.d = d; /* assign the binary representation */
  11506. /* is this a big-endian machine? */
  11507. if (endian.u8 == 0U) {
  11508. /* swap fu64.u[0] &lt;-&gt; fu64.u[1]... */
  11509. i = fu64.u[0];
  11510. fu64.u[0] = fu64.u[1];
  11511. fu64.u[1] = i;
  11512. }
  11513. QS_priv_.used += 9U; /* 9 bytes about to be added */
  11514. QS_INSERT_ESC_BYTE_(format) /* insert the format byte */
  11515. /* output 4 bytes from fu64.u[0]... */
  11516. for (i = 4U; i != 0U; --i) {
  11517. QS_INSERT_ESC_BYTE_((uint8_t)fu64.u[0])
  11518. fu64.u[0] &gt;&gt;= 8U;
  11519. }
  11520. /* output 4 bytes from fu64.u[1]... */
  11521. for (i = 4U; i != 0U; --i) {
  11522. QS_INSERT_ESC_BYTE_((uint8_t)fu64.u[1])
  11523. fu64.u[1] &gt;&gt;= 8U;
  11524. }
  11525. QS_priv_.head = head; /* save the head */
  11526. QS_priv_.chksum = chksum; /* save the checksum */</code>
  11527. </operation>
  11528. </package>
  11529. <!--${QS::QS-rx}-->
  11530. <package name="QS-rx" stereotype="0x02" namespace="QS_">
  11531. <!--${QS::QS-rx::rx}-->
  11532. <class name="rx">
  11533. <documentation>/*! @brief QS software tracing parameters for QS input (QS-RX)
  11534. * @class QS_rx
  11535. */</documentation>
  11536. <!--${QS::QS-rx::rx::currObj[8]}-->
  11537. <attribute name="currObj[8]" type="void *" visibility="0x00" properties="0x00">
  11538. <documentation>* current objects</documentation>
  11539. </attribute>
  11540. <!--${QS::QS-rx::rx::buf}-->
  11541. <attribute name="buf" type="uint8_t *" visibility="0x00" properties="0x00">
  11542. <documentation>* pointer to the start of the ring buffer</documentation>
  11543. </attribute>
  11544. <!--${QS::QS-rx::rx:: end}-->
  11545. <attribute name=" end" type="QSCtr" visibility="0x00" properties="0x00">
  11546. <documentation>* offset of the end of the ring buffer</documentation>
  11547. </attribute>
  11548. <!--${QS::QS-rx::rx::head}-->
  11549. <attribute name="head" type="QSCtr volatile" visibility="0x00" properties="0x00">
  11550. <documentation>* offset to where next byte will be inserted</documentation>
  11551. </attribute>
  11552. <!--${QS::QS-rx::rx::tail}-->
  11553. <attribute name="tail" type="QSCtr volatile" visibility="0x00" properties="0x00">
  11554. <documentation>* offset of where next byte will be extracted</documentation>
  11555. </attribute>
  11556. <!--${QS::QS-rx::rx::inTestLoop}-->
  11557. <attribute name="inTestLoop?def Q_UTEST" type="bool" visibility="0x00" properties="0x00">
  11558. <documentation>* QUTest event loop is running</documentation>
  11559. </attribute>
  11560. </class>
  11561. <!--${QS::QS-rx::rxPriv_}-->
  11562. <attribute name="rxPriv_" type="QS_rx" visibility="0x00" properties="0x01">
  11563. <documentation>/*! the only instance of the QS-RX object (Singleton)
  11564. * @static @private @memberof QS_rx
  11565. */</documentation>
  11566. </attribute>
  11567. <!--${QS::QS-rx::QSpyObjKind}-->
  11568. <attribute name="QSpyObjKind" type="enum" visibility="0x04" properties="0x01">
  11569. <documentation>/*! Kinds of objects used in QS_setCurrObj() and QS_queryCurrObj()
  11570. * @static @public @memberof QS_rx
  11571. */</documentation>
  11572. <code>{
  11573. SM_OBJ, /*!&lt; state machine object */
  11574. AO_OBJ, /*!&lt; active object */
  11575. MP_OBJ, /*!&lt; event pool object */
  11576. EQ_OBJ, /*!&lt; raw queue object */
  11577. TE_OBJ, /*!&lt; time event object */
  11578. AP_OBJ, /*!&lt; generic Application-specific object */
  11579. MAX_OBJ
  11580. };</code>
  11581. </attribute>
  11582. <!--${QS::QS-rx::OSpyObjCombnation}-->
  11583. <attribute name="OSpyObjCombnation" type="enum" visibility="0x04" properties="0x01">
  11584. <documentation>/*! Object combinations for QS_setCurrObj() and QS_queryCurrObj()
  11585. * @static @public @memberof QS_rx
  11586. */</documentation>
  11587. <code>{
  11588. SM_AO_OBJ = (enum_t)MAX_OBJ /*!&lt; combination of SM and AO */
  11589. };</code>
  11590. </attribute>
  11591. <!--${QS::QS-rx::rxInitBuf}-->
  11592. <operation name="rxInitBuf" type="void" visibility="0x00" properties="0x00">
  11593. <documentation>/*! Initialize the QS-RX data buffer
  11594. * @static @public @memberof QS_rx
  11595. *
  11596. * @details
  11597. * This function should be called from QS::onStartup() to provide QS-RX
  11598. * with the receive data buffer.
  11599. *
  11600. * @param[in] sto pointer to the memory block for input buffer
  11601. * @param[in] stoSize the size of this block [bytes]. The size of the
  11602. * QS-RX buffer cannot exceed 64KB.
  11603. *
  11604. * @note
  11605. * QS-RX can work with quite small data buffers, but you will start
  11606. * losing data if the buffer is not drained fast enough (e.g., in the
  11607. * idle task).
  11608. *
  11609. * @note
  11610. * If the data input rate exceeds the QS-RX processing rate, the data
  11611. * will be lost, but the QS protocol will notice that:
  11612. * (1) that the checksum in the incomplete QS records will fail; and
  11613. * (2) the sequence counter in QS records will show discontinuities.
  11614. *
  11615. * The QS-RX channel will report any data errors by sending the
  11616. * QS_RX_DATA_ERROR trace record.
  11617. */
  11618. /*! @static @public @memberof QS_rx */</documentation>
  11619. <!--${QS::QS-rx::rxInitBuf::sto}-->
  11620. <parameter name="sto" type="uint8_t * const"/>
  11621. <!--${QS::QS-rx::rxInitBuf::stoSize}-->
  11622. <parameter name="stoSize" type="uint16_t const"/>
  11623. <code>QS_rxPriv_.buf = &amp;sto[0];
  11624. QS_rxPriv_.end = (QSCtr)stoSize;
  11625. QS_rxPriv_.head = 0U;
  11626. QS_rxPriv_.tail = 0U;
  11627. QS_rxPriv_.currObj[SM_OBJ] = (void *)0;
  11628. QS_rxPriv_.currObj[AO_OBJ] = (void *)0;
  11629. QS_rxPriv_.currObj[MP_OBJ] = (void *)0;
  11630. QS_rxPriv_.currObj[EQ_OBJ] = (void *)0;
  11631. QS_rxPriv_.currObj[TE_OBJ] = (void *)0;
  11632. QS_rxPriv_.currObj[AP_OBJ] = (void *)0;
  11633. QS_RX_TRAN_(WAIT4_SEQ);
  11634. l_rx.esc = 0U;
  11635. l_rx.seq = 0U;
  11636. l_rx.chksum = 0U;
  11637. QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
  11638. QS_OBJ_PRE_(&amp;QS_rxPriv_);
  11639. QS_STR_PRE_(&quot;QS_RX&quot;);
  11640. QS_endRec_();
  11641. /* no QS_REC_DONE(), because QS is not running yet */
  11642. #ifdef Q_UTEST
  11643. QS_testData.tpNum = 0U;
  11644. QS_testData.testTime = 0U;
  11645. #endif /* Q_UTEST */</code>
  11646. </operation>
  11647. <!--${QS::QS-rx::rxPut}-->
  11648. <operation name="rxPut" type="bool" visibility="0x00" properties="0x02">
  11649. <documentation>/*! Put one byte into the QS-RX lock-free buffer
  11650. * @static @public @memberof QS_rx
  11651. */
  11652. /*! @static @public @memberof QS_rx */</documentation>
  11653. <!--${QS::QS-rx::rxPut::b}-->
  11654. <parameter name="b" type="uint8_t const"/>
  11655. <code>QSCtr head = QS_rxPriv_.head + 1U;
  11656. if (head == QS_rxPriv_.end) {
  11657. head = 0U;
  11658. }
  11659. if (head != QS_rxPriv_.tail) { /* buffer NOT full? */
  11660. QS_rxPriv_.buf[QS_rxPriv_.head] = b;
  11661. QS_rxPriv_.head = head; /* update the head to a *valid* index */
  11662. return true; /* byte placed in the buffer */
  11663. }
  11664. else {
  11665. return false; /* byte NOT placed in the buffer */
  11666. }</code>
  11667. </operation>
  11668. <!--${QS::QS-rx::rxGetNfree}-->
  11669. <operation name="rxGetNfree" type="uint16_t" visibility="0x00" properties="0x00">
  11670. <documentation>/*! Obtain the number of free bytes in the QS-RX data buffer
  11671. * @static @public @memberof QS_rx
  11672. *
  11673. * @details
  11674. * This function is intended to be called from the ISR that reads the
  11675. * QS-RX bytes from the QSPY application. The function returns the
  11676. * conservative number of free bytes currently available in the buffer,
  11677. * assuming that the head pointer is not being moved concurrently.
  11678. * The tail pointer might be moving, meaning that bytes can be
  11679. * concurrently removed from the buffer.
  11680. */
  11681. /*! @static @public @memberof QS_rx */</documentation>
  11682. <code>QSCtr const head = QS_rxPriv_.head;
  11683. if (head == QS_rxPriv_.tail) { /* buffer empty? */
  11684. return (uint16_t)(QS_rxPriv_.end - 1U);
  11685. }
  11686. else if (head &lt; QS_rxPriv_.tail) {
  11687. return (uint16_t)(QS_rxPriv_.tail - (head + 1U));
  11688. }
  11689. else {
  11690. return (uint16_t)(QS_rxPriv_.end + QS_rxPriv_.tail - (head + 1U));
  11691. }</code>
  11692. </operation>
  11693. <!--${QS::QS-rx::doInput}-->
  11694. <operation name="doInput" type="void" visibility="0x00" properties="0x00">
  11695. <documentation>/*! Perform the QS-RX input (implemented in some QS ports)
  11696. * @static @public @memberof QS_rx
  11697. */
  11698. /*! @static @public @memberof QS_rx */</documentation>
  11699. </operation>
  11700. <!--${QS::QS-rx::setCurrObj}-->
  11701. <operation name="setCurrObj" type="void" visibility="0x00" properties="0x00">
  11702. <documentation>/*! Set the &quot;current object&quot; in the Target
  11703. * @static @public @memberof QS_rx
  11704. *
  11705. * @details
  11706. * This function sets the &quot;current object&quot; in the Target.
  11707. */
  11708. /*! @static @public @memberof QS_rx */</documentation>
  11709. <!--${QS::QS-rx::setCurrObj::obj_kind}-->
  11710. <parameter name="obj_kind" type="uint8_t const"/>
  11711. <!--${QS::QS-rx::setCurrObj::obj_ptr}-->
  11712. <parameter name="obj_ptr" type="void * const"/>
  11713. <code>Q_REQUIRE_ID(100, obj_kind &lt; Q_DIM(QS_rxPriv_.currObj));
  11714. QS_rxPriv_.currObj[obj_kind] = obj_ptr;</code>
  11715. </operation>
  11716. <!--${QS::QS-rx::queryCurrObj}-->
  11717. <operation name="queryCurrObj" type="void" visibility="0x00" properties="0x00">
  11718. <documentation>/*! Query the &quot;current object&quot; in the Target
  11719. * @static @public @memberof QS_rx
  11720. *
  11721. * @details
  11722. * This function programmatically generates the response to the query for
  11723. * a &quot;current object&quot;.
  11724. */
  11725. /*! @static @public @memberof QS_rx */</documentation>
  11726. <!--${QS::QS-rx::queryCurrObj::obj_kind}-->
  11727. <parameter name="obj_kind" type="uint8_t const"/>
  11728. <code>if (QS_rxPriv_.currObj[obj_kind] != (void *)0) {
  11729. QS_CRIT_STAT_
  11730. QS_CRIT_E_();
  11731. QS_beginRec_((uint_fast8_t)QS_QUERY_DATA);
  11732. QS_TIME_PRE_(); /* timestamp */
  11733. QS_U8_PRE_(obj_kind); /* object kind */
  11734. QS_OBJ_PRE_(QS_rxPriv_.currObj[obj_kind]);
  11735. switch (obj_kind) {
  11736. case (uint8_t)SM_OBJ: /* intentionally fall through */
  11737. case (uint8_t)AO_OBJ:
  11738. QS_FUN_PRE_((*((QHsm *)QS_rxPriv_.currObj[obj_kind])-&gt;vptr
  11739. -&gt;getStateHandler)(
  11740. ((QHsm *)QS_rxPriv_.currObj[obj_kind])));
  11741. break;
  11742. case (uint8_t)MP_OBJ:
  11743. QS_MPC_PRE_(((QMPool *)QS_rxPriv_.currObj[obj_kind])
  11744. -&gt;nFree);
  11745. QS_MPC_PRE_(((QMPool *)QS_rxPriv_.currObj[obj_kind])
  11746. -&gt;nMin);
  11747. break;
  11748. case (uint8_t)EQ_OBJ:
  11749. QS_EQC_PRE_(((QEQueue *)QS_rxPriv_.currObj[obj_kind])
  11750. -&gt;nFree);
  11751. QS_EQC_PRE_(((QEQueue *)QS_rxPriv_.currObj[obj_kind])
  11752. -&gt;nMin);
  11753. break;
  11754. case (uint8_t)TE_OBJ:
  11755. QS_OBJ_PRE_(((QTimeEvt *)QS_rxPriv_.currObj[obj_kind])
  11756. -&gt;act);
  11757. QS_TEC_PRE_(((QTimeEvt *)QS_rxPriv_.currObj[obj_kind])
  11758. -&gt;ctr);
  11759. QS_TEC_PRE_(((QTimeEvt *)QS_rxPriv_.currObj[obj_kind])
  11760. -&gt;interval);
  11761. QS_SIG_PRE_(((QTimeEvt *)QS_rxPriv_.currObj[obj_kind])
  11762. -&gt;super.sig);
  11763. QS_U8_PRE_ (((QTimeEvt *)QS_rxPriv_.currObj[obj_kind])
  11764. -&gt;super.refCtr_);
  11765. break;
  11766. default:
  11767. /* intentionally empty */
  11768. break;
  11769. }
  11770. QS_endRec_();
  11771. QS_CRIT_X_();
  11772. QS_REC_DONE(); /* user callback (if defined) */
  11773. }
  11774. else {
  11775. QS_rxReportError_((int8_t)QS_RX_QUERY_CURR);
  11776. }</code>
  11777. </operation>
  11778. <!--${QS::QS-rx::rxParse}-->
  11779. <operation name="rxParse" type="void" visibility="0x00" properties="0x00">
  11780. <documentation>/*! Parse all bytes present in the QS-RX data buffer
  11781. * @static @public @memberof QS_rx
  11782. */
  11783. /*! @static @public @memberof QS_rx */</documentation>
  11784. <code>QSCtr tail = QS_rxPriv_.tail;
  11785. while (QS_rxPriv_.head != tail) { /* QS-RX buffer NOT empty? */
  11786. uint8_t b = QS_rxPriv_.buf[tail];
  11787. ++tail;
  11788. if (tail == QS_rxPriv_.end) {
  11789. tail = 0U;
  11790. }
  11791. QS_rxPriv_.tail = tail; /* update the tail to a *valid* index */
  11792. if (l_rx.esc != 0U) { /* escaped byte arrived? */
  11793. l_rx.esc = 0U;
  11794. b ^= QS_ESC_XOR;
  11795. l_rx.chksum += b;
  11796. QS_rxParseData_(b);
  11797. }
  11798. else if (b == QS_ESC) {
  11799. l_rx.esc = 1U;
  11800. }
  11801. else if (b == QS_FRAME) {
  11802. /* get ready for the next frame */
  11803. b = l_rx.state; /* save the current state in b */
  11804. l_rx.esc = 0U;
  11805. QS_RX_TRAN_(WAIT4_SEQ);
  11806. if (l_rx.chksum == QS_GOOD_CHKSUM) {
  11807. l_rx.chksum = 0U;
  11808. QS_rxHandleGoodFrame_(b);
  11809. }
  11810. else { /* bad checksum */
  11811. l_rx.chksum = 0U;
  11812. QS_rxReportError_(0x41);
  11813. QS_rxHandleBadFrame_(b);
  11814. }
  11815. }
  11816. else {
  11817. l_rx.chksum += b;
  11818. QS_rxParseData_(b);
  11819. }
  11820. }</code>
  11821. </operation>
  11822. <!--${QS::QS-rx::rxHandleGoodFrame_}-->
  11823. <operation name="rxHandleGoodFrame_" type="void" visibility="0x00" properties="0x00">
  11824. <documentation>/*! internal function to handle incoming (QS-RX) packet
  11825. * @static @private @memberof QS_rx
  11826. */
  11827. /*! @static @private @memberof QS_rx */</documentation>
  11828. <!--${QS::QS-rx::rxHandleGoodFram~::state}-->
  11829. <parameter name="state" type="uint8_t const"/>
  11830. <code>uint8_t i;
  11831. uint8_t *ptr;
  11832. QS_CRIT_STAT_
  11833. switch (state) {
  11834. case WAIT4_INFO_FRAME: {
  11835. /* no need to report Ack or Done */
  11836. QS_CRIT_E_();
  11837. QS_target_info_pre_(0U); /* send only Target info */
  11838. QS_CRIT_X_();
  11839. break;
  11840. }
  11841. case WAIT4_RESET_FRAME: {
  11842. /* no need to report Ack or Done, because Target resets */
  11843. QS_onReset(); /* reset the Target */
  11844. break;
  11845. }
  11846. case WAIT4_CMD_PARAM1: /* intentionally fall-through */
  11847. case WAIT4_CMD_PARAM2: /* intentionally fall-through */
  11848. case WAIT4_CMD_PARAM3: /* intentionally fall-through */
  11849. case WAIT4_CMD_FRAME: {
  11850. QS_rxReportAck_((int8_t)QS_RX_COMMAND);
  11851. QS_onCommand(l_rx.var.cmd.cmdId, l_rx.var.cmd.param1,
  11852. l_rx.var.cmd.param2, l_rx.var.cmd.param3);
  11853. #ifdef Q_UTEST
  11854. #if Q_UTEST != 0
  11855. QS_processTestEvts_(); /* process all events produced */
  11856. #endif /* Q_UTEST != 0 */
  11857. #endif /* Q_UTEST */
  11858. QS_rxReportDone_((int8_t)QS_RX_COMMAND);
  11859. break;
  11860. }
  11861. case WAIT4_TICK_FRAME: {
  11862. QS_rxReportAck_((int8_t)QS_RX_TICK);
  11863. #ifdef Q_UTEST
  11864. QTimeEvt_tick1_((uint_fast8_t)l_rx.var.tick.rate, &amp;QS_rxPriv_);
  11865. #if Q_UTEST != 0
  11866. QS_processTestEvts_(); /* process all events produced */
  11867. #endif /* Q_UTEST != 0 */
  11868. #else
  11869. QTimeEvt_tick_((uint_fast8_t)l_rx.var.tick.rate, &amp;QS_rxPriv_);
  11870. #endif /* Q_UTEST */
  11871. QS_rxReportDone_((int8_t)QS_RX_TICK);
  11872. break;
  11873. }
  11874. case WAIT4_PEEK_FRAME: {
  11875. /* no need to report Ack or Done */
  11876. QS_CRIT_E_();
  11877. QS_beginRec_((uint_fast8_t)QS_PEEK_DATA);
  11878. ptr = (uint8_t *)QS_rxPriv_.currObj[AP_OBJ];
  11879. ptr = &amp;ptr[l_rx.var.peek.offs];
  11880. QS_TIME_PRE_(); /* timestamp */
  11881. QS_U16_PRE_(l_rx.var.peek.offs); /* data offset */
  11882. QS_U8_PRE_(l_rx.var.peek.size); /* data size */
  11883. QS_U8_PRE_(l_rx.var.peek.num); /* number of data items */
  11884. for (i = 0U; i &lt; l_rx.var.peek.num; ++i) {
  11885. switch (l_rx.var.peek.size) {
  11886. case 1:
  11887. QS_U8_PRE_(ptr[i]);
  11888. break;
  11889. case 2:
  11890. QS_U16_PRE_(((uint16_t *)ptr)[i]);
  11891. break;
  11892. case 4:
  11893. QS_U32_PRE_(((uint32_t *)ptr)[i]);
  11894. break;
  11895. default:
  11896. /* intentionally empty */
  11897. break;
  11898. }
  11899. }
  11900. QS_endRec_();
  11901. QS_CRIT_X_();
  11902. QS_REC_DONE(); /* user callback (if defined) */
  11903. break;
  11904. }
  11905. case WAIT4_POKE_DATA: {
  11906. /* received less than expected poke data items */
  11907. QS_rxReportError_((int8_t)QS_RX_POKE);
  11908. break;
  11909. }
  11910. case WAIT4_POKE_FRAME: {
  11911. QS_rxReportAck_((int8_t)QS_RX_POKE);
  11912. /* no need to report done */
  11913. break;
  11914. }
  11915. case WAIT4_FILL_FRAME: {
  11916. QS_rxReportAck_((int8_t)QS_RX_FILL);
  11917. ptr = (uint8_t *)QS_rxPriv_.currObj[AP_OBJ];
  11918. ptr = &amp;ptr[l_rx.var.poke.offs];
  11919. for (i = 0U; i &lt; l_rx.var.poke.num; ++i) {
  11920. switch (l_rx.var.poke.size) {
  11921. case 1:
  11922. ptr[i] = (uint8_t)l_rx.var.poke.data;
  11923. break;
  11924. case 2:
  11925. ((uint16_t *)ptr)[i]
  11926. = (uint16_t)l_rx.var.poke.data;
  11927. break;
  11928. case 4:
  11929. ((uint32_t *)ptr)[i] = l_rx.var.poke.data;
  11930. break;
  11931. default:
  11932. /* intentionally empty */
  11933. break;
  11934. }
  11935. }
  11936. break;
  11937. }
  11938. case WAIT4_FILTER_FRAME: {
  11939. QS_rxReportAck_(l_rx.var.flt.recId);
  11940. /* apply the received filters */
  11941. if (l_rx.var.flt.recId == (int8_t)QS_RX_GLB_FILTER) {
  11942. for (i = 0U; i &lt; Q_DIM(QS_priv_.glbFilter); ++i) {
  11943. QS_priv_.glbFilter[i] = l_rx.var.flt.data[i];
  11944. }
  11945. /* leave the &quot;not maskable&quot; filters enabled,
  11946. * see qs.h, Miscellaneous QS records (not maskable)
  11947. */
  11948. QS_priv_.glbFilter[0] |= 0x01U;
  11949. QS_priv_.glbFilter[7] |= 0xFCU;
  11950. QS_priv_.glbFilter[8] |= 0x7FU;
  11951. /* never enable the last 3 records (0x7D, 0x7E, 0x7F) */
  11952. QS_priv_.glbFilter[15] &amp;= 0x1FU;
  11953. }
  11954. else if (l_rx.var.flt.recId == (int8_t)QS_RX_LOC_FILTER) {
  11955. for (i = 0U; i &lt; Q_DIM(QS_priv_.locFilter); ++i) {
  11956. QS_priv_.locFilter[i] = l_rx.var.flt.data[i];
  11957. }
  11958. /* leave QS_ID == 0 always on */
  11959. QS_priv_.locFilter[0] |= 0x01U;
  11960. }
  11961. else {
  11962. QS_rxReportError_(l_rx.var.flt.recId);
  11963. }
  11964. /* no need to report Done */
  11965. break;
  11966. }
  11967. case WAIT4_OBJ_FRAME: {
  11968. i = l_rx.var.obj.kind;
  11969. if (i &lt; (uint8_t)MAX_OBJ) {
  11970. if (l_rx.var.obj.recId == (int8_t)QS_RX_CURR_OBJ) {
  11971. QS_rxPriv_.currObj[i] = (void *)l_rx.var.obj.addr;
  11972. QS_rxReportAck_((int8_t)QS_RX_CURR_OBJ);
  11973. }
  11974. else if (l_rx.var.obj.recId == (int8_t)QS_RX_AO_FILTER) {
  11975. if (l_rx.var.obj.addr != 0U) {
  11976. int_fast16_t const filter =
  11977. (int_fast16_t)((QActive *)l_rx.var.obj.addr)-&gt;prio;
  11978. QS_locFilter_((i == 0U)
  11979. ? filter
  11980. :-filter);
  11981. QS_rxReportAck_((int8_t)QS_RX_AO_FILTER);
  11982. }
  11983. else {
  11984. QS_rxReportError_((int8_t)QS_RX_AO_FILTER);
  11985. }
  11986. }
  11987. else {
  11988. QS_rxReportError_(l_rx.var.obj.recId);
  11989. }
  11990. }
  11991. /* both SM and AO */
  11992. else if (i == (uint8_t)SM_AO_OBJ) {
  11993. if (l_rx.var.obj.recId == (int8_t)QS_RX_CURR_OBJ) {
  11994. QS_rxPriv_.currObj[SM_OBJ] = (void *)l_rx.var.obj.addr;
  11995. QS_rxPriv_.currObj[AO_OBJ] = (void *)l_rx.var.obj.addr;
  11996. }
  11997. QS_rxReportAck_(l_rx.var.obj.recId);
  11998. }
  11999. else {
  12000. QS_rxReportError_(l_rx.var.obj.recId);
  12001. }
  12002. break;
  12003. }
  12004. case WAIT4_QUERY_FRAME: {
  12005. QS_queryCurrObj(l_rx.var.obj.kind);
  12006. break;
  12007. }
  12008. case WAIT4_EVT_FRAME: {
  12009. /* NOTE: Ack was already reported in the WAIT4_EVT_LEN state */
  12010. #ifdef Q_UTEST
  12011. QS_onTestEvt(l_rx.var.evt.e); /* adjust the event, if needed */
  12012. #endif /* Q_UTEST */
  12013. i = 0U; /* use 'i' as status, 0 == success,no-recycle */
  12014. if (l_rx.var.evt.prio == 0U) { /* publish */
  12015. QActive_publish_(l_rx.var.evt.e, &amp;QS_rxPriv_, 0U);
  12016. }
  12017. else if (l_rx.var.evt.prio &lt; QF_MAX_ACTIVE) {
  12018. if (!QACTIVE_POST_X(QActive_registry_[l_rx.var.evt.prio],
  12019. l_rx.var.evt.e,
  12020. 0U, /* margin */
  12021. &amp;QS_rxPriv_))
  12022. {
  12023. /* failed QACTIVE_POST() recycles the event */
  12024. i = 0x80U; /* failure status, no recycle */
  12025. }
  12026. }
  12027. else if (l_rx.var.evt.prio == 255U) { /* special prio */
  12028. /* dispatch to the current SM object */
  12029. if (QS_rxPriv_.currObj[SM_OBJ] != (void *)0) {
  12030. /* increment the ref-ctr to simulate the situation
  12031. * when the event is just retreived from a queue.
  12032. * This is expected for the following QF_gc() call.
  12033. */
  12034. ++l_rx.var.evt.e-&gt;refCtr_;
  12035. QHSM_DISPATCH((QHsm *)QS_rxPriv_.currObj[SM_OBJ],
  12036. l_rx.var.evt.e, 0U);
  12037. i = 0x01U; /* success status, recycle needed */
  12038. }
  12039. else {
  12040. i = 0x81U; /* failure status, recycle needed */
  12041. }
  12042. }
  12043. else if (l_rx.var.evt.prio == 254U) { /* special prio */
  12044. /* init the current SM object&quot; */
  12045. if (QS_rxPriv_.currObj[SM_OBJ] != (void *)0) {
  12046. /* increment the ref-ctr to simulate the situation
  12047. * when the event is just retreived from a queue.
  12048. * This is expected for the following QF_gc() call.
  12049. */
  12050. ++l_rx.var.evt.e-&gt;refCtr_;
  12051. QHSM_INIT((QHsm *)QS_rxPriv_.currObj[SM_OBJ],
  12052. l_rx.var.evt.e, 0U);
  12053. i = 0x01U; /* success status, recycle needed */
  12054. }
  12055. else {
  12056. i = 0x81U; /* failure status, recycle needed */
  12057. }
  12058. }
  12059. else if (l_rx.var.evt.prio == 253U) { /* special prio */
  12060. /* post to the current AO */
  12061. if (QS_rxPriv_.currObj[AO_OBJ] != (void *)0) {
  12062. if (!QACTIVE_POST_X(
  12063. (QActive *)QS_rxPriv_.currObj[AO_OBJ],
  12064. l_rx.var.evt.e,
  12065. 0U, /* margin */
  12066. &amp;QS_rxPriv_))
  12067. {
  12068. /* failed QACTIVE_POST() recycles the event */
  12069. i = 0x80U; /* failure status, no recycle */
  12070. }
  12071. }
  12072. else {
  12073. i = 0x81U; /* failure status, recycle needed */
  12074. }
  12075. }
  12076. else {
  12077. i = 0x81U; /* failure status, recycle needed */
  12078. }
  12079. #if (QF_MAX_EPOOL &gt; 0U)
  12080. if ((i &amp; 0x01U) != 0U) { /* recycle needed? */
  12081. QF_gc(l_rx.var.evt.e);
  12082. }
  12083. #endif
  12084. if ((i &amp; 0x80U) != 0U) { /* failure? */
  12085. QS_rxReportError_((int8_t)QS_RX_EVENT);
  12086. }
  12087. else {
  12088. #ifdef Q_UTEST
  12089. #if Q_UTEST != 0
  12090. QS_processTestEvts_(); /* process all events produced */
  12091. #endif /* Q_UTEST != 0 */
  12092. #endif /* Q_UTEST */
  12093. QS_rxReportDone_((int8_t)QS_RX_EVENT);
  12094. }
  12095. break;
  12096. }
  12097. #ifdef Q_UTEST
  12098. case WAIT4_TEST_SETUP_FRAME: {
  12099. QS_rxReportAck_((int8_t)QS_RX_TEST_SETUP);
  12100. QS_testData.tpNum = 0U; /* clear the Test-Probes */
  12101. QS_testData.testTime = 0U; /* clear the time tick */
  12102. /* don't clear current objects */
  12103. QS_onTestSetup(); /* application-specific test setup */
  12104. /* no need to report Done */
  12105. break;
  12106. }
  12107. case WAIT4_TEST_TEARDOWN_FRAME: {
  12108. QS_rxReportAck_((int8_t)QS_RX_TEST_TEARDOWN);
  12109. QS_onTestTeardown(); /* application-specific test teardown */
  12110. /* no need to report Done */
  12111. break;
  12112. }
  12113. case WAIT4_TEST_CONTINUE_FRAME: {
  12114. QS_rxReportAck_((int8_t)QS_RX_TEST_CONTINUE);
  12115. QS_rxPriv_.inTestLoop = false; /* exit the QUTest loop */
  12116. /* no need to report Done */
  12117. break;
  12118. }
  12119. case WAIT4_TEST_PROBE_FRAME: {
  12120. QS_rxReportAck_((int8_t)QS_RX_TEST_PROBE);
  12121. Q_ASSERT_ID(815, QS_testData.tpNum
  12122. &lt; (sizeof(QS_testData.tpBuf) / sizeof(QS_testData.tpBuf[0])));
  12123. QS_testData.tpBuf[QS_testData.tpNum] = l_rx.var.tp;
  12124. ++QS_testData.tpNum;
  12125. /* no need to report Done */
  12126. break;
  12127. }
  12128. #endif /* Q_UTEST */
  12129. case ERROR_STATE: {
  12130. /* keep ignoring all bytes until new frame */
  12131. break;
  12132. }
  12133. default: {
  12134. QS_rxReportError_(0x47);
  12135. break;
  12136. }
  12137. }</code>
  12138. </operation>
  12139. <!--${QS::QS-rx::onReset}-->
  12140. <operation name="onReset" type="void" visibility="0x00" properties="0x00">
  12141. <documentation>/*! callback function to reset the Target (to be implemented in the BSP)
  12142. * @static @public @memberof QS_rx
  12143. */
  12144. /*! @static @public @memberof QS_rx */</documentation>
  12145. </operation>
  12146. <!--${QS::QS-rx::onCommand}-->
  12147. <operation name="onCommand" type="void" visibility="0x00" properties="0x00">
  12148. <documentation>/*! Callback function to execute user commands (to be implemented in BSP)
  12149. * @static @public @memberof QS_rx
  12150. */
  12151. /*! @static @public @memberof QS_rx */</documentation>
  12152. <!--${QS::QS-rx::onCommand::cmdId}-->
  12153. <parameter name="cmdId" type="uint8_t"/>
  12154. <!--${QS::QS-rx::onCommand::param1}-->
  12155. <parameter name="param1" type="uint32_t"/>
  12156. <!--${QS::QS-rx::onCommand::param2}-->
  12157. <parameter name="param2" type="uint32_t"/>
  12158. <!--${QS::QS-rx::onCommand::param3}-->
  12159. <parameter name="param3" type="uint32_t"/>
  12160. </operation>
  12161. <!--${QS::QS-rx::RX_PUT}-->
  12162. <operation name="RX_PUT" type="bool" visibility="0x00" properties="0x00">
  12163. <documentation>/*! Put one byte into the QS RX lock-free buffer
  12164. * @static @public @memberof QS_rx
  12165. */
  12166. /*! @static @public @memberof QS_rx */</documentation>
  12167. <!--${QS::QS-rx::RX_PUT::b}-->
  12168. <parameter name="b" type="uint8_t const"/>
  12169. <code>QSCtr head = QS_rxPriv_.head + 1U;
  12170. if (head == QS_rxPriv_.end) {
  12171. head = 0U;
  12172. }
  12173. if (head != QS_rxPriv_.tail) { /* buffer NOT full? */
  12174. QS_rxPriv_.buf[QS_rxPriv_.head] = b;
  12175. QS_rxPriv_.head = head; /* update the head to a *valid* index */
  12176. return true; /* byte placed in the buffer */
  12177. }
  12178. else {
  12179. return false; /* byte NOT placed in the buffer */
  12180. }</code>
  12181. </operation>
  12182. </package>
  12183. </package>
  12184. <!--${QUTest}-->
  12185. <package name="QUTest" stereotype="0x05">
  12186. <!--${QUTest::QS}-->
  12187. <package name="QS" stereotype="0x02" namespace="QS_">
  12188. <!--${QUTest::QS::TProbe}-->
  12189. <attribute name="TProbe" type="struct" visibility="0x04" properties="0x00">
  12190. <documentation>/*! @brief Test Probe attributes */</documentation>
  12191. <code>{
  12192. QSFun addr;
  12193. uint32_t data;
  12194. uint8_t idx;
  12195. };</code>
  12196. </attribute>
  12197. <!--${QUTest::QS::TestData}-->
  12198. <attribute name="TestData" type="struct" visibility="0x04" properties="0x00">
  12199. <documentation>/*! @brief QUTest data */</documentation>
  12200. <code>{
  12201. struct QS_TProbe tpBuf[16]; /*!&lt; buffer of Test-Probes received so far */
  12202. uint8_t tpNum; /*!&lt; current number of Test-Probes */
  12203. QSTimeCtr testTime; /*!&lt; test time (tick counter) */
  12204. };</code>
  12205. </attribute>
  12206. <!--${QUTest::QS::testData}-->
  12207. <attribute name="testData" type="struct QS_TestData" visibility="0x00" properties="0x00">
  12208. <documentation>/*! QUTest data */</documentation>
  12209. </attribute>
  12210. <!--${QUTest::QS::test_pause_}-->
  12211. <operation name="test_pause_" type="void" visibility="0x00" properties="0x00">
  12212. <documentation>/*! internal function to pause test and enter the test event loop */</documentation>
  12213. <code>QS_beginRec_((uint_fast8_t)QS_TEST_PAUSED);
  12214. QS_endRec_();
  12215. QS_onTestLoop();</code>
  12216. </operation>
  12217. <!--${QUTest::QS::getTestProbe_}-->
  12218. <operation name="getTestProbe_" type="uint32_t" visibility="0x00" properties="0x00">
  12219. <documentation>/*! get the test probe data for the given API */</documentation>
  12220. <!--${QUTest::QS::getTestProbe_::api}-->
  12221. <parameter name="api" type="QSpyFunPtr const"/>
  12222. <code>uint32_t data = 0U;
  12223. uint_fast8_t i;
  12224. for (i = 0U; i &lt; QS_testData.tpNum; ++i) {
  12225. uint_fast8_t j;
  12226. if (QS_testData.tpBuf[i].addr == (QSFun)api) {
  12227. QS_CRIT_STAT_
  12228. data = QS_testData.tpBuf[i].data;
  12229. QS_CRIT_E_();
  12230. QS_beginRec_((uint_fast8_t)QS_TEST_PROBE_GET);
  12231. QS_TIME_PRE_(); /* timestamp */
  12232. QS_FUN_PRE_(api); /* the calling API */
  12233. QS_U32_PRE_(data); /* the Test-Probe data */
  12234. QS_endRec_();
  12235. QS_CRIT_X_();
  12236. QS_REC_DONE(); /* user callback (if defined) */
  12237. --QS_testData.tpNum; /* one less Test-Probe */
  12238. /* move all remaining entries in the buffer up by one */
  12239. for (j = i; j &lt; QS_testData.tpNum; ++j) {
  12240. QS_testData.tpBuf[j] = QS_testData.tpBuf[j + 1U];
  12241. }
  12242. break; /* we are done (Test-Probe retreived) */
  12243. }
  12244. }
  12245. return data;</code>
  12246. </operation>
  12247. <!--${QUTest::QS::onTestSetup}-->
  12248. <operation name="onTestSetup" type="void" visibility="0x00" properties="0x00">
  12249. <documentation>/*! callback to setup a unit test inside the Target */</documentation>
  12250. </operation>
  12251. <!--${QUTest::QS::onTestTeardown}-->
  12252. <operation name="onTestTeardown" type="void" visibility="0x00" properties="0x00">
  12253. <documentation>/*! callback to teardown after a unit test inside the Target */</documentation>
  12254. </operation>
  12255. <!--${QUTest::QS::onTestEvt}-->
  12256. <operation name="onTestEvt" type="void" visibility="0x00" properties="0x00">
  12257. <documentation>/*! callback to &quot;massage&quot; the test event before dispatching/posting it */</documentation>
  12258. <!--${QUTest::QS::onTestEvt::e}-->
  12259. <parameter name="e" type="QEvt *"/>
  12260. </operation>
  12261. <!--${QUTest::QS::onTestPost}-->
  12262. <operation name="onTestPost" type="void" visibility="0x00" properties="0x00">
  12263. <documentation>/*! callback to examine an event that is about to be posted */</documentation>
  12264. <!--${QUTest::QS::onTestPost::sender}-->
  12265. <parameter name="sender" type="void const *"/>
  12266. <!--${QUTest::QS::onTestPost::recipient}-->
  12267. <parameter name="recipient" type="QActive *"/>
  12268. <!--${QUTest::QS::onTestPost::e}-->
  12269. <parameter name="e" type="QEvt const *"/>
  12270. <!--${QUTest::QS::onTestPost::status}-->
  12271. <parameter name="status" type="bool"/>
  12272. </operation>
  12273. <!--${QUTest::QS::onTestLoop}-->
  12274. <operation name="onTestLoop" type="void" visibility="0x00" properties="0x00">
  12275. <documentation>/*! callback to run the test loop */</documentation>
  12276. </operation>
  12277. </package>
  12278. <!--${QUTest::QUTEST_ON_POST}-->
  12279. <attribute name="QUTEST_ON_POST" type="124" visibility="0x03" properties="0x00">
  12280. <documentation>/*! record-ID for posting events */</documentation>
  12281. <code>124</code>
  12282. </attribute>
  12283. </package>
  12284. <!--${QUTest-stub}-->
  12285. <package name="QUTest-stub" stereotype="0x05">
  12286. <!--${QUTest-stub::QS}-->
  12287. <package name="QS" stereotype="0x02" namespace="QS_">
  12288. <!--${QUTest-stub::QS::processTestEvts_}-->
  12289. <operation name="processTestEvts_" type="void" visibility="0x00" properties="0x00">
  12290. <documentation>/*! internal function to process posted events during test */</documentation>
  12291. <code>QS_TEST_PROBE_DEF(&amp;QS_processTestEvts_)
  12292. /* return immediately (do nothing) for Test Probe != 0 */
  12293. QS_TEST_PROBE(return;)
  12294. while (QPSet_notEmpty(&amp;QF_readySet_)) {
  12295. uint_fast8_t const p = QPSet_findMax(&amp;QF_readySet_);
  12296. QActive * const a = QActive_registry_[p];
  12297. /* perform the run-to-completion (RTC) step...
  12298. * 1. retrieve the event from the AO's event queue, which by this
  12299. * time must be non-empty and The &quot;Vanialla&quot; kernel asserts it.
  12300. * 2. dispatch the event to the AO's state machine.
  12301. * 3. determine if event is garbage and collect it if so
  12302. */
  12303. QEvt const * const e = QActive_get_(a);
  12304. QHSM_DISPATCH(&amp;a-&gt;super, e, a-&gt;prio);
  12305. #if (QF_MAX_EPOOL &gt; 0U)
  12306. QF_gc(e);
  12307. #endif
  12308. if (a-&gt;eQueue.frontEvt == (QEvt *)0) { /* empty queue? */
  12309. QPSet_remove(&amp;QF_readySet_, p);
  12310. }
  12311. }</code>
  12312. </operation>
  12313. </package>
  12314. <!--${QUTest-stub::QF}-->
  12315. <package name="QF" stereotype="0x02" namespace="QF_">
  12316. <!--${QUTest-stub::QF::init}-->
  12317. <operation name="init" type="void" visibility="0x00" properties="0x01">
  12318. <documentation>/*! QF initialization for QUTest */</documentation>
  12319. <code>/* Clear the internal QF variables, so that the framework can start
  12320. * correctly even if the startup code fails to clear the uninitialized
  12321. * data (as is required by the C Standard).
  12322. */
  12323. QF_maxPool_ = 0U;
  12324. QF_intLock_ = 0U;
  12325. QF_intNest_ = 0U;
  12326. QF_bzero(&amp;QActive_registry_[0], sizeof(QActive_registry_));
  12327. QF_bzero(&amp;QF_readySet_, sizeof(QF_readySet_));</code>
  12328. </operation>
  12329. <!--${QUTest-stub::QF::stop}-->
  12330. <operation name="stop" type="void" visibility="0x00" properties="0x01">
  12331. <documentation>/*! stop the QF customization for QUTest */</documentation>
  12332. <code>QS_onReset();</code>
  12333. </operation>
  12334. <!--${QUTest-stub::QF::run}-->
  12335. <operation name="run" type="int_t" visibility="0x00" properties="0x01">
  12336. <documentation>/*! QF_run() customization for QUTest */</documentation>
  12337. <code>/* function dictionaries for the standard API */
  12338. QS_FUN_DICTIONARY(&amp;QActive_post_);
  12339. QS_FUN_DICTIONARY(&amp;QActive_postLIFO_);
  12340. QS_FUN_DICTIONARY(&amp;QS_processTestEvts_);
  12341. /* produce the QS_QF_RUN trace record */
  12342. QS_CRIT_STAT_
  12343. QS_BEGIN_PRE_(QS_QF_RUN, 0U)
  12344. QS_END_PRE_()
  12345. QS_processTestEvts_(); /* process all events posted so far */
  12346. QS_onTestLoop(); /* run the test loop */
  12347. QS_onCleanup(); /* application cleanup */
  12348. return 0; /* return no error */</code>
  12349. </operation>
  12350. </package>
  12351. <!--${QUTest-stub::QActive}-->
  12352. <class name="QActive" superclass="QEP::QHsm">
  12353. <documentation>/*! QActive active object class customization for QUTest */</documentation>
  12354. <!--${QUTest-stub::QActive::start_}-->
  12355. <operation name="start_" type="void" visibility="0x00" properties="0x00">
  12356. <documentation>/*! QActive_start_() customization for QUTest
  12357. * @public @memberof QActive
  12358. */</documentation>
  12359. <!--${QUTest-stub::QActive::start_::prioSpec}-->
  12360. <parameter name="prioSpec" type="QPrioSpec const"/>
  12361. <!--${QUTest-stub::QActive::start_::qSto}-->
  12362. <parameter name="qSto" type="QEvt const * * const"/>
  12363. <!--${QUTest-stub::QActive::start_::qLen}-->
  12364. <parameter name="qLen" type="uint_fast16_t const"/>
  12365. <!--${QUTest-stub::QActive::start_::stkSto}-->
  12366. <parameter name="stkSto" type="void * const"/>
  12367. <!--${QUTest-stub::QActive::start_::stkSize}-->
  12368. <parameter name="stkSize" type="uint_fast16_t const"/>
  12369. <!--${QUTest-stub::QActive::start_::par}-->
  12370. <parameter name="par" type="void const * const"/>
  12371. <code>Q_UNUSED_PAR(stkSto);
  12372. Q_UNUSED_PAR(stkSize);
  12373. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  12374. me-&gt;pthre = (uint8_t)(prioSpec &gt;&gt; 8U); /* preemption-threshold */
  12375. QActive_register_(me); /* make QF aware of this active object */
  12376. QEQueue_init(&amp;me-&gt;eQueue, qSto, qLen); /* initialize the built-in queue */
  12377. QHSM_INIT(&amp;me-&gt;super, par, me-&gt;prio); /* the top-most initial tran. */</code>
  12378. </operation>
  12379. <!--${QUTest-stub::QActive::stop}-->
  12380. <operation name="stop?def QF_ACTIVE_STOP" type="void" visibility="0x00" properties="0x00">
  12381. <documentation>/*! Stops execution of an active object and unregisters the object
  12382. * with the framework customized for QUTest
  12383. * @public @memberof QActive
  12384. */</documentation>
  12385. <code>QActive_unsubscribeAll(me); /* unsubscribe from all events */
  12386. QActive_unregister_(me); /* un-register this active object */</code>
  12387. </operation>
  12388. </class>
  12389. <!--${QUTest-stub::QTimeEvt}-->
  12390. <class name="QTimeEvt" superclass="QEP::QEvt">
  12391. <documentation>/*! QTimeEvt class customization for QUTest */</documentation>
  12392. <!--${QUTest-stub::QTimeEvt::tick1_}-->
  12393. <operation name="tick1_" type="void" visibility="0x00" properties="0x01">
  12394. <documentation>/*! Processes one clock tick for QUTest */</documentation>
  12395. <!--${QUTest-stub::QTimeEvt::tick1_::tickRate}-->
  12396. <parameter name="tickRate" type="uint_fast8_t const"/>
  12397. <!--${QUTest-stub::QTimeEvt::tick1_::sender}-->
  12398. <parameter name="sender" type="void const * const"/>
  12399. <code>QF_CRIT_STAT_
  12400. QF_CRIT_E_();
  12401. QTimeEvt *prev = &amp;QTimeEvt_timeEvtHead_[tickRate];
  12402. QS_BEGIN_NOCRIT_PRE_(QS_QF_TICK, 0U)
  12403. ++prev-&gt;ctr;
  12404. QS_TEC_PRE_(prev-&gt;ctr); /* tick ctr */
  12405. QS_U8_PRE_(tickRate); /* tick rate */
  12406. QS_END_NOCRIT_PRE_()
  12407. /* is current Time Event object provided? */
  12408. QTimeEvt *t = (QTimeEvt *)QS_rxPriv_.currObj[TE_OBJ];
  12409. if (t != (QTimeEvt *)0) {
  12410. /* the time event must be armed */
  12411. Q_ASSERT_ID(810, t-&gt;ctr != 0U);
  12412. QActive * const act = (QActive * const)(t-&gt;act);
  12413. /* the recipient AO must be provided */
  12414. Q_ASSERT_ID(820, act != (QActive *)0);
  12415. /* periodic time evt? */
  12416. if (t-&gt;interval != 0U) {
  12417. t-&gt;ctr = t-&gt;interval; /* rearm the time event */
  12418. }
  12419. else { /* one-shot time event: automatically disarm */
  12420. t-&gt;ctr = 0U; /* auto-disarm */
  12421. /* mark time event 't' as NOT linked */
  12422. t-&gt;super.refCtr_ &amp;= (uint8_t)(~(uint8_t)QTE_IS_LINKED);
  12423. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act-&gt;prio)
  12424. QS_OBJ_PRE_(t); /* this time event object */
  12425. QS_OBJ_PRE_(act); /* the target AO */
  12426. QS_U8_PRE_(tickRate); /* tick rate */
  12427. QS_END_NOCRIT_PRE_()
  12428. }
  12429. QS_BEGIN_NOCRIT_PRE_(QS_QF_TIMEEVT_POST, act-&gt;prio)
  12430. QS_TIME_PRE_(); /* timestamp */
  12431. QS_OBJ_PRE_(t); /* the time event object */
  12432. QS_SIG_PRE_(t-&gt;super.sig); /* signal of this time event */
  12433. QS_OBJ_PRE_(act); /* the target AO */
  12434. QS_U8_PRE_(tickRate); /* tick rate */
  12435. QS_END_NOCRIT_PRE_()
  12436. QF_CRIT_X_(); /* exit critical section before posting */
  12437. QACTIVE_POST(act, &amp;t-&gt;super, sender); /* asserts if queue overflows */
  12438. QF_CRIT_E_();
  12439. }
  12440. /* update the linked list of time events */
  12441. for (;;) {
  12442. t = prev-&gt;next; /* advance down the time evt. list */
  12443. /* end of the list? */
  12444. if (t == (QTimeEvt *)0) {
  12445. /* any new time events armed since the last QTimeEvt_tick_()? */
  12446. if (QTimeEvt_timeEvtHead_[tickRate].act != (void *)0) {
  12447. /* sanity check */
  12448. Q_ASSERT_CRIT_(830, prev != (QTimeEvt *)0);
  12449. prev-&gt;next = (QTimeEvt *)QTimeEvt_timeEvtHead_[tickRate].act;
  12450. QTimeEvt_timeEvtHead_[tickRate].act = (void *)0;
  12451. t = prev-&gt;next; /* switch to the new list */
  12452. }
  12453. else {
  12454. break; /* all currently armed time evts. processed */
  12455. }
  12456. }
  12457. /* time event scheduled for removal? */
  12458. if (t-&gt;ctr == 0U) {
  12459. prev-&gt;next = t-&gt;next;
  12460. /* mark time event 't' as NOT linked */
  12461. t-&gt;super.refCtr_ &amp;= (uint8_t)(~(uint8_t)QTE_IS_LINKED);
  12462. /* do NOT advance the prev pointer */
  12463. QF_CRIT_X_(); /* exit crit. section to reduce latency */
  12464. /* prevent merging critical sections, see NOTE1 below */
  12465. QF_CRIT_EXIT_NOP();
  12466. }
  12467. else {
  12468. prev = t; /* advance to this time event */
  12469. QF_CRIT_X_(); /* exit crit. section to reduce latency */
  12470. /* prevent merging critical sections, see NOTE1 below */
  12471. QF_CRIT_EXIT_NOP();
  12472. }
  12473. QF_CRIT_E_(); /* re-enter crit. section to continue */
  12474. }
  12475. QF_CRIT_X_();
  12476. </code>
  12477. </operation>
  12478. </class>
  12479. <!--${QUTest-stub::QHsmDummy}-->
  12480. <class name="QHsmDummy" superclass="QEP::QHsm">
  12481. <documentation>/*! @brief QHsmDummy class
  12482. * @class QHsmDummy
  12483. * @extends QHsm
  12484. *
  12485. * @details
  12486. * ::QHsmDummy is a test double for the role of &quot;Orthogonal Components&quot;
  12487. * HSM objects in QUTest unit testing.
  12488. */</documentation>
  12489. <!--${QUTest-stub::QHsmDummy::ctor}-->
  12490. <operation name="ctor" type="void" visibility="0x00" properties="0x00">
  12491. <documentation>/*! Constructor of the QHsmDummy HSM class
  12492. * @public @memberof QHsmDummy
  12493. */</documentation>
  12494. <code>static struct QHsmVtable const vtable = { /* QHsm virtual table */
  12495. &amp;QHsmDummy_init_,
  12496. &amp;QHsmDummy_dispatch_
  12497. #ifdef Q_SPY
  12498. ,&amp;QHsm_getStateHandler_
  12499. #endif
  12500. };
  12501. /* superclass' ctor */
  12502. QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(0));
  12503. me-&gt;super.vptr = &amp;vtable; /* hook the vptr */</code>
  12504. </operation>
  12505. <!--${QUTest-stub::QHsmDummy::init_}-->
  12506. <operation name="init_" type="void" visibility="0x00" properties="0x01">
  12507. <documentation>/*! override for QHsm_init_()
  12508. * @private @memberof QHsmDummy
  12509. */</documentation>
  12510. <!--${QUTest-stub::QHsmDummy::init_::me}-->
  12511. <parameter name="me" type="QHsm * const"/>
  12512. <!--${QUTest-stub::QHsmDummy::init_::par}-->
  12513. <parameter name="par" type="void const * const"/>
  12514. <!--${QUTest-stub::QHsmDummy::init_::qs_id}-->
  12515. <parameter name="qs_id" type="uint_fast8_t const"/>
  12516. <code>Q_UNUSED_PAR(par);
  12517. #ifdef Q_SPY
  12518. if ((QS_priv_.flags &amp; 0x01U) == 0U) {
  12519. QS_priv_.flags |= 0x01U;
  12520. QS_FUN_DICTIONARY(&amp;QHsm_top);
  12521. }
  12522. #endif
  12523. QS_CRIT_STAT_
  12524. QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qs_id)
  12525. QS_OBJ_PRE_(me); /* this state machine object */
  12526. QS_FUN_PRE_(me-&gt;state.fun); /* the source state */
  12527. QS_FUN_PRE_(me-&gt;temp.fun); /* the target of the initial transition */
  12528. QS_END_PRE_()</code>
  12529. </operation>
  12530. <!--${QUTest-stub::QHsmDummy::dispatch_}-->
  12531. <operation name="dispatch_" type="void" visibility="0x00" properties="0x01">
  12532. <documentation>/*! override for QHsm_dispatch_()
  12533. * @private @memberof QHsmDummy
  12534. */</documentation>
  12535. <!--${QUTest-stub::QHsmDummy::dispatch_::me}-->
  12536. <parameter name="me" type="QHsm * const"/>
  12537. <!--${QUTest-stub::QHsmDummy::dispatch_::e}-->
  12538. <parameter name="e" type="QEvt const * const"/>
  12539. <!--${QUTest-stub::QHsmDummy::dispatch_::qs_id}-->
  12540. <parameter name="qs_id" type="uint_fast8_t const"/>
  12541. <code>QS_CRIT_STAT_
  12542. QS_BEGIN_PRE_(QS_QEP_DISPATCH, qs_id)
  12543. QS_TIME_PRE_(); /* time stamp */
  12544. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  12545. QS_OBJ_PRE_(me); /* this state machine object */
  12546. QS_FUN_PRE_(me-&gt;state.fun); /* the current state */
  12547. QS_END_PRE_()</code>
  12548. </operation>
  12549. </class>
  12550. <!--${QUTest-stub::QActiveDummy}-->
  12551. <class name="QActiveDummy" superclass="QF::QActive">
  12552. <documentation>/*! @brief QActiveDummy Object class
  12553. * @class QActiveDummy
  12554. * @extends QActive
  12555. *
  12556. * @details
  12557. * QActiveDummy is a test double for the role of collaborating active
  12558. * objects in QUTest unit testing.
  12559. */</documentation>
  12560. <!--${QUTest-stub::QActiveDummy::ctor}-->
  12561. <operation name="ctor" type="void" visibility="0x00" properties="0x00">
  12562. <documentation>/*! Constructor of the QActiveDummy Active Object class
  12563. * @public @memberof QActiveDummy
  12564. */</documentation>
  12565. <code>static QActiveVtable const vtable = { /* QActive virtual table */
  12566. { &amp;QActiveDummy_init_,
  12567. &amp;QActiveDummy_dispatch_
  12568. #ifdef Q_SPY
  12569. ,&amp;QHsm_getStateHandler_
  12570. #endif
  12571. },
  12572. &amp;QActiveDummy_start_,
  12573. &amp;QActiveDummy_post_,
  12574. &amp;QActiveDummy_postLIFO_
  12575. };
  12576. /* superclass' ctor */
  12577. QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(0));
  12578. me-&gt;super.super.vptr = &amp;vtable.super; /* hook the vptr */</code>
  12579. </operation>
  12580. <!--${QUTest-stub::QActiveDummy::init_}-->
  12581. <operation name="init_" type="void" visibility="0x00" properties="0x01">
  12582. <documentation>/*! override for QHsm_init_()
  12583. * @private @memberof QActiveDummy
  12584. */</documentation>
  12585. <!--${QUTest-stub::QActiveDummy::init_::me}-->
  12586. <parameter name="me" type="QHsm * const"/>
  12587. <!--${QUTest-stub::QActiveDummy::init_::par}-->
  12588. <parameter name="par" type="void const * const"/>
  12589. <!--${QUTest-stub::QActiveDummy::init_::qs_id}-->
  12590. <parameter name="qs_id" type="uint_fast8_t const"/>
  12591. <code>Q_UNUSED_PAR(qs_id);
  12592. QHsmDummy_init_(me, par, ((QActive const *)me)-&gt;prio);</code>
  12593. </operation>
  12594. <!--${QUTest-stub::QActiveDummy::dispatch_}-->
  12595. <operation name="dispatch_" type="void" visibility="0x00" properties="0x01">
  12596. <documentation>/*! override for QHsm_dispatch_()
  12597. * @private @memberof QActiveDummy
  12598. */</documentation>
  12599. <!--${QUTest-stub::QActiveDummy::dispatch_::me}-->
  12600. <parameter name="me" type="QHsm * const"/>
  12601. <!--${QUTest-stub::QActiveDummy::dispatch_::e}-->
  12602. <parameter name="e" type="QEvt const * const"/>
  12603. <!--${QUTest-stub::QActiveDummy::dispatch_::qs_id}-->
  12604. <parameter name="qs_id" type="uint_fast8_t const"/>
  12605. <code>Q_UNUSED_PAR(qs_id);
  12606. QHsmDummy_dispatch_(me, e, ((QActive const *)me)-&gt;prio);</code>
  12607. </operation>
  12608. <!--${QUTest-stub::QActiveDummy::start_}-->
  12609. <operation name="start_" type="void" visibility="0x00" properties="0x01">
  12610. <documentation>/*! override for QActive_start_()
  12611. * @private @memberof QActiveDummy
  12612. */</documentation>
  12613. <!--${QUTest-stub::QActiveDummy::start_::me}-->
  12614. <parameter name="me" type="QActive * const"/>
  12615. <!--${QUTest-stub::QActiveDummy::start_::prioSpec}-->
  12616. <parameter name="prioSpec" type="QPrioSpec const"/>
  12617. <!--${QUTest-stub::QActiveDummy::start_::qSto}-->
  12618. <parameter name="qSto" type="QEvt const * * const"/>
  12619. <!--${QUTest-stub::QActiveDummy::start_::qLen}-->
  12620. <parameter name="qLen" type="uint_fast16_t const"/>
  12621. <!--${QUTest-stub::QActiveDummy::start_::stkSto}-->
  12622. <parameter name="stkSto" type="void * const"/>
  12623. <!--${QUTest-stub::QActiveDummy::start_::stkSize}-->
  12624. <parameter name="stkSize" type="uint_fast16_t const"/>
  12625. <!--${QUTest-stub::QActiveDummy::start_::par}-->
  12626. <parameter name="par" type="void const * const"/>
  12627. <code>/* No special preconditions for checking parameters to allow starting
  12628. * dummy AOs the exact same way as the real counterparts.
  12629. */
  12630. Q_UNUSED_PAR(qSto);
  12631. Q_UNUSED_PAR(qLen);
  12632. Q_UNUSED_PAR(stkSto);
  12633. Q_UNUSED_PAR(stkSize);
  12634. me-&gt;prio = (uint8_t)(prioSpec &amp; 0xFFU); /* QF-priority of the AO */
  12635. me-&gt;pthre = (uint8_t)(prioSpec &gt;&gt; 8U); /* preemption-threshold */
  12636. QActive_register_(me); /* make QF aware of this active object */
  12637. /* the top-most initial tran. (virtual) */
  12638. QHSM_INIT(&amp;me-&gt;super, par, me-&gt;prio);
  12639. //QS_FLUSH();</code>
  12640. </operation>
  12641. <!--${QUTest-stub::QActiveDummy::post_}-->
  12642. <operation name="post_" type="bool" visibility="0x00" properties="0x01">
  12643. <documentation>/*! override for QActive_post_()
  12644. * @private @memberof QActiveDummy
  12645. */</documentation>
  12646. <!--${QUTest-stub::QActiveDummy::post_::me}-->
  12647. <parameter name="me" type="QActive * const"/>
  12648. <!--${QUTest-stub::QActiveDummy::post_::e}-->
  12649. <parameter name="e" type="QEvt const * const"/>
  12650. <!--${QUTest-stub::QActiveDummy::post_::margin}-->
  12651. <parameter name="margin" type="uint_fast16_t const"/>
  12652. <!--${QUTest-stub::QActiveDummy::post_::sender}-->
  12653. <parameter name="sender" type="void const * const"/>
  12654. <code>QS_TEST_PROBE_DEF(&amp;QActive_post_)
  12655. /* test-probe#1 for faking queue overflow */
  12656. bool status = true;
  12657. QS_TEST_PROBE_ID(1,
  12658. status = false;
  12659. if (margin == QF_NO_MARGIN) {
  12660. /* fake assertion Mod=qf_actq,Loc=110 */
  12661. Q_onAssert(&quot;qf_actq&quot;, 110);
  12662. }
  12663. )
  12664. QF_CRIT_STAT_
  12665. QF_CRIT_E_();
  12666. /* is it a dynamic event? */
  12667. if (e-&gt;poolId_ != 0U) {
  12668. QEvt_refCtr_inc_(e); /* increment the reference counter */
  12669. }
  12670. uint_fast8_t const rec = (status ? (uint_fast8_t)QS_QF_ACTIVE_POST
  12671. : (uint_fast8_t)QS_QF_ACTIVE_POST_ATTEMPT);
  12672. QS_BEGIN_NOCRIT_PRE_(rec, me-&gt;prio)
  12673. QS_TIME_PRE_(); /* timestamp */
  12674. QS_OBJ_PRE_(sender); /* the sender object */
  12675. QS_SIG_PRE_(e-&gt;sig); /* the signal of the event */
  12676. QS_OBJ_PRE_(me); /* this active object */
  12677. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; refCtr of the evt */
  12678. QS_EQC_PRE_(0U); /* number of free entries */
  12679. QS_EQC_PRE_(margin); /* margin requested */
  12680. QS_END_NOCRIT_PRE_()
  12681. /* callback to examine the posted event under the same conditions
  12682. * as producing the #QS_QF_ACTIVE_POST trace record, which are:
  12683. * the local filter for this AO ('me-&gt;prio') is set
  12684. */
  12685. if ((QS_priv_.locFilter[me-&gt;prio &gt;&gt; 3U]
  12686. &amp; (1U &lt;&lt; (me-&gt;prio &amp; 7U))) != 0U)
  12687. {
  12688. QS_onTestPost(sender, me, e, status);
  12689. }
  12690. QF_CRIT_X_();
  12691. /* recycle the event immediately, because it was not really posted */
  12692. #if (QF_MAX_EPOOL &gt; 0U)
  12693. QF_gc(e);
  12694. #endif
  12695. return status; /* the event is &quot;posted&quot; correctly */</code>
  12696. </operation>
  12697. <!--${QUTest-stub::QActiveDummy::postLIFO_}-->
  12698. <operation name="postLIFO_" type="void" visibility="0x00" properties="0x01">
  12699. <documentation>/*! override for QActive_postLIFO_()
  12700. * @private @memberof QActiveDummy
  12701. */</documentation>
  12702. <!--${QUTest-stub::QActiveDummy::postLIFO_::me}-->
  12703. <parameter name="me" type="QActive * const"/>
  12704. <!--${QUTest-stub::QActiveDummy::postLIFO_::e}-->
  12705. <parameter name="e" type="QEvt const * const"/>
  12706. <code>QS_TEST_PROBE_DEF(&amp;QActive_postLIFO_)
  12707. /* test-probe#1 for faking queue overflow */
  12708. QS_TEST_PROBE_ID(1,
  12709. /* fake assertion Mod=qf_actq,Loc=210 */
  12710. Q_onAssert(&quot;qf_actq&quot;, 210);
  12711. )
  12712. QF_CRIT_STAT_
  12713. QF_CRIT_E_();
  12714. /* is it a dynamic event? */
  12715. if (e-&gt;poolId_ != 0U) {
  12716. QEvt_refCtr_inc_(e); /* increment the reference counter */
  12717. }
  12718. QS_BEGIN_NOCRIT_PRE_(QS_QF_ACTIVE_POST_LIFO, me-&gt;prio)
  12719. QS_TIME_PRE_(); /* timestamp */
  12720. QS_SIG_PRE_(e-&gt;sig); /* the signal of this event */
  12721. QS_OBJ_PRE_(me); /* this active object */
  12722. QS_2U8_PRE_(e-&gt;poolId_, e-&gt;refCtr_); /* pool Id &amp; refCtr of the evt */
  12723. QS_EQC_PRE_(0U); /* number of free entries */
  12724. QS_EQC_PRE_(0U); /* min number of free entries */
  12725. QS_END_NOCRIT_PRE_()
  12726. /* callback to examine the posted event under the same conditions
  12727. * as producing the #QS_QF_ACTIVE_POST trace record, which are:
  12728. * the local filter for this AO ('me-&gt;prio') is set
  12729. */
  12730. if ((QS_priv_.locFilter[me-&gt;prio &gt;&gt; 3U]
  12731. &amp; (1U &lt;&lt; (me-&gt;prio &amp; 7U))) != 0U)
  12732. {
  12733. QS_onTestPost((QActive *)0, me, e, true);
  12734. }
  12735. QF_CRIT_X_();
  12736. /* recycle the event immediately, because it was not really posted */
  12737. #if (QF_MAX_EPOOL &gt; 0U)
  12738. QF_gc(e);
  12739. #endif</code>
  12740. </operation>
  12741. </class>
  12742. </package>
  12743. <!--${include}-->
  12744. <directory name="include">
  12745. <!--${include::qassert.h}-->
  12746. <file name="qassert.h">
  12747. <text>/*! @file
  12748. * @brief Customizable and memory-efficient Design by Contract (DbC)
  12749. * for embedded systems
  12750. *
  12751. * @note
  12752. * This header file can be used in C, C++, and mixed C/C++ programs.
  12753. *
  12754. * @note
  12755. * The preprocessor switch #Q_NASSERT disables checking assertions.
  12756. * However, it is generally **not** advisable to disable assertions,
  12757. * **especially** in the production code. Instead, the assertion
  12758. * handler Q_onAssert() should be very carefully designed and tested.
  12759. */
  12760. #ifndef QASSERT_H_
  12761. #define QASSERT_H_
  12762. #ifdef __cplusplus
  12763. extern &quot;C&quot; {
  12764. #endif
  12765. #ifndef Q_NASSERT
  12766. $declare ${DbC::active}
  12767. #else
  12768. $declare ${DbC::inactive}
  12769. #endif
  12770. $declare1 ${DbC}
  12771. #ifdef __cplusplus
  12772. }
  12773. #endif
  12774. #endif /* QASSERT_H_ */</text>
  12775. </file>
  12776. <!--${include::qep.h}-->
  12777. <file name="qep.h">
  12778. <text>/*! @file
  12779. * @brief QEP/C platform-independent public interface.
  12780. *
  12781. * @trace
  12782. * @tr{RQP001}, @tr{RQP101}
  12783. */
  12784. #ifndef QEP_H_
  12785. #define QEP_H_
  12786. /*==========================================================================*/
  12787. /*! The current QP version as an unsigned number
  12788. *
  12789. * @details
  12790. * ::QP_VERSION is a decimal constant, where XX is a 1-digit or 2-digit
  12791. * major version number, Y is a 1-digit minor version number, and Z is
  12792. * a 1-digit release number.
  12793. */
  12794. #define QP_VERSION 722U
  12795. /*! The current QP version as a zero terminated string literal.
  12796. *
  12797. * @details
  12798. * ::QP_VERSION_STR is of the form &quot;XX.Y.Z&quot;, where XX is a 1-or 2-digit
  12799. * major version number, Y is a 1-digit minor version number, and Z is
  12800. * a 1-digit release number.
  12801. */
  12802. #define QP_VERSION_STR &quot;7.2.2&quot;
  12803. /*! Encrypted current QP release (7.2.2) and date (2023-03-01) */
  12804. #define QP_RELEASE 0x76BAD85DU
  12805. /*==========================================================================*/
  12806. $declare ${glob-types}
  12807. $declare ${QEP-config}
  12808. /*==========================================================================*/
  12809. $declare ${QEP}
  12810. /*==========================================================================*/
  12811. $declare ${QEP-macros}
  12812. #endif /* QEP_H_ */</text>
  12813. </file>
  12814. <!--${include::qf.h}-->
  12815. <file name="qf.h">
  12816. <text>/*! @file
  12817. * @brief QF/C platform-independent public interface.
  12818. */
  12819. #ifndef QF_H_
  12820. #define QF_H_
  12821. /*==========================================================================*/
  12822. $declare ${QF-config}
  12823. /*==========================================================================*/
  12824. $declare ${QF-types}
  12825. $declare ${QF::QActive}
  12826. $declare ${QF::QActiveVtable}
  12827. $declare ${QF::QMActive}
  12828. $declare ${QF::QMActiveVtable}
  12829. $declare ${QF::QTimeEvt}
  12830. $declare ${QF::QTicker}
  12831. $declare ${QF::QF-base}
  12832. $declare ${QF::QF-dyn}
  12833. $declare ${QF::QF-extern-C}
  12834. /*==========================================================================*/
  12835. $declare ${QF-macros}
  12836. #endif /* QF_H_ */</text>
  12837. </file>
  12838. <!--${include::qf_pkg.h}-->
  12839. <file name="qf_pkg.h">
  12840. <text>/*! @file
  12841. * @brief Internal (package scope) QF/C interface.
  12842. */
  12843. #ifndef QF_PKG_H_
  12844. #define QF_PKG_H_
  12845. /*==========================================================================*/
  12846. $declare ${QF::QF-pkg}
  12847. /*==========================================================================*/
  12848. /* QF-specific critical section */
  12849. #ifndef QF_CRIT_STAT_TYPE
  12850. /*! This is an internal macro for defining the critical section
  12851. * status type. */
  12852. /**
  12853. * @details
  12854. * The purpose of this macro is to enable writing the same code for the
  12855. * case when critical section status type is defined and when it is not.
  12856. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  12857. * provides the definition of the critical section status variable.
  12858. * Otherwise this macro is empty.
  12859. * @sa #QF_CRIT_STAT_TYPE
  12860. */
  12861. #define QF_CRIT_STAT_
  12862. /*! This is an internal macro for entering a critical section. */
  12863. /**
  12864. * @details
  12865. * The purpose of this macro is to enable writing the same code for the
  12866. * case when critical section status type is defined and when it is not.
  12867. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  12868. * invokes QF_CRIT_ENTRY() passing the key variable as the parameter.
  12869. * Otherwise QF_CRIT_ENTRY() is invoked with a dummy parameter.
  12870. * @sa QF_CRIT_ENTRY()
  12871. */
  12872. #define QF_CRIT_E_() QF_CRIT_ENTRY(dummy)
  12873. /*! This is an internal macro for exiting a critical section. */
  12874. /**
  12875. * @details
  12876. * The purpose of this macro is to enable writing the same code for the
  12877. * case when critical section status type is defined and when it is not.
  12878. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  12879. * invokes #QF_CRIT_EXIT passing the key variable as the parameter.
  12880. * Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter.
  12881. * @sa #QF_CRIT_EXIT
  12882. */
  12883. #define QF_CRIT_X_() QF_CRIT_EXIT(dummy)
  12884. #elif (!defined QF_CRIT_STAT_)
  12885. #define QF_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_;
  12886. #define QF_CRIT_E_() QF_CRIT_ENTRY(critStat_)
  12887. #define QF_CRIT_X_() QF_CRIT_EXIT(critStat_)
  12888. #endif
  12889. /*==========================================================================*/
  12890. /* Assertions inside the critical section */
  12891. #ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */
  12892. #define Q_ASSERT_CRIT_(id_, test_) ((void)0)
  12893. #define Q_REQUIRE_CRIT_(id_, test_) ((void)0)
  12894. #define Q_ERROR_CRIT_(id_) ((void)0)
  12895. #else /* Q_NASSERT not defined--assertion checking enabled */
  12896. #define Q_ASSERT_CRIT_(id_, test_) do { \
  12897. if ((test_)) {} else { \
  12898. QF_CRIT_X_(); \
  12899. Q_onAssert(&amp;Q_this_module_[0], (int_t)(id_)); \
  12900. } \
  12901. } while (false)
  12902. #define Q_REQUIRE_CRIT_(id_, test_) Q_ASSERT_CRIT_((id_), (test_))
  12903. #define Q_ERROR_CRIT_(id_) do { \
  12904. QF_CRIT_X_(); \
  12905. Q_onAssert(&amp;Q_this_module_[0], (int_t)(id_)); \
  12906. } while (false)
  12907. #endif /* Q_NASSERT */
  12908. /*==========================================================================*/
  12909. /* The following bitmasks are for the fields of the @c refCtr_ attribute
  12910. * of the QTimeEvt struct (inherited from QEvt). This attribute is NOT used
  12911. * for reference counting in time events, because the @c poolId_ attribute
  12912. * is zero (&quot;immutable events&quot;).
  12913. */
  12914. #define QTE_IS_LINKED (1U &lt;&lt; 7U)
  12915. #define QTE_WAS_DISARMED (1U &lt;&lt; 6U)
  12916. #define QTE_TICK_RATE 0x0FU
  12917. /*! @brief structure representing a free block in the Native QF Memory Pool */
  12918. typedef struct QFreeBlock {
  12919. struct QFreeBlock * volatile next;
  12920. } QFreeBlock;
  12921. /* internal helper macros ==================================================*/
  12922. /*! increment the refCtr of a const event (requires casting `const` away)
  12923. * @private @memberof QEvt
  12924. *
  12925. * @trace
  12926. * @tr{PQP11_8}
  12927. */
  12928. static inline void QEvt_refCtr_inc_(QEvt const *me) {
  12929. ++((QEvt *)me)-&gt;refCtr_;
  12930. }
  12931. /*! decrement the refCtr of a const event (requires casting `const` away)
  12932. * @private @memberof QEvt
  12933. *
  12934. * @trace
  12935. * @tr{PQP11_8}
  12936. */
  12937. static inline void QEvt_refCtr_dec_(QEvt const *me) {
  12938. --((QEvt *)me)-&gt;refCtr_;
  12939. }
  12940. #endif /* QF_PKG_H_ */</text>
  12941. </file>
  12942. <!--${include::qequeue.h}-->
  12943. <file name="qequeue.h">
  12944. <text>/*! @file
  12945. * @brief QP natvie, platform-independent, thread-safe event queue interface
  12946. * @details
  12947. * This header file must be included in all QF ports that use native QF
  12948. * event queue for active objects. Also, this file needs to be included
  12949. * in the QP/C library when the application uses QActive_defer()/
  12950. * QActive_recall(). Finally, this file is also needed when the &quot;raw&quot;
  12951. * thread-safe queues are used for communication between active objects
  12952. * and non-framework entities, such as ISRs, device drivers, or legacy
  12953. * code.
  12954. */
  12955. #ifndef QEQUEUE_H_
  12956. #define QEQUEUE_H_
  12957. #ifndef QF_EQUEUE_CTR_SIZE
  12958. /*! The size [bytes] of the ring-buffer counters used in the
  12959. * native QF event queue implementation. Valid values: 1U, 2U, or 4U;
  12960. * default 1U.
  12961. * @details
  12962. * This macro can be defined in the QF port file (qf_port.h) to
  12963. * configure the ::QEQueueCtr type. Here the macro is not defined so the
  12964. * default of 1 byte is chosen.
  12965. */
  12966. #define QF_EQUEUE_CTR_SIZE 1U
  12967. #endif
  12968. #if (QF_EQUEUE_CTR_SIZE == 1U)
  12969. /*! The data type to store the ring-buffer counters based on
  12970. * the macro #QF_EQUEUE_CTR_SIZE.
  12971. * @details
  12972. * The dynamic range of this data type determines the maximum length
  12973. * of the ring buffer managed by the native QF event queue.
  12974. */
  12975. typedef uint8_t QEQueueCtr;
  12976. #elif (QF_EQUEUE_CTR_SIZE == 2U)
  12977. typedef uint16_t QEQueueCtr;
  12978. #elif (QF_EQUEUE_CTR_SIZE == 4U)
  12979. typedef uint32_t QEQueueCtr;
  12980. #else
  12981. #error &quot;QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U&quot;
  12982. #endif
  12983. /*==========================================================================*/
  12984. $declare ${QF::QEQueue}
  12985. #endif /* QEQUEUE_H_ */</text>
  12986. </file>
  12987. <!--${include::qmpool.h}-->
  12988. <file name="qmpool.h">
  12989. <text>/*! @file
  12990. * @brief QP native, platform-independent memory pool ::QMPool interface.
  12991. */
  12992. #ifndef QMPOOL_H_
  12993. #define QMPOOL_H_
  12994. /*==========================================================================*/
  12995. #ifndef QF_MPOOL_SIZ_SIZE
  12996. /*! macro to override the default ::QMPoolSize size [bytes].
  12997. * Valid values 1U, 2U, or 4U; default 2U
  12998. */
  12999. #define QF_MPOOL_SIZ_SIZE 2U
  13000. #endif
  13001. #if (QF_MPOOL_SIZ_SIZE == 1U)
  13002. /*! The data type to store the block-size based on the macro
  13003. * #QF_MPOOL_SIZ_SIZE.
  13004. * @details
  13005. * The dynamic range of this data type determines the maximum size
  13006. * of blocks that can be managed by the native QF event pool.
  13007. */
  13008. typedef uint8_t QMPoolSize;
  13009. #elif (QF_MPOOL_SIZ_SIZE == 2U)
  13010. typedef uint16_t QMPoolSize;
  13011. #elif (QF_MPOOL_SIZ_SIZE == 4U)
  13012. typedef uint32_t QMPoolSize;
  13013. #else
  13014. #error &quot;QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U&quot;
  13015. #endif
  13016. /*==========================================================================*/
  13017. #ifndef QF_MPOOL_CTR_SIZE
  13018. /*! macro to override the default ::QMPoolCtr size [bytes].
  13019. * Valid values 1U, 2U, or 4U; default 2U
  13020. */
  13021. #define QF_MPOOL_CTR_SIZE 2U
  13022. #endif
  13023. #if (QF_MPOOL_CTR_SIZE == 1U)
  13024. /*! The data type to store the block-counter based on the macro
  13025. * #QF_MPOOL_CTR_SIZE.
  13026. * @details
  13027. * The dynamic range of this data type determines the maximum number
  13028. * of blocks that can be stored in the pool.
  13029. */
  13030. typedef uint8_t QMPoolCtr;
  13031. #elif (QF_MPOOL_CTR_SIZE == 2U)
  13032. typedef uint16_t QMPoolCtr;
  13033. #elif (QF_MPOOL_CTR_SIZE == 4U)
  13034. typedef uint32_t QMPoolCtr;
  13035. #else
  13036. #error &quot;QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U&quot;
  13037. #endif
  13038. /*! Memory pool element to allocate correctly aligned storage
  13039. * for QMPool class.
  13040. * @param[in] evType_ event type (name of the subclass of QEvt)
  13041. */
  13042. #define QF_MPOOL_EL(evType_) \
  13043. struct { void *sto_[((sizeof(evType_) - 1U)/sizeof(void*)) + 1U]; }
  13044. /*==========================================================================*/
  13045. $declare ${QF::QMPool}
  13046. #endif /* QMPOOL_H_ */</text>
  13047. </file>
  13048. <!--${include::qv.h}-->
  13049. <file name="qv.h">
  13050. <text>/*! @file
  13051. * @brief QV/C (cooperative &quot;Vanilla&quot; kernel) platform-independent
  13052. * public interface
  13053. */
  13054. #ifndef QV_H_
  13055. #define QV_H_
  13056. /*==========================================================================*/
  13057. /* QF customization for QV -- data members of the QActive class... */
  13058. /* QV event-queue used for AOs */
  13059. #define QF_EQUEUE_TYPE QEQueue
  13060. /*==========================================================================*/
  13061. #include &quot;qequeue.h&quot; /* QV kernel uses the native QP event queue */
  13062. #include &quot;qmpool.h&quot; /* QV kernel uses the native QP memory pool */
  13063. #include &quot;qf.h&quot; /* QF framework integrates directly with QV */
  13064. //============================================================================
  13065. $declare ${QV::QV-base}
  13066. /*==========================================================================*/
  13067. /* interface used only inside QF, but not in applications */
  13068. #ifdef QP_IMPL
  13069. /* QV-specific scheduler locking and event queue... */
  13070. $declare ${QV-impl}
  13071. /* Native QF event pool operations... */
  13072. $declare ${QF-QMPool-impl}
  13073. #endif /* QP_IMPL */
  13074. #endif /* QV_H_ */</text>
  13075. </file>
  13076. <!--${include::qk.h}-->
  13077. <file name="qk.h">
  13078. <text>/*! @file
  13079. * @brief QK/C (preemptive non-blocking kernel) platform-independent
  13080. * public interface.
  13081. */
  13082. #ifndef QK_H_
  13083. #define QK_H_
  13084. /*==========================================================================*/
  13085. /* QF configuration for QK -- data members of the QActive class... */
  13086. /* QK event-queue used for AOs */
  13087. #define QF_EQUEUE_TYPE QEQueue
  13088. /* QK thread type used for AOs
  13089. * QK uses this member to store the private Thread-Local Storage pointer.
  13090. */
  13091. #define QF_THREAD_TYPE void*
  13092. #include &quot;qequeue.h&quot; /* QK kernel uses the native QP event queue */
  13093. #include &quot;qmpool.h&quot; /* QK kernel uses the native QP memory pool */
  13094. #include &quot;qf.h&quot; /* QF framework integrates directly with QK */
  13095. /*==========================================================================*/
  13096. $declare ${QK::QK-extern-C}
  13097. /*--------------------------------------------------------------------------*/
  13098. $declare ${QK::QK-base}
  13099. /*==========================================================================*/
  13100. /* interface used only inside QF, but not in applications */
  13101. #ifdef QP_IMPL
  13102. /* QK-specific scheduler locking and event queue... */
  13103. $declare ${QK-impl}
  13104. /* Native QF event pool operations... */
  13105. $declare ${QF-QMPool-impl}
  13106. #endif /* QP_IMPL */
  13107. #endif /* QK_H_ */</text>
  13108. </file>
  13109. <!--${include::qxk.h}-->
  13110. <file name="qxk.h">
  13111. <text>/*! @file
  13112. * @brief QXK/C (preemptive dual-mode kernel) platform-independent
  13113. * public interface.
  13114. */
  13115. #ifndef QXK_H_
  13116. #define QXK_H_
  13117. /*==========================================================================*/
  13118. /* QF configuration for QXK -- data members of the QActive class... */
  13119. /* QXK event-queue used for AOs */
  13120. #define QF_EQUEUE_TYPE QEQueue
  13121. /* QXK OS-object used to store the private stack pointer for extended threads.
  13122. * (The private stack pointer is NULL for basic-threads).
  13123. */
  13124. #define QF_OS_OBJECT_TYPE void*
  13125. /* QXK thread type used to store the private Thread-Local Storage pointer */
  13126. #define QF_THREAD_TYPE void*
  13127. /*! Access Thread-Local Storage (TLS) and cast it on the given `type_` */
  13128. #define QXK_TLS(type_) ((type_)QXK_current()-&gt;thread)
  13129. /*==========================================================================*/
  13130. #include &quot;qequeue.h&quot; /* QXK kernel uses the native QP event queue */
  13131. #include &quot;qmpool.h&quot; /* QXK kernel uses the native QP memory pool */
  13132. #include &quot;qf.h&quot; /* QF framework integrates directly with QXK */
  13133. /*==========================================================================*/
  13134. $declare ${QXK::QXK-extern-C}
  13135. /*--------------------------------------------------------------------------*/
  13136. $declare ${QXK::QXK-base}
  13137. $declare ${QXK::QXThread}
  13138. $declare ${QXK::QXThreadVtable}
  13139. $declare ${QXK::QXSemaphore}
  13140. $declare ${QXK::QXMutex}
  13141. $declare ${QXK-macros}
  13142. /*==========================================================================*/
  13143. /* interface used only inside QP implementation, but not in applications */
  13144. #ifdef QP_IMPL
  13145. /* QXK implementation... */
  13146. $declare ${QXK-impl}
  13147. /* Native QF event pool operations... */
  13148. $declare ${QF-QMPool-impl}
  13149. #endif /* QP_IMPL */
  13150. #endif /* QXK_H_ */</text>
  13151. </file>
  13152. <!--${include::qs.h}-->
  13153. <file name="qs.h">
  13154. <text>/*! @file
  13155. * @brief QS/C platform-independent public interface.
  13156. */
  13157. #ifndef QS_H_
  13158. #define QS_H_
  13159. #ifndef Q_SPY
  13160. #error &quot;Q_SPY must be defined to include qs.h&quot;
  13161. #endif
  13162. /*==========================================================================*/
  13163. $declare ${QS-config}
  13164. /*==========================================================================*/
  13165. $declare ${QS}
  13166. /*==========================================================================*/
  13167. $declare ${QS-macros}
  13168. /*==========================================================================*/
  13169. /* Facilities for QS critical section */
  13170. /* QS-specific critical section */
  13171. #ifdef QS_CRIT_ENTRY /* separate QS critical section defined? */
  13172. #ifndef QS_CRIT_STAT_TYPE
  13173. #define QS_CRIT_STAT_
  13174. #define QS_CRIT_E_() QS_CRIT_ENTRY(dummy)
  13175. #define QS_CRIT_X_() QS_CRIT_EXIT(dummy); QS_REC_DONE()
  13176. #else
  13177. #define QS_CRIT_STAT_ QS_CRIT_STAT_TYPE critStat_;
  13178. #define QS_CRIT_E_() QS_CRIT_ENTRY(critStat_)
  13179. #define QS_CRIT_X_() QS_CRIT_EXIT(critStat_); QS_REC_DONE()
  13180. #endif /* QS_CRIT_STAT_TYPE */
  13181. #else /* separate QS critical section not defined--use the QF definition */
  13182. #ifndef QF_CRIT_STAT_TYPE
  13183. /*! This is an internal macro for defining the critical section
  13184. * status type.
  13185. * @details
  13186. * The purpose of this macro is to enable writing the same code for the
  13187. * case when critical section status type is defined and when it is not.
  13188. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  13189. * provides the definition of the critical section status variable.
  13190. * Otherwise this macro is empty.
  13191. * @sa #QF_CRIT_STAT_TYPE
  13192. */
  13193. #define QS_CRIT_STAT_
  13194. /*! This is an internal macro for entering a critical section.
  13195. * @details
  13196. * The purpose of this macro is to enable writing the same code for the
  13197. * case when critical section status type is defined and when it is not.
  13198. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  13199. * invokes QF_CRIT_ENTRY() passing the key variable as the parameter.
  13200. * Otherwise QF_CRIT_ENTRY() is invoked with a dummy parameter.
  13201. * @sa QF_CRIT_ENTRY()
  13202. */
  13203. #define QS_CRIT_E_() QF_CRIT_ENTRY(dummy)
  13204. /*! This is an internal macro for exiting a critical section.
  13205. * @details
  13206. * The purpose of this macro is to enable writing the same code for the
  13207. * case when critical section status type is defined and when it is not.
  13208. * If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
  13209. * invokes QF_CRIT_EXIT() passing the key variable as the parameter.
  13210. * Otherwise QF_CRIT_EXIT() is invoked with a dummy parameter.
  13211. * @sa QF_CRIT_EXIT()
  13212. */
  13213. #define QS_CRIT_X_() QF_CRIT_EXIT(dummy); QS_REC_DONE()
  13214. #elif (!defined QS_CRIT_STAT_)
  13215. #define QS_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_;
  13216. #define QS_CRIT_E_() QF_CRIT_ENTRY(critStat_)
  13217. #define QS_CRIT_X_() QF_CRIT_EXIT(critStat_); QS_REC_DONE()
  13218. #endif /* simple unconditional interrupt disabling used */
  13219. #endif /* separate QS critical section not defined */
  13220. /*==========================================================================*/
  13221. /* Macros for use in QUTest only */
  13222. #ifdef Q_UTEST
  13223. $declare ${QUTest}
  13224. /*--------------------------------------------------------------------------*/
  13225. /* QP-stub for QUTest
  13226. * NOTE: The QP-stub is needed for unit testing QP applications,
  13227. * but might NOT be needed for testing QP itself.
  13228. */
  13229. #if Q_UTEST != 0
  13230. $declare ${QUTest-stub::QS}
  13231. $declare ${QUTest-stub::QHsmDummy}
  13232. $declare ${QUTest-stub::QActiveDummy}
  13233. #endif /* Q_UTEST != 0 */
  13234. /*! QS macro to define the Test-Probe for a given `fun_` */
  13235. #define QS_TEST_PROBE_DEF(fun_) \
  13236. uint32_t const qs_tp_ = QS_getTestProbe_((void (*)(void))(fun_));
  13237. /*! QS macro to apply a Test-Probe */
  13238. #define QS_TEST_PROBE(code_) \
  13239. if (qs_tp_ != 0U) { code_ }
  13240. /*! QS macro to apply a Test-Probe */
  13241. #define QS_TEST_PROBE_ID(id_, code_) \
  13242. if (qs_tp_ == (uint32_t)(id_)) { code_ }
  13243. /*! QS macro to pause test execution and enter the test event-loop */
  13244. #define QS_TEST_PAUSE() (QS_test_pause_())
  13245. #else /* Q_UTEST not defined */
  13246. /* dummy definitions when not building for QUTEST */
  13247. #define QS_TEST_PROBE_DEF(fun_)
  13248. #define QS_TEST_PROBE(code_)
  13249. #define QS_TEST_PROBE_ID(id_, code_)
  13250. #define QS_TEST_PAUSE() ((void)0)
  13251. #endif /* Q_UTEST */
  13252. #endif /* QS_H_ */</text>
  13253. </file>
  13254. <!--${include::qs_dummy.h}-->
  13255. <file name="qs_dummy.h">
  13256. <text>/*! @file
  13257. * @brief Dummy definitions of the QS macros that avoid code generation from
  13258. * the QS instrumentation.
  13259. */
  13260. #ifndef QS_DUMMY_H_
  13261. #define QS_DUMMY_H_
  13262. #ifdef Q_SPY
  13263. #error &quot;Q_SPY must NOT be defined to include qs_dummy.h&quot;
  13264. #endif
  13265. #define QS_INIT(arg_) ((uint8_t)1U)
  13266. #define QS_EXIT() ((void)0)
  13267. #define QS_DUMP() ((void)0)
  13268. #define QS_GLB_FILTER(rec_) ((void)0)
  13269. #define QS_LOC_FILTER(qs_id_) ((void)0)
  13270. #define QS_GET_BYTE(pByte_) ((uint16_t)0xFFFFU)
  13271. #define QS_GET_BLOCK(pSize_) ((uint8_t *)0)
  13272. #define QS_BEGIN_ID(rec_, qs_id_) if (false) {
  13273. #define QS_END() }
  13274. #define QS_BEGIN_NOCRIT(rec_, qs_id_) if (false) {
  13275. #define QS_END_NOCRIT() }
  13276. #define QS_I8(width_, data_) ((void)0)
  13277. #define QS_U8(width_, data_) ((void)0)
  13278. #define QS_I16(width_, data_) ((void)0)
  13279. #define QS_U16(width_, data_) ((void)0)
  13280. #define QS_I32(width_, data_) ((void)0)
  13281. #define QS_U32(width_, data_) ((void)0)
  13282. #define QS_F32(width_, data_) ((void)0)
  13283. #define QS_F64(width_, data_) ((void)0)
  13284. #define QS_I64(width_, data_) ((void)0)
  13285. #define QS_U64(width_, data_) ((void)0)
  13286. #define QS_ENUM(group_, value_) ((void)0)
  13287. #define QS_STR(str_) ((void)0)
  13288. #define QS_MEM(mem_, size_) ((void)0)
  13289. #define QS_SIG(sig_, obj_) ((void)0)
  13290. #define QS_OBJ(obj_) ((void)0)
  13291. #define QS_FUN(fun_) ((void)0)
  13292. #define QS_SIG_DICTIONARY(sig_, obj_) ((void)0)
  13293. #define QS_OBJ_DICTIONARY(obj_) ((void)0)
  13294. #define QS_OBJ_ARR_DICTIONARY(obj_, idx_) ((void)0)
  13295. #define QS_FUN_DICTIONARY(fun_) ((void)0)
  13296. #define QS_USR_DICTIONARY(rec_) ((void)0)
  13297. #define QS_ENUM_DICTIONARY(value_, group_) ((void)0)
  13298. #define QS_ASSERTION(module_, loc_, delay_) ((void)0)
  13299. #define QS_FLUSH() ((void)0)
  13300. #define QS_TEST_PROBE_DEF(fun_)
  13301. #define QS_TEST_PROBE(code_)
  13302. #define QS_TEST_PROBE_ID(id_, code_)
  13303. #define QS_TEST_PAUSE() ((void)0)
  13304. #define QS_OUTPUT() ((void)0)
  13305. #define QS_RX_INPUT() ((void)0)
  13306. /*==========================================================================*/
  13307. /* internal QS macros used only in the QP components */
  13308. #ifdef QP_IMPL
  13309. /* predefined QS trace records */
  13310. #define QS_BEGIN_PRE_(rec_, qs_id_) if (false) {
  13311. #define QS_END_PRE_() }
  13312. #define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_) if (false) {
  13313. #define QS_END_NOCRIT_PRE_() }
  13314. #define QS_U8_PRE_(data_) ((void)0)
  13315. #define QS_2U8_PRE_(data1_, data2_) ((void)0)
  13316. #define QS_U16_PRE_(data_) ((void)0)
  13317. #define QS_U32_PRE_(data_) ((void)0)
  13318. #define QS_TIME_PRE_() ((void)0)
  13319. #define QS_SIG_PRE_(sig_) ((void)0)
  13320. #define QS_EVS_PRE_(size_) ((void)0)
  13321. #define QS_OBJ_PRE_(obj_) ((void)0)
  13322. #define QS_FUN_PRE_(fun_) ((void)0)
  13323. #define QS_EQC_PRE_(ctr_) ((void)0)
  13324. #define QS_MPC_PRE_(ctr_) ((void)0)
  13325. #define QS_MPS_PRE_(size_) ((void)0)
  13326. #define QS_TEC_PRE_(ctr_) ((void)0)
  13327. #define QS_CRIT_STAT_
  13328. #define QF_QS_CRIT_ENTRY() ((void)0)
  13329. #define QF_QS_CRIT_EXIT() ((void)0)
  13330. #define QF_QS_ISR_ENTRY(isrnest_, prio_) ((void)0)
  13331. #define QF_QS_ISR_EXIT(isrnest_, prio_) ((void)0)
  13332. #define QF_QS_ACTION(act_) ((void)0)
  13333. #endif /* QP_IMPL */
  13334. #endif /* QS_DUMMY_H_ */</text>
  13335. </file>
  13336. <!--${include::qs_pkg.h}-->
  13337. <file name="qs_pkg.h">
  13338. <text>/*! @file
  13339. * @brief Internal (package scope) QS/C interface.
  13340. */
  13341. #ifndef QS_PKG_H_
  13342. #define QS_PKG_H_
  13343. /*==========================================================================*/
  13344. /*! QS received record types (RX channel)
  13345. * @details
  13346. * This enumeration specifies the record types for the QS receive channel
  13347. */
  13348. enum QSpyRxRecords {
  13349. QS_RX_INFO, /*!&lt; query Target info (ver, config, tstamp) */
  13350. QS_RX_COMMAND, /*!&lt; execute a user-defined command in the Target */
  13351. QS_RX_RESET, /*!&lt; reset the Target */
  13352. QS_RX_TICK, /*!&lt; call QTIMEEVT_TICK_X() in the Target */
  13353. QS_RX_PEEK, /*!&lt; peek Target memory */
  13354. QS_RX_POKE, /*!&lt; poke Target memory */
  13355. QS_RX_FILL, /*!&lt; fill Target memory */
  13356. QS_RX_TEST_SETUP, /*!&lt; test setup */
  13357. QS_RX_TEST_TEARDOWN, /*!&lt; test teardown */
  13358. QS_RX_TEST_PROBE, /*!&lt; set a Test-Probe in the Target */
  13359. QS_RX_GLB_FILTER, /*!&lt; set global filters in the Target */
  13360. QS_RX_LOC_FILTER, /*!&lt; set local filters in the Target */
  13361. QS_RX_AO_FILTER, /*!&lt; set local AO filter in the Target */
  13362. QS_RX_CURR_OBJ, /*!&lt; set the &quot;current-object&quot; in the Target */
  13363. QS_RX_TEST_CONTINUE, /*!&lt; continue a test after QS_TEST_PAUSE() */
  13364. QS_RX_QUERY_CURR, /*!&lt; query the &quot;current object&quot; in the Target */
  13365. QS_RX_EVENT /*!&lt; inject an event to the Target */
  13366. };
  13367. /*==========================================================================*/
  13368. /*! Frame character of the QS output protocol */
  13369. #define QS_FRAME (0x7EU)
  13370. /*! Escape character of the QS output protocol */
  13371. #define QS_ESC (0x7DU)
  13372. /*! The expected checksum value over a correct QS record */
  13373. #define QS_GOOD_CHKSUM (0xFFU)
  13374. /*! Escape modifier of the QS output protocol */
  13375. /**
  13376. * @details
  13377. * The escaped byte is XOR-ed with the escape modifier before it is inserted
  13378. * into the QS buffer.
  13379. */
  13380. #define QS_ESC_XOR (0x20U)
  13381. /*==========================================================================*/
  13382. /*! Internal QS macro to begin a predefined QS record with
  13383. * entering critical section.
  13384. *
  13385. * @note This macro is intended to use only inside QP components and NOT
  13386. * at the application level.
  13387. * @sa QS_BEGIN_ID()
  13388. */
  13389. #define QS_BEGIN_PRE_(rec_, qs_id_) \
  13390. if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qs_id_)) { \
  13391. QS_CRIT_E_(); \
  13392. QS_beginRec_((uint_fast8_t)(rec_));
  13393. /*! Internal QS macro to end a predefined QS record with
  13394. * exiting critical section.
  13395. *
  13396. * @note This macro is intended to use only inside QP components and NOT
  13397. * at the application level.
  13398. * @sa QS_END()
  13399. */
  13400. #define QS_END_PRE_() \
  13401. QS_endRec_(); \
  13402. QS_CRIT_X_(); \
  13403. }
  13404. /*! Internal macro to begin a predefined QS record without
  13405. * entering critical section.
  13406. *
  13407. * @note This macro is intended to use only inside QP components and NOT
  13408. * at the application level.
  13409. * @sa QS_BEGIN_NOCRIT()
  13410. */
  13411. #define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_) \
  13412. if (QS_GLB_CHECK_(rec_) &amp;&amp; QS_LOC_CHECK_(qs_id_)) { \
  13413. QS_beginRec_((uint_fast8_t)(rec_));
  13414. /*! Internal QS macro to end a predefined QS record without
  13415. * exiting critical section
  13416. *
  13417. * @note This macro is intended to use only inside QP components and NOT
  13418. * at the application level. @sa #QS_END_NOCRIT
  13419. */
  13420. #define QS_END_NOCRIT_PRE_() QS_endRec_(); }
  13421. /*! Internal QS macro to output a predefined uint8_t data element */
  13422. #define QS_U8_PRE_(data_) (QS_u8_raw_((uint8_t)(data_)))
  13423. /*! Internal QS macro to output 2 predefined uint8_t data elements */
  13424. #define QS_2U8_PRE_(data1_, data2_) \
  13425. (QS_2u8_raw_((uint8_t)(data1_), (uint8_t)(data2_)))
  13426. /*! Internal QS macro to output an predefined uint16_t data element */
  13427. #define QS_U16_PRE_(data_) (QS_u16_raw_((uint16_t)(data_)))
  13428. /*! Internal QS macro to output a predefined uint32_t data element */
  13429. #define QS_U32_PRE_(data_) (QS_u32_raw_((uint32_t)(data_)))
  13430. /*! Internal QS macro to output a predefined zero-terminated string element */
  13431. #define QS_STR_PRE_(msg_) (QS_str_raw_((msg_)))
  13432. #if (!defined Q_SIGNAL_SIZE || (Q_SIGNAL_SIZE == 1U))
  13433. /*! Internal macro to output an unformatted event signal data element */
  13434. /**
  13435. * @note the size of the pointer depends on the macro #Q_SIGNAL_SIZE.
  13436. */
  13437. #define QS_SIG_PRE_(sig_) (QS_u8_raw_((uint8_t)sig_))
  13438. #elif (Q_SIGNAL_SIZE == 2U)
  13439. #define QS_SIG_PRE_(sig_) (QS_u16_raw_((uint16_t)sig_))
  13440. #elif (Q_SIGNAL_SIZE == 4U)
  13441. #define QS_SIG_PRE_(sig_) (QS_u32_raw_((uint32_t)sig_))
  13442. #endif
  13443. #define QS_OBJ_PRE_(obj_) (QS_obj_raw_(obj_))
  13444. #if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 1U))
  13445. #define QS_FUN_PRE_(fun_) (QS_u8_raw_((uint8_t)(fun_)))
  13446. #elif (QS_FUN_PTR_SIZE == 2U)
  13447. #define QS_FUN_PRE_(fun_) (QS_u16_raw_((uint16_t)(fun_)))
  13448. #elif (QS_FUN_PTR_SIZE == 4U)
  13449. #define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_)))
  13450. #elif (QS_FUN_PTR_SIZE == 8U)
  13451. #define QS_FUN_PRE_(fun_) (QS_u64_raw_((uint64_t)(fun_)))
  13452. #else
  13453. /*! Internal macro to output an unformatted function pointer */
  13454. /** @note the size of the pointer depends on the macro #QS_FUN_PTR_SIZE.
  13455. * If the size is not defined the size of pointer is assumed 4-bytes.
  13456. */
  13457. #define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_)))
  13458. #endif
  13459. /*==========================================================================*/
  13460. #if (!defined QF_EQUEUE_CTR_SIZE || (QF_EQUEUE_CTR_SIZE == 1U))
  13461. /*! Internal QS macro to output an unformatted event queue counter
  13462. * data element. */
  13463. /**
  13464. * @note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
  13465. */
  13466. #define QS_EQC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
  13467. #elif (QF_EQUEUE_CTR_SIZE == 2U)
  13468. #define QS_EQC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
  13469. #elif (QF_EQUEUE_CTR_SIZE == 4U)
  13470. #define QS_EQC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_))
  13471. #endif
  13472. #if (!defined QF_EVENT_SIZ_SIZE || (QF_EVENT_SIZ_SIZE == 1U))
  13473. /*! Internal QS macro to output an unformatted event size
  13474. * data element. */
  13475. /**
  13476. * @note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
  13477. */
  13478. #define QS_EVS_PRE_(size_) QS_u8_raw_((uint8_t)(size_))
  13479. #elif (QF_EVENT_SIZ_SIZE == 2U)
  13480. #define QS_EVS_PRE_(size_) QS_u16_raw_((uint16_t)(size_))
  13481. #elif (QF_EVENT_SIZ_SIZE == 4U)
  13482. #define QS_EVS_PRE_(size_) QS_u32_raw_((uint32_t)(size_))
  13483. #endif
  13484. #if (!defined QF_MPOOL_SIZ_SIZE || (QF_MPOOL_SIZ_SIZE == 1U))
  13485. /*! Internal QS macro to output an unformatted memory pool
  13486. * block-size data element */
  13487. /**
  13488. * @note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
  13489. */
  13490. #define QS_MPS_PRE_(size_) QS_u8_raw_((uint8_t)(size_))
  13491. #elif (QF_MPOOL_SIZ_SIZE == 2U)
  13492. #define QS_MPS_PRE_(size_) QS_u16_raw_((uint16_t)(size_))
  13493. #elif (QF_MPOOL_SIZ_SIZE == 4U)
  13494. #define QS_MPS_PRE_(size_) QS_u32_raw_((uint32_t)(size_))
  13495. #endif
  13496. #if (!defined QF_MPOOL_CTR_SIZE || (QF_MPOOL_CTR_SIZE == 1U))
  13497. /*! Internal QS macro to output an unformatted memory pool
  13498. * block-counter data element. */
  13499. /**
  13500. * @note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
  13501. */
  13502. #define QS_MPC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
  13503. #elif (QF_MPOOL_CTR_SIZE == 2U)
  13504. #define QS_MPC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
  13505. #elif (QF_MPOOL_CTR_SIZE == 4U)
  13506. #define QS_MPC_PRE_(ctr_) QS_u32_raw_((uint16_t)(ctr_))
  13507. #endif
  13508. #if (!defined QF_TIMEEVT_CTR_SIZE || (QF_TIMEEVT_CTR_SIZE == 1U))
  13509. /*! Internal QS macro to output an unformatted time event
  13510. * tick-counter data element */
  13511. /**
  13512. * @note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
  13513. */
  13514. #define QS_TEC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
  13515. #elif (QF_TIMEEVT_CTR_SIZE == 2U)
  13516. #define QS_TEC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
  13517. #elif (QF_TIMEEVT_CTR_SIZE == 4U)
  13518. #define QS_TEC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_))
  13519. #endif
  13520. /*==========================================================================*/
  13521. /*! Internal QS macro to insert an un-escaped byte into the QS buffer */
  13522. #define QS_INSERT_BYTE_(b_) \
  13523. buf[head] = (b_); \
  13524. ++head; \
  13525. if (head == end) { \
  13526. head = 0U; \
  13527. }
  13528. /*! Internal QS macro to insert an escaped byte into the QS buffer */
  13529. #define QS_INSERT_ESC_BYTE_(b_) \
  13530. chksum = (uint8_t)(chksum + (b_)); \
  13531. if (((b_) != QS_FRAME) &amp;&amp; ((b_) != QS_ESC)) { \
  13532. QS_INSERT_BYTE_(b_) \
  13533. } \
  13534. else { \
  13535. QS_INSERT_BYTE_(QS_ESC) \
  13536. QS_INSERT_BYTE_((uint8_t)((b_) ^ QS_ESC_XOR))\
  13537. ++QS_priv_.used; \
  13538. }
  13539. #endif /* QS_PKG_H_ */</text>
  13540. </file>
  13541. <!--${include::qpc.h}-->
  13542. <file name="qpc.h">
  13543. <text>/*! @file
  13544. * @brief QP/C public interface including backwards-compatibility layer
  13545. * @details
  13546. * This header file must be included directly or indirectly
  13547. * in all application modules (*.c files) that use QP/C.
  13548. */
  13549. #ifndef QPC_H_
  13550. #define QPC_H_
  13551. #ifdef __cplusplus
  13552. extern &quot;C&quot; {
  13553. #endif
  13554. /*==========================================================================*/
  13555. #include &quot;qf_port.h&quot; /* QF/C port from the port directory */
  13556. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13557. #ifdef Q_SPY /* software tracing enabled? */
  13558. #include &quot;qs_port.h&quot; /* QS/C port from the port directory */
  13559. #else
  13560. #include &quot;qs_dummy.h&quot; /* QS/C dummy (inactive) interface */
  13561. #endif
  13562. /*==========================================================================*/
  13563. #ifndef QP_API_VERSION
  13564. /*! Specifies the backwards compatibility with the QP/C API version.
  13565. * @details
  13566. * For example, QP_API_VERSION==691 will cause generating the compatibility
  13567. * layer with QP/C version 6.9.1 and newer, but not older than 6.9.1.
  13568. * QP_API_VERSION==0 causes generation of the maximum currently supported
  13569. * backwards compatibility. This is the default.&lt;br&gt;
  13570. * &lt;br&gt;
  13571. * Conversely, QP_API_VERSION==9999 means that no compatibility layer should
  13572. * be generated. This setting is useful for checking if an application
  13573. * complies with the latest QP/C API.
  13574. */
  13575. #define QP_API_VERSION 0
  13576. #endif /* #ifndef QP_API_VERSION */
  13577. /*==========================================================================*/
  13578. /* QP API compatibility layer... */
  13579. #if (QP_API_VERSION &lt; 700)
  13580. /*! @deprecated plain 'char' is no longer forbidden in MISRA-C 2012 */
  13581. typedef char char_t;
  13582. /*! Static (compile-time) assertion.
  13583. *
  13584. * @deprecated
  13585. * Use Q_ASSERT_STATIC() or better yet `_Static_assert()` instead.
  13586. */
  13587. #define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_)
  13588. /*==========================================================================*/
  13589. #if (QP_API_VERSION &lt; 691)
  13590. /*! @deprecated enable the QS global filter */
  13591. #define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_))
  13592. /*! @deprecated disable the QS global filter */
  13593. #define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_))
  13594. /*! @deprecated enable the QS local filter for SM (state machine) object */
  13595. #define QS_FILTER_SM_OBJ(obj_) ((void)0)
  13596. /*! @deprecated enable the QS local filter for AO (active objects) */
  13597. #define QS_FILTER_AO_OBJ(obj_) ((void)0)
  13598. /*! @deprecated enable the QS local filter for MP (memory pool) object */
  13599. #define QS_FILTER_MP_OBJ(obj_) ((void)0)
  13600. /*! @deprecated enable the QS local filter for EQ (event queue) object */
  13601. #define QS_FILTER_EQ_OBJ(obj_) ((void)0)
  13602. /*! @deprecated enable the QS local filter for TE (time event) object */
  13603. #define QS_FILTER_TE_OBJ(obj_) ((void)0)
  13604. #ifdef Q_SPY
  13605. /*! @deprecated local Filter for a generic application object `obj_`. */
  13606. #define QS_FILTER_AP_OBJ(obj_) (QS_priv_.locFilter_AP = (obj_))
  13607. /*! @deprecated begin of a user QS record, instead use QS_BEGIN_ID() */
  13608. #define QS_BEGIN(rec_, obj_) \
  13609. if (((QS_priv_.glbFilter[(uint_fast8_t)(rec_) &gt;&gt; 3U] \
  13610. &amp; (1U &lt;&lt; ((uint_fast8_t)(rec_) &amp; 7U))) != 0U) \
  13611. &amp;&amp; ((QS_priv_.locFilter_AP == (void *)0) \
  13612. || (QS_priv_.locFilter_AP == (obj_)))) \
  13613. { \
  13614. QS_CRIT_STAT_ \
  13615. QS_CRIT_E_(); \
  13616. QS_beginRec_((uint_fast8_t)(rec_)); \
  13617. QS_TIME_PRE_(); {
  13618. /*! @deprecated Output formatted uint32_t to the QS record */
  13619. #define QS_U32_HEX(width_, data_) \
  13620. (QS_u32_fmt_((uint8_t)(((width_) &lt;&lt; 4)) | QS_HEX_FMT, (data_)))
  13621. #else
  13622. #define QS_FILTER_AP_OBJ(obj_) ((void)0)
  13623. #define QS_BEGIN(rec_, obj_) if (false) {
  13624. #define QS_U32_HEX(width_, data_) ((void)0)
  13625. #endif
  13626. /*==========================================================================*/
  13627. #if (QP_API_VERSION &lt; 660)
  13628. /*! @deprecated casting to QXThreadHandler
  13629. * instead use: the new signature of QXThreadHandler and don't cast
  13630. */
  13631. #define Q_XTHREAD_CAST(handler_) ((QXThreadHandler)(handler_))
  13632. /*==========================================================================*/
  13633. #if (QP_API_VERSION &lt; 580)
  13634. /*! @deprecated call to the QMSM_INIT() operation; instead use: QHSM_INIT() */
  13635. #define QMSM_INIT(me_, e_) QHSM_INIT((me_), (e_))
  13636. /*! @deprecated call to the QMSM_DISPATCH() operation;
  13637. * instead use: QHSM_DISPATCH() */
  13638. #define QMSM_DISPATCH(me_, e_) QHSM_DISPATCH((me_), (e_), 0U)
  13639. #endif /* QP_API_VERSION &lt; 580 */
  13640. #endif /* QP_API_VERSION &lt; 660 */
  13641. #endif /* QP_API_VERSION &lt; 691 */
  13642. #endif /* QP_API_VERSION &lt; 700 */
  13643. #ifdef __cplusplus
  13644. }
  13645. #endif
  13646. #endif /* QPC_H_ */</text>
  13647. </file>
  13648. <!--${include::qstamp.h}-->
  13649. <file name="qstamp.h">
  13650. <text>/*! @file
  13651. * @brief Application build time-stamp interface
  13652. */
  13653. #ifndef QSTAMP_H_
  13654. #define QSTAMP_H_
  13655. extern char const Q_BUILD_DATE[12];
  13656. extern char const Q_BUILD_TIME[9];
  13657. #endif /* QSTAMP_H_ */</text>
  13658. </file>
  13659. </directory>
  13660. <!--${src}-->
  13661. <directory name="src">
  13662. <!--${src::qf}-->
  13663. <directory name="qf">
  13664. <!--${src::qf::qep_hsm.c}-->
  13665. <file name="qep_hsm.c">
  13666. <text>/*! @file
  13667. * @brief ::QHsm implementation
  13668. */
  13669. #define QP_IMPL /* this is QP implementation */
  13670. #include &quot;qep_port.h&quot; /* QEP port */
  13671. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13672. #ifdef Q_SPY /* QS software tracing enabled? */
  13673. #include &quot;qs_port.h&quot; /* QS port */
  13674. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13675. #else
  13676. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13677. #endif /* Q_SPY */
  13678. Q_DEFINE_THIS_MODULE(&quot;qep_hsm&quot;)
  13679. /*==========================================================================*/
  13680. $define ${QEP::QP_versionStr[8]}
  13681. /*! Immutable events corresponding to the reserved signals.
  13682. *
  13683. * @details
  13684. * Static, immutable reserved events that the QEP event processor sends
  13685. * to state handler functions of QHsm-style state machine to execute entry
  13686. * actions, exit actions, and initial transitions.
  13687. */
  13688. static QEvt const l_reservedEvt_[] = {
  13689. { (QSignal)Q_EMPTY_SIG, 0U, 0U },
  13690. { (QSignal)Q_ENTRY_SIG, 0U, 0U },
  13691. { (QSignal)Q_EXIT_SIG, 0U, 0U },
  13692. { (QSignal)Q_INIT_SIG, 0U, 0U }
  13693. };
  13694. /*! helper function to trigger reserved event in an QHsm
  13695. * @private @memberof QHsm
  13696. *
  13697. * @param[in] state state handler function
  13698. * @param[in] sig reserved signal to trigger
  13699. */
  13700. static inline QState QHsm_reservedEvt_(
  13701. QHsm * const me,
  13702. QStateHandler const state,
  13703. enum QReservedSig const sig)
  13704. {
  13705. return (*state)(me, &amp;l_reservedEvt_[sig]);
  13706. }
  13707. /*! maximum depth of state nesting in a HSM (including the top level),
  13708. * must be &gt;= 3
  13709. */
  13710. enum { QHSM_MAX_NEST_DEPTH_ = 6};
  13711. $define ${QEP::QHsm}</text>
  13712. </file>
  13713. <!--${src::qf::qep_msm.c}-->
  13714. <file name="qep_msm.c">
  13715. <text>#define QP_IMPL /* this is QP implementation */
  13716. #include &quot;qep_port.h&quot; /* QEP port */
  13717. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13718. #ifdef Q_SPY /* QS software tracing enabled? */
  13719. #include &quot;qs_port.h&quot; /* QS port */
  13720. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13721. #else
  13722. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13723. #endif /* Q_SPY */
  13724. Q_DEFINE_THIS_MODULE(&quot;qep_msm&quot;)
  13725. /*==========================================================================*/
  13726. /*! internal QEP constants */
  13727. /*! top state object for QMsm-style state machines. */
  13728. static struct QMState const l_msm_top_s = {
  13729. (struct QMState *)0,
  13730. Q_STATE_CAST(0),
  13731. Q_ACTION_CAST(0),
  13732. Q_ACTION_CAST(0),
  13733. Q_ACTION_CAST(0)
  13734. };
  13735. /*! maximum depth of entry levels in a MSM for transition to history. */
  13736. enum { QMSM_MAX_ENTRY_DEPTH_ = 4};
  13737. /*==========================================================================*/
  13738. $define ${QEP::QMsm}</text>
  13739. </file>
  13740. <!--${src::qf::qf_act.c}-->
  13741. <file name="qf_act.c">
  13742. <text>/*! @file
  13743. * @brief Empty file kept only for backwards compatibility.
  13744. *
  13745. * @deprecated please stop using this file.
  13746. *
  13747. * @sa qf_qact.c
  13748. */
  13749. extern char const dummy; /* declaration */
  13750. char const dummy = '\0'; /* definition */</text>
  13751. </file>
  13752. <!--${src::qf::qf_actq.c}-->
  13753. <file name="qf_actq.c">
  13754. <text>/*! @file
  13755. * @brief ::QActive native queue operations (based on ::QEQueue)
  13756. *
  13757. * @note
  13758. * This `qf_actq.c` source file needs to be included in the application
  13759. * build only when the native ::QEQueue queue is used for ::QActive objects
  13760. * (instead of a message queue of an RTOS).
  13761. */
  13762. #define QP_IMPL /* this is QP implementation */
  13763. #include &quot;qf_port.h&quot; /* QF port */
  13764. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13765. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13766. #ifdef Q_SPY /* QS software tracing enabled? */
  13767. #include &quot;qs_port.h&quot; /* QS port */
  13768. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13769. #else
  13770. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13771. #endif /* Q_SPY */
  13772. Q_DEFINE_THIS_MODULE(&quot;qf_actq&quot;)
  13773. /*==========================================================================*/
  13774. $define ${QF::QActive::post_}
  13775. $define ${QF::QActive::postLIFO_}
  13776. $define ${QF::QActive::get_}
  13777. $define ${QF::QF-base::getQueueMin}
  13778. /*==========================================================================*/
  13779. /*! Perform downcast to QTicker pointer.
  13780. *
  13781. * @details
  13782. * This macro encapsulates the downcast to (QTicker *), which is used in
  13783. * QTicker_init_() and QTicker_dispatch_(). Such casts violate MISRA-C 2012
  13784. * Rule 11.3(req) &quot;cast from pointer to object type to pointer to different
  13785. * object type&quot;.
  13786. */
  13787. #define QTICKER_CAST_(me_) ((QActive *)(me_))
  13788. $define ${QF::QTicker}</text>
  13789. </file>
  13790. <!--${src::qf::qf_defer.c}-->
  13791. <file name="qf_defer.c">
  13792. <text>/*! @file
  13793. * @brief QActive_defer() and QActive_recall() implementation.
  13794. */
  13795. #define QP_IMPL /* this is QP implementation */
  13796. #include &quot;qf_port.h&quot; /* QF port */
  13797. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13798. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13799. #ifdef Q_SPY /* QS software tracing enabled? */
  13800. #include &quot;qs_port.h&quot; /* QS port */
  13801. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13802. #else
  13803. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13804. #endif /* Q_SPY */
  13805. Q_DEFINE_THIS_MODULE(&quot;qf_defer&quot;)
  13806. $define ${QF::QActive::defer}
  13807. $define ${QF::QActive::recall}
  13808. $define ${QF::QActive::flushDeferred}</text>
  13809. </file>
  13810. <!--${src::qf::qf_dyn.c}-->
  13811. <file name="qf_dyn.c">
  13812. <text>/*! @file
  13813. * @brief QF/C dynamic event management
  13814. */
  13815. #define QP_IMPL /* this is QP implementation */
  13816. #include &quot;qf_port.h&quot; /* QF port */
  13817. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13818. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13819. #ifdef Q_SPY /* QS software tracing enabled? */
  13820. #include &quot;qs_port.h&quot; /* QS port */
  13821. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13822. #else
  13823. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13824. #endif /* Q_SPY */
  13825. #if (QF_MAX_EPOOL &gt; 0U) /* dynamic events configured? */
  13826. Q_DEFINE_THIS_MODULE(&quot;qf_dyn&quot;)
  13827. //============================================================================
  13828. $define ${QF::QF-pkg::maxPool_}
  13829. $define ${QF::QF-pkg::ePool_[QF_MAX_EPOOL]}
  13830. //============================================================================
  13831. $define ${QEP::QEvt}
  13832. //============================================================================
  13833. $define ${QF::QF-dyn}
  13834. #endif /* (QF_MAX_EPOOL &gt; 0U) dynamic events configured */</text>
  13835. </file>
  13836. <!--${src::qf::qf_mem.c}-->
  13837. <file name="qf_mem.c">
  13838. <text>/*! @file
  13839. * @brief ::QMPool implementatin (Memory Pool)
  13840. */
  13841. #define QP_IMPL /* this is QP implementation */
  13842. #include &quot;qf_port.h&quot; /* QF port */
  13843. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13844. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13845. #ifdef Q_SPY /* QS software tracing enabled? */
  13846. #include &quot;qs_port.h&quot; /* QS port */
  13847. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13848. #else
  13849. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13850. #endif /* Q_SPY */
  13851. Q_DEFINE_THIS_MODULE(&quot;qf_mem&quot;)
  13852. $define ${QF::QMPool}</text>
  13853. </file>
  13854. <!--${src::qf::qf_qact.c}-->
  13855. <file name="qf_qact.c">
  13856. <text>/*! @file
  13857. * @brief QActive_ctor() definition
  13858. *
  13859. * @details
  13860. * This file must remain separate from the rest to avoid pulling in the
  13861. * &quot;virtual&quot; functions QHsm::QHsm_init_() and QHsm::QHsm_dispatch_() in
  13862. * case they are not used by the application.
  13863. *
  13864. * @sa qf_qmact.c
  13865. */
  13866. #define QP_IMPL /* this is QP implementation */
  13867. #include &quot;qf_port.h&quot; /* QF port */
  13868. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13869. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13870. Q_DEFINE_THIS_MODULE(&quot;qf_qact&quot;)
  13871. //============================================================================
  13872. $define ${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]}
  13873. $define ${QF::QF-base::intLock_}
  13874. $define ${QF::QF-base::intNest_}
  13875. $define ${QF::QF-pkg::readySet_}
  13876. $define ${QF::QF-pkg::bzero}
  13877. //============================================================================
  13878. $define ${QF::QActive::ctor}
  13879. $define ${QF::QActive::register_}
  13880. $define ${QF::QActive::unregister_}
  13881. //============================================================================
  13882. $define ${QF-types::QF_LOG2}</text>
  13883. </file>
  13884. <!--${src::qf::qf_qmact.c}-->
  13885. <file name="qf_qmact.c">
  13886. <text>/*! @file
  13887. * @brief QMActive_ctor() definition
  13888. *
  13889. * @details
  13890. * This file must remain separate from the rest to avoid pulling in the
  13891. * &quot;virtual&quot; functions QHsm::QHsm_init_() and QHsm::QHsm_dispatch_() in
  13892. * case they are not used by the application.
  13893. *
  13894. * @sa qf_qact.c
  13895. */
  13896. #define QP_IMPL /* this is QP implementation */
  13897. #include &quot;qf_port.h&quot; /* QF port */
  13898. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13899. /*Q_DEFINE_THIS_MODULE(&quot;qf_qmact&quot;)*/
  13900. /*
  13901. * This internal macro encapsulates the violation of MISRA-C 2012
  13902. * Rule 11.3(req) &quot;A cast shall not be performed between a pointer to
  13903. * object type and a poiner to a different object type&quot;.
  13904. */
  13905. #define QMSM_CAST_(ptr_) ((QMsm *)(ptr_))
  13906. $define ${QF::QMActive}</text>
  13907. </file>
  13908. <!--${src::qf::qf_qeq.c}-->
  13909. <file name="qf_qeq.c">
  13910. <text>/*! @file
  13911. * @brief ::QEQueue implementation (QP native thread-safe queue)
  13912. */
  13913. #define QP_IMPL /* this is QP implementation */
  13914. #include &quot;qf_port.h&quot; /* QF port */
  13915. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13916. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13917. #ifdef Q_SPY /* QS software tracing enabled? */
  13918. #include &quot;qs_port.h&quot; /* QS port */
  13919. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13920. #else
  13921. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13922. #endif /* Q_SPY */
  13923. Q_DEFINE_THIS_MODULE(&quot;qf_qeq&quot;)
  13924. $define ${QF::QEQueue}</text>
  13925. </file>
  13926. <!--${src::qf::qf_ps.c}-->
  13927. <file name="qf_ps.c">
  13928. <text>/*! @file
  13929. * @brief Publish-Subscribe services
  13930. */
  13931. #define QP_IMPL /* this is QP implementation */
  13932. #include &quot;qf_port.h&quot; /* QF port */
  13933. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13934. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13935. #ifdef Q_SPY /* QS software tracing enabled? */
  13936. #include &quot;qs_port.h&quot; /* QS port */
  13937. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13938. #else
  13939. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13940. #endif /* Q_SPY */
  13941. Q_DEFINE_THIS_MODULE(&quot;qf_ps&quot;)
  13942. /*==========================================================================*/
  13943. $define ${QF::QActive::subscrList_}
  13944. $define ${QF::QActive::maxPubSignal_}
  13945. $define ${QF::QActive::psInit}
  13946. $define ${QF::QActive::publish_}
  13947. $define ${QF::QActive::subscribe}
  13948. $define ${QF::QActive::unsubscribe}
  13949. $define ${QF::QActive::unsubscribeAll}</text>
  13950. </file>
  13951. <!--${src::qf::qf_time.c}-->
  13952. <file name="qf_time.c">
  13953. <text>/*! @file
  13954. * @brief QF/C time events and time management services
  13955. */
  13956. #define QP_IMPL /* this is QP implementation */
  13957. #include &quot;qf_port.h&quot; /* QF port */
  13958. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  13959. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13960. #ifdef Q_SPY /* QS software tracing enabled? */
  13961. #include &quot;qs_port.h&quot; /* QS port */
  13962. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13963. #else
  13964. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13965. #endif /* Q_SPY */
  13966. Q_DEFINE_THIS_MODULE(&quot;qf_time&quot;)
  13967. #ifdef Q_SPY
  13968. /*! intertnal macro to encapsulate a MISRA deviation
  13969. * @details
  13970. * This internal macro encapsulates the violation of MISRA-C 2012
  13971. * Rule 11.5(A) &quot;A conversion should not be performed from pointer to void
  13972. * into pointer to object&quot;.
  13973. */
  13974. #define QACTIVE_CAST_(ptr_) ((QActive *)(ptr_))
  13975. #endif
  13976. $define ${QF::QTimeEvt}</text>
  13977. </file>
  13978. </directory>
  13979. <!--${src::qv}-->
  13980. <directory name="qv">
  13981. <!--${src::qv::qv.c}-->
  13982. <file name="qv.c">
  13983. <text>/*! @file
  13984. * @brief Cooperative QV kernel, implementation of kernel-specific functions.
  13985. */
  13986. #define QP_IMPL /* this is QP implementation */
  13987. #include &quot;qf_port.h&quot; /* QF port */
  13988. #include &quot;qf_pkg.h&quot; /* QF package-scope internal interface */
  13989. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  13990. #ifdef Q_SPY /* QS software tracing enabled? */
  13991. #include &quot;qs_port.h&quot; /* QS port */
  13992. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  13993. #else
  13994. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  13995. #endif /* Q_SPY */
  13996. /* protection against including this source file in a wrong project */
  13997. #ifndef QV_H_
  13998. #error &quot;Source file included in a project NOT based on the QV kernel&quot;
  13999. #endif /* QV_H_ */
  14000. Q_DEFINE_THIS_MODULE(&quot;qv&quot;)
  14001. /*==========================================================================*/
  14002. $define ${QV::QV-base}
  14003. $define ${QV::QF-cust}
  14004. $define ${QV::QActive}</text>
  14005. </file>
  14006. </directory>
  14007. <!--${src::qk}-->
  14008. <directory name="qk">
  14009. <!--${src::qk::qk.c}-->
  14010. <file name="qk.c">
  14011. <text>/*! @file
  14012. * @brief QK preemptive kernel implementation
  14013. */
  14014. #define QP_IMPL /* this is QP implementation */
  14015. #include &quot;qf_port.h&quot; /* QF port */
  14016. #include &quot;qf_pkg.h&quot; /* QF package-scope internal interface */
  14017. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14018. #ifdef Q_SPY /* QS software tracing enabled? */
  14019. #include &quot;qs_port.h&quot; /* QS port */
  14020. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14021. #else
  14022. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  14023. #endif /* Q_SPY */
  14024. /* protection against including this source file in a wrong project */
  14025. #ifndef QK_H_
  14026. #error &quot;Source file included in a project NOT based on the QK kernel&quot;
  14027. #endif /* QK_H_ */
  14028. Q_DEFINE_THIS_MODULE(&quot;qk&quot;)
  14029. /*==========================================================================*/
  14030. $define ${QK::QK-base}
  14031. $define ${QK::QF-cust}
  14032. $define ${QK::QActive}
  14033. $define ${QK::QK-extern-C}</text>
  14034. </file>
  14035. </directory>
  14036. <!--${src::qxk}-->
  14037. <directory name="qxk">
  14038. <!--${src::qxk::qxk.c}-->
  14039. <file name="qxk.c">
  14040. <text>/*! @file
  14041. * @brief QXK preemptive dual-mode kernel core functions
  14042. */
  14043. #define QP_IMPL /* this is QP implementation */
  14044. #include &quot;qf_port.h&quot; /* QF port */
  14045. #include &quot;qf_pkg.h&quot; /* QF package-scope internal interface */
  14046. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14047. #ifdef Q_SPY /* QS software tracing enabled? */
  14048. #include &quot;qs_port.h&quot; /* QS port */
  14049. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14050. #else
  14051. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  14052. #endif /* Q_SPY */
  14053. /* protection against including this source file in a wrong project */
  14054. #ifndef QXK_H_
  14055. #error &quot;Source file included in a project NOT based on the QXK kernel&quot;
  14056. #endif /* QXK_H_ */
  14057. Q_DEFINE_THIS_MODULE(&quot;qxk&quot;)
  14058. /*==========================================================================*/
  14059. $define ${QXK::QXK-base}
  14060. $define ${QXK::QF-cust}
  14061. $define ${QXK::QActive}
  14062. $define ${QXK::QXK-extern-C}
  14063. /*==========================================================================*/
  14064. $define ${QXK-impl}</text>
  14065. </file>
  14066. <!--${src::qxk::qxk_mutex.c}-->
  14067. <file name="qxk_mutex.c">
  14068. <text>/*! @file
  14069. * @brief ::QXMutex class definition.
  14070. */
  14071. #define QP_IMPL /* this is QP implementation */
  14072. #include &quot;qf_port.h&quot; /* QF port */
  14073. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  14074. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14075. #ifdef Q_SPY /* QS software tracing enabled? */
  14076. #include &quot;qs_port.h&quot; /* QS port */
  14077. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14078. #else
  14079. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  14080. #endif /* Q_SPY */
  14081. /* protection against including this source file in a wrong project */
  14082. #ifndef QXK_H_
  14083. #error &quot;Source file included in a project NOT based on the QXK kernel&quot;
  14084. #endif /* QXK_H_ */
  14085. Q_DEFINE_THIS_MODULE(&quot;qxk_mutex&quot;)
  14086. /*==========================================================================*/
  14087. $define ${QXK::QXMutex}</text>
  14088. </file>
  14089. <!--${src::qxk::qxk_sema.c}-->
  14090. <file name="qxk_sema.c">
  14091. <text>/*! @file
  14092. * @brief ::QXSemaphore class definition.
  14093. */
  14094. #define QP_IMPL /* this is QP implementation */
  14095. #include &quot;qf_port.h&quot; /* QF port */
  14096. #include &quot;qf_pkg.h&quot; /* QF package-scope internal interface */
  14097. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14098. #ifdef Q_SPY /* QS software tracing enabled? */
  14099. #include &quot;qs_port.h&quot; /* QS port */
  14100. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14101. #else
  14102. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  14103. #endif /* Q_SPY */
  14104. /* protection against including this source file in a wrong project */
  14105. #ifndef QXK_H_
  14106. #error &quot;Source file included in a project NOT based on the QXK kernel&quot;
  14107. #endif /* QXK_H_ */
  14108. Q_DEFINE_THIS_MODULE(&quot;qxk_sema&quot;)
  14109. /*==========================================================================*/
  14110. $define ${QXK::QXSemaphore}</text>
  14111. </file>
  14112. <!--${src::qxk::qxk_xthr.c}-->
  14113. <file name="qxk_xthr.c">
  14114. <text>/*! @file
  14115. * @brief ::QXThread class definition.
  14116. */
  14117. #define QP_IMPL /* this is QP implementation */
  14118. #include &quot;qf_port.h&quot; /* QF port */
  14119. #include &quot;qf_pkg.h&quot; /* QF package-scope internal interface */
  14120. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14121. #ifdef Q_SPY /* QS software tracing enabled? */
  14122. #include &quot;qs_port.h&quot; /* QS port */
  14123. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14124. #else
  14125. #include &quot;qs_dummy.h&quot; /* disable the QS software tracing */
  14126. #endif /* Q_SPY */
  14127. /* protection against including this source file in a wrong project */
  14128. #ifndef QXK_H_
  14129. #error &quot;Source file included in a project NOT based on the QXK kernel&quot;
  14130. #endif /* QXK_H_ */
  14131. Q_DEFINE_THIS_MODULE(&quot;qxk_xthr&quot;)
  14132. /*==========================================================================*/
  14133. $define ${QXK::QXThread}</text>
  14134. </file>
  14135. </directory>
  14136. <!--${src::qs}-->
  14137. <directory name="qs">
  14138. <!--${src::qs::qs.c}-->
  14139. <file name="qs.c">
  14140. <text>/*! @file
  14141. * @brief QS software tracing services
  14142. */
  14143. #define QP_IMPL /* this is QP implementation */
  14144. #include &quot;qs_port.h&quot; /* QS port */
  14145. #include &quot;qs_pkg.h&quot; /* QS package-scope interface */
  14146. #include &quot;qstamp.h&quot; /* QP time-stamp */
  14147. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14148. Q_DEFINE_THIS_MODULE(&quot;qs&quot;)
  14149. /* ensure that the predefined records don't overlap the
  14150. * user records (application-specific).
  14151. */
  14152. Q_ASSERT_STATIC((enum_t)QS_PRE_MAX &lt;= (enum_t)QS_USER);
  14153. /*==========================================================================*/
  14154. $define ${QS::QS-tx}</text>
  14155. </file>
  14156. <!--${src::qs::qs_64bit.c}-->
  14157. <file name="qs_64bit.c">
  14158. <text>/*! @file
  14159. * @brief QS long-long (64-bit) output
  14160. */
  14161. #define QP_IMPL /* this is QP implementation */
  14162. #include &quot;qs_port.h&quot; /* QS port */
  14163. #include &quot;qs_pkg.h&quot; /* QS package-scope internal interface */
  14164. $define ${QS::QS-tx-64bit}</text>
  14165. </file>
  14166. <!--${src::qs::qs_fp.c}-->
  14167. <file name="qs_fp.c">
  14168. <text>/*! @file
  14169. * @brief QS floating point output implementation
  14170. */
  14171. #define QP_IMPL /* this is QP implementation */
  14172. #include &quot;qs_port.h&quot; /* QS port */
  14173. #include &quot;qs_pkg.h&quot; /* QS package-scope internal interface */
  14174. $define ${QS::QS-tx-fp}</text>
  14175. </file>
  14176. <!--${src::qs::qs_rx.c}-->
  14177. <file name="qs_rx.c">
  14178. <text>/*! @file
  14179. * @brief QS/C receive channel services
  14180. */
  14181. #define QP_IMPL /* this is QP implementation */
  14182. #include &quot;qs_port.h&quot; /* QS port */
  14183. #include &quot;qs_pkg.h&quot; /* QS package-scope interface */
  14184. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14185. Q_DEFINE_THIS_MODULE(&quot;qs_rx&quot;)
  14186. /*==========================================================================*/
  14187. #if (QS_OBJ_PTR_SIZE == 1U)
  14188. typedef uint8_t QSObj;
  14189. #elif (QS_OBJ_PTR_SIZE == 2U)
  14190. typedef uint16_t QSObj;
  14191. #elif (QS_OBJ_PTR_SIZE == 4U)
  14192. typedef uint32_t QSObj;
  14193. #elif (QS_OBJ_PTR_SIZE == 8U)
  14194. typedef uint64_t QSObj;
  14195. #endif
  14196. /*! @cond
  14197. * Exclude the following internals from the Doxygen documentation
  14198. * Extended-state variables used for parsing various QS-RX Records
  14199. */
  14200. typedef struct {
  14201. uint32_t param1;
  14202. uint32_t param2;
  14203. uint32_t param3;
  14204. uint8_t idx;
  14205. uint8_t cmdId;
  14206. } CmdVar;
  14207. typedef struct {
  14208. uint_fast8_t rate;
  14209. } TickVar;
  14210. typedef struct {
  14211. uint16_t offs;
  14212. uint8_t size;
  14213. uint8_t num;
  14214. uint8_t idx;
  14215. } PeekVar;
  14216. typedef struct {
  14217. uint32_t data;
  14218. uint16_t offs;
  14219. uint8_t size;
  14220. uint8_t num;
  14221. uint8_t idx;
  14222. uint8_t fill;
  14223. } PokeVar;
  14224. typedef struct {
  14225. uint8_t data[16];
  14226. uint8_t idx;
  14227. int8_t recId; /* global/local */
  14228. } FltVar;
  14229. typedef struct {
  14230. QSObj addr;
  14231. uint8_t idx;
  14232. uint8_t kind; /* see qs.h, enum QSpyObjKind */
  14233. int8_t recId;
  14234. } ObjVar;
  14235. typedef struct {
  14236. QEvt *e;
  14237. uint8_t *p;
  14238. QSignal sig;
  14239. uint16_t len;
  14240. uint8_t prio;
  14241. uint8_t idx;
  14242. } EvtVar;
  14243. /* extended-state variables for the current state */
  14244. static struct {
  14245. union Variant {
  14246. CmdVar cmd;
  14247. TickVar tick;
  14248. PeekVar peek;
  14249. PokeVar poke;
  14250. FltVar flt;
  14251. ObjVar obj;
  14252. EvtVar evt;
  14253. #ifdef Q_UTEST
  14254. struct QS_TProbe tp;
  14255. #endif /* Q_UTEST */
  14256. } var;
  14257. uint8_t state;
  14258. uint8_t esc;
  14259. uint8_t seq;
  14260. uint8_t chksum;
  14261. } l_rx;
  14262. enum {
  14263. ERROR_STATE,
  14264. WAIT4_SEQ,
  14265. WAIT4_REC,
  14266. WAIT4_INFO_FRAME,
  14267. WAIT4_CMD_ID,
  14268. WAIT4_CMD_PARAM1,
  14269. WAIT4_CMD_PARAM2,
  14270. WAIT4_CMD_PARAM3,
  14271. WAIT4_CMD_FRAME,
  14272. WAIT4_RESET_FRAME,
  14273. WAIT4_TICK_RATE,
  14274. WAIT4_TICK_FRAME,
  14275. WAIT4_PEEK_OFFS,
  14276. WAIT4_PEEK_SIZE,
  14277. WAIT4_PEEK_NUM,
  14278. WAIT4_PEEK_FRAME,
  14279. WAIT4_POKE_OFFS,
  14280. WAIT4_POKE_SIZE,
  14281. WAIT4_POKE_NUM,
  14282. WAIT4_POKE_DATA,
  14283. WAIT4_POKE_FRAME,
  14284. WAIT4_FILL_DATA,
  14285. WAIT4_FILL_FRAME,
  14286. WAIT4_FILTER_LEN,
  14287. WAIT4_FILTER_DATA,
  14288. WAIT4_FILTER_FRAME,
  14289. WAIT4_OBJ_KIND,
  14290. WAIT4_OBJ_ADDR,
  14291. WAIT4_OBJ_FRAME,
  14292. WAIT4_QUERY_KIND,
  14293. WAIT4_QUERY_FRAME,
  14294. WAIT4_EVT_PRIO,
  14295. WAIT4_EVT_SIG,
  14296. WAIT4_EVT_LEN,
  14297. WAIT4_EVT_PAR,
  14298. WAIT4_EVT_FRAME
  14299. #ifdef Q_UTEST
  14300. ,
  14301. WAIT4_TEST_SETUP_FRAME,
  14302. WAIT4_TEST_TEARDOWN_FRAME,
  14303. WAIT4_TEST_PROBE_DATA,
  14304. WAIT4_TEST_PROBE_ADDR,
  14305. WAIT4_TEST_PROBE_FRAME,
  14306. WAIT4_TEST_CONTINUE_FRAME
  14307. #endif /* Q_UTEST */
  14308. };
  14309. /* static helper functions... */
  14310. static void QS_rxParseData_(uint8_t const b);
  14311. //static void QS_rxHandleGoodFrame_(uint8_t const state);
  14312. static void QS_rxHandleBadFrame_(uint8_t const state);
  14313. static void QS_rxReportAck_(int8_t const recId);
  14314. static void QS_rxReportError_(int8_t const code);
  14315. static void QS_rxReportDone_(int8_t const recId);
  14316. static void QS_rxPoke_(void);
  14317. /*! Internal QS-RX macro to encapsulate transition in the QS-RX FSM */
  14318. #define QS_RX_TRAN_(target_) (l_rx.state = (uint8_t)(target_))
  14319. /*! @endcond */
  14320. /*==========================================================================*/
  14321. $define ${QS::QS-rx}
  14322. /*==========================================================================*/
  14323. static void QS_rxParseData_(uint8_t const b) {
  14324. switch (l_rx.state) {
  14325. case (uint8_t)WAIT4_SEQ: {
  14326. ++l_rx.seq;
  14327. if (l_rx.seq != b) {
  14328. QS_rxReportError_(0x42);
  14329. l_rx.seq = b; /* update the sequence */
  14330. }
  14331. QS_RX_TRAN_(WAIT4_REC);
  14332. break;
  14333. }
  14334. case (uint8_t)WAIT4_REC: {
  14335. switch (b) {
  14336. case (uint8_t)QS_RX_INFO:
  14337. QS_RX_TRAN_(WAIT4_INFO_FRAME);
  14338. break;
  14339. case (uint8_t)QS_RX_COMMAND:
  14340. QS_RX_TRAN_(WAIT4_CMD_ID);
  14341. break;
  14342. case (uint8_t)QS_RX_RESET:
  14343. QS_RX_TRAN_(WAIT4_RESET_FRAME);
  14344. break;
  14345. case (uint8_t)QS_RX_TICK:
  14346. QS_RX_TRAN_(WAIT4_TICK_RATE);
  14347. break;
  14348. case (uint8_t)QS_RX_PEEK:
  14349. if (QS_rxPriv_.currObj[AP_OBJ] != (void *)0) {
  14350. l_rx.var.peek.offs = 0U;
  14351. l_rx.var.peek.idx = 0U;
  14352. QS_RX_TRAN_(WAIT4_PEEK_OFFS);
  14353. }
  14354. else {
  14355. QS_rxReportError_((int8_t)QS_RX_PEEK);
  14356. QS_RX_TRAN_(ERROR_STATE);
  14357. }
  14358. break;
  14359. case (uint8_t)QS_RX_POKE: /* intentionally fall-through */
  14360. case (uint8_t)QS_RX_FILL:
  14361. l_rx.var.poke.fill =
  14362. ((b == (uint8_t)QS_RX_FILL) ? 1U : 0U);
  14363. if (QS_rxPriv_.currObj[AP_OBJ] != (void *)0) {
  14364. l_rx.var.poke.offs = 0U;
  14365. l_rx.var.poke.idx = 0U;
  14366. QS_RX_TRAN_(WAIT4_POKE_OFFS);
  14367. }
  14368. else {
  14369. QS_rxReportError_((l_rx.var.poke.fill != 0U)
  14370. ? (int8_t)QS_RX_FILL
  14371. : (int8_t)QS_RX_POKE);
  14372. QS_RX_TRAN_(ERROR_STATE);
  14373. }
  14374. break;
  14375. case (uint8_t)QS_RX_GLB_FILTER: /* intentionally fall-through */
  14376. case (uint8_t)QS_RX_LOC_FILTER:
  14377. l_rx.var.flt.recId = (int8_t)b;
  14378. QS_RX_TRAN_(WAIT4_FILTER_LEN);
  14379. break;
  14380. case (uint8_t)QS_RX_AO_FILTER: /* intentionally fall-through */
  14381. case (uint8_t)QS_RX_CURR_OBJ:
  14382. l_rx.var.obj.recId = (int8_t)b;
  14383. QS_RX_TRAN_(WAIT4_OBJ_KIND);
  14384. break;
  14385. case (uint8_t)QS_RX_QUERY_CURR:
  14386. l_rx.var.obj.recId = (int8_t)QS_RX_QUERY_CURR;
  14387. QS_RX_TRAN_(WAIT4_QUERY_KIND);
  14388. break;
  14389. case (uint8_t)QS_RX_EVENT:
  14390. QS_RX_TRAN_(WAIT4_EVT_PRIO);
  14391. break;
  14392. #ifdef Q_UTEST
  14393. case (uint8_t)QS_RX_TEST_SETUP:
  14394. QS_RX_TRAN_(WAIT4_TEST_SETUP_FRAME);
  14395. break;
  14396. case (uint8_t)QS_RX_TEST_TEARDOWN:
  14397. QS_RX_TRAN_(WAIT4_TEST_TEARDOWN_FRAME);
  14398. break;
  14399. case (uint8_t)QS_RX_TEST_CONTINUE:
  14400. QS_RX_TRAN_(WAIT4_TEST_CONTINUE_FRAME);
  14401. break;
  14402. case (uint8_t)QS_RX_TEST_PROBE:
  14403. if (QS_testData.tpNum
  14404. &lt; (uint8_t)(sizeof(QS_testData.tpBuf)
  14405. / sizeof(QS_testData.tpBuf[0])))
  14406. {
  14407. l_rx.var.tp.data = 0U;
  14408. l_rx.var.tp.idx = 0U;
  14409. QS_RX_TRAN_(WAIT4_TEST_PROBE_DATA);
  14410. }
  14411. else { /* the number of Test-Probes exceeded */
  14412. QS_rxReportError_((int8_t)QS_RX_TEST_PROBE);
  14413. QS_RX_TRAN_(ERROR_STATE);
  14414. }
  14415. break;
  14416. #endif /* Q_UTEST */
  14417. default:
  14418. QS_rxReportError_(0x43);
  14419. QS_RX_TRAN_(ERROR_STATE);
  14420. break;
  14421. }
  14422. break;
  14423. }
  14424. case (uint8_t)WAIT4_INFO_FRAME: {
  14425. /* keep ignoring the data until a frame is collected */
  14426. break;
  14427. }
  14428. case (uint8_t)WAIT4_CMD_ID: {
  14429. l_rx.var.cmd.cmdId = b;
  14430. l_rx.var.cmd.idx = 0U;
  14431. l_rx.var.cmd.param1 = 0U;
  14432. l_rx.var.cmd.param2 = 0U;
  14433. l_rx.var.cmd.param3 = 0U;
  14434. QS_RX_TRAN_(WAIT4_CMD_PARAM1);
  14435. break;
  14436. }
  14437. case (uint8_t)WAIT4_CMD_PARAM1: {
  14438. l_rx.var.cmd.param1 |= ((uint32_t)b &lt;&lt; l_rx.var.cmd.idx);
  14439. l_rx.var.cmd.idx += 8U;
  14440. if (l_rx.var.cmd.idx == (8U * 4U)) {
  14441. l_rx.var.cmd.idx = 0U;
  14442. QS_RX_TRAN_(WAIT4_CMD_PARAM2);
  14443. }
  14444. break;
  14445. }
  14446. case (uint8_t)WAIT4_CMD_PARAM2: {
  14447. l_rx.var.cmd.param2 |= ((uint32_t)b &lt;&lt; l_rx.var.cmd.idx);
  14448. l_rx.var.cmd.idx += 8U;
  14449. if (l_rx.var.cmd.idx == (8U * 4U)) {
  14450. l_rx.var.cmd.idx = 0U;
  14451. QS_RX_TRAN_(WAIT4_CMD_PARAM3);
  14452. }
  14453. break;
  14454. }
  14455. case (uint8_t)WAIT4_CMD_PARAM3: {
  14456. l_rx.var.cmd.param3 |= ((uint32_t)b &lt;&lt; l_rx.var.cmd.idx);
  14457. l_rx.var.cmd.idx += 8U;
  14458. if (l_rx.var.cmd.idx == (8U * 4U)) {
  14459. l_rx.var.cmd.idx = 0U;
  14460. QS_RX_TRAN_(WAIT4_CMD_FRAME);
  14461. }
  14462. break;
  14463. }
  14464. case (uint8_t)WAIT4_CMD_FRAME: {
  14465. /* keep ignoring the data until a frame is collected */
  14466. break;
  14467. }
  14468. case (uint8_t)WAIT4_RESET_FRAME: {
  14469. /* keep ignoring the data until a frame is collected */
  14470. break;
  14471. }
  14472. case (uint8_t)WAIT4_TICK_RATE: {
  14473. l_rx.var.tick.rate = (uint_fast8_t)b;
  14474. QS_RX_TRAN_(WAIT4_TICK_FRAME);
  14475. break;
  14476. }
  14477. case (uint8_t)WAIT4_TICK_FRAME: {
  14478. /* keep ignoring the data until a frame is collected */
  14479. break;
  14480. }
  14481. case (uint8_t)WAIT4_PEEK_OFFS: {
  14482. if (l_rx.var.peek.idx == 0U) {
  14483. l_rx.var.peek.offs = (uint16_t)b;
  14484. l_rx.var.peek.idx += 8U;
  14485. }
  14486. else {
  14487. l_rx.var.peek.offs |= (uint16_t)((uint16_t)b &lt;&lt; 8U);
  14488. QS_RX_TRAN_(WAIT4_PEEK_SIZE);
  14489. }
  14490. break;
  14491. }
  14492. case (uint8_t)WAIT4_PEEK_SIZE: {
  14493. if ((b == 1U) || (b == 2U) || (b == 4U)) {
  14494. l_rx.var.peek.size = b;
  14495. QS_RX_TRAN_(WAIT4_PEEK_NUM);
  14496. }
  14497. else {
  14498. QS_rxReportError_((int8_t)QS_RX_PEEK);
  14499. QS_RX_TRAN_(ERROR_STATE);
  14500. }
  14501. break;
  14502. }
  14503. case (uint8_t)WAIT4_PEEK_NUM: {
  14504. l_rx.var.peek.num = b;
  14505. QS_RX_TRAN_(WAIT4_PEEK_FRAME);
  14506. break;
  14507. }
  14508. case (uint8_t)WAIT4_PEEK_FRAME: {
  14509. /* keep ignoring the data until a frame is collected */
  14510. break;
  14511. }
  14512. case (uint8_t)WAIT4_POKE_OFFS: {
  14513. if (l_rx.var.poke.idx == 0U) {
  14514. l_rx.var.poke.offs = (uint16_t)b;
  14515. l_rx.var.poke.idx = 1U;
  14516. }
  14517. else {
  14518. l_rx.var.poke.offs |= (uint16_t)((uint16_t)b &lt;&lt; 8U);
  14519. QS_RX_TRAN_(WAIT4_POKE_SIZE);
  14520. }
  14521. break;
  14522. }
  14523. case (uint8_t)WAIT4_POKE_SIZE: {
  14524. if ((b == 1U) || (b == 2U) || (b == 4U)) {
  14525. l_rx.var.poke.size = b;
  14526. QS_RX_TRAN_(WAIT4_POKE_NUM);
  14527. }
  14528. else {
  14529. QS_rxReportError_((l_rx.var.poke.fill != 0U)
  14530. ? (int8_t)QS_RX_FILL
  14531. : (int8_t)QS_RX_POKE);
  14532. QS_RX_TRAN_(ERROR_STATE);
  14533. }
  14534. break;
  14535. }
  14536. case (uint8_t)WAIT4_POKE_NUM: {
  14537. if (b &gt; 0U) {
  14538. l_rx.var.poke.num = b;
  14539. l_rx.var.poke.data = 0U;
  14540. l_rx.var.poke.idx = 0U;
  14541. QS_RX_TRAN_((l_rx.var.poke.fill != 0U)
  14542. ? WAIT4_FILL_DATA
  14543. : WAIT4_POKE_DATA);
  14544. }
  14545. else {
  14546. QS_rxReportError_((l_rx.var.poke.fill != 0U)
  14547. ? (int8_t)QS_RX_FILL
  14548. : (int8_t)QS_RX_POKE);
  14549. QS_RX_TRAN_(ERROR_STATE);
  14550. }
  14551. break;
  14552. }
  14553. case (uint8_t)WAIT4_FILL_DATA: {
  14554. l_rx.var.poke.data |= ((uint32_t)b &lt;&lt; l_rx.var.poke.idx);
  14555. l_rx.var.poke.idx += 8U;
  14556. if ((uint8_t)(l_rx.var.poke.idx &gt;&gt; 3U) == l_rx.var.poke.size) {
  14557. QS_RX_TRAN_(WAIT4_FILL_FRAME);
  14558. }
  14559. break;
  14560. }
  14561. case (uint8_t)WAIT4_POKE_DATA: {
  14562. l_rx.var.poke.data |= ((uint32_t)b &lt;&lt; l_rx.var.poke.idx);
  14563. l_rx.var.poke.idx += 8U;
  14564. if ((uint8_t)(l_rx.var.poke.idx &gt;&gt; 3U) == l_rx.var.poke.size) {
  14565. QS_rxPoke_();
  14566. --l_rx.var.poke.num;
  14567. if (l_rx.var.poke.num == 0U) {
  14568. QS_RX_TRAN_(WAIT4_POKE_FRAME);
  14569. }
  14570. }
  14571. break;
  14572. }
  14573. case (uint8_t)WAIT4_FILL_FRAME: {
  14574. /* keep ignoring the data until a frame is collected */
  14575. break;
  14576. }
  14577. case WAIT4_POKE_FRAME: {
  14578. /* keep ignoring the data until a frame is collected */
  14579. break;
  14580. }
  14581. case (uint8_t)WAIT4_FILTER_LEN: {
  14582. if (b == sizeof(l_rx.var.flt.data)) {
  14583. l_rx.var.flt.idx = 0U;
  14584. QS_RX_TRAN_(WAIT4_FILTER_DATA);
  14585. }
  14586. else {
  14587. QS_rxReportError_(l_rx.var.flt.recId);
  14588. QS_RX_TRAN_(ERROR_STATE);
  14589. }
  14590. break;
  14591. }
  14592. case (uint8_t)WAIT4_FILTER_DATA: {
  14593. l_rx.var.flt.data[l_rx.var.flt.idx] = b;
  14594. ++l_rx.var.flt.idx;
  14595. if (l_rx.var.flt.idx == sizeof(l_rx.var.flt.data)) {
  14596. QS_RX_TRAN_(WAIT4_FILTER_FRAME);
  14597. }
  14598. break;
  14599. }
  14600. case (uint8_t)WAIT4_FILTER_FRAME: {
  14601. /* keep ignoring the data until a frame is collected */
  14602. break;
  14603. }
  14604. case (uint8_t)WAIT4_OBJ_KIND: {
  14605. if (b &lt;= (uint8_t)SM_AO_OBJ) {
  14606. l_rx.var.obj.kind = b;
  14607. l_rx.var.obj.addr = 0U;
  14608. l_rx.var.obj.idx = 0U;
  14609. QS_RX_TRAN_(WAIT4_OBJ_ADDR);
  14610. }
  14611. else {
  14612. QS_rxReportError_(l_rx.var.obj.recId);
  14613. QS_RX_TRAN_(ERROR_STATE);
  14614. }
  14615. break;
  14616. }
  14617. case (uint8_t)WAIT4_OBJ_ADDR: {
  14618. l_rx.var.obj.addr |= ((QSObj)b &lt;&lt; l_rx.var.obj.idx);
  14619. l_rx.var.obj.idx += 8U;
  14620. if (l_rx.var.obj.idx == (uint8_t)(8U * QS_OBJ_PTR_SIZE)) {
  14621. QS_RX_TRAN_(WAIT4_OBJ_FRAME);
  14622. }
  14623. break;
  14624. }
  14625. case (uint8_t)WAIT4_OBJ_FRAME: {
  14626. /* keep ignoring the data until a frame is collected */
  14627. break;
  14628. }
  14629. case (uint8_t)WAIT4_QUERY_KIND: {
  14630. if (b &lt; (uint8_t)MAX_OBJ) {
  14631. l_rx.var.obj.kind = b;
  14632. QS_RX_TRAN_(WAIT4_QUERY_FRAME);
  14633. }
  14634. else {
  14635. QS_rxReportError_(l_rx.var.obj.recId);
  14636. QS_RX_TRAN_(ERROR_STATE);
  14637. }
  14638. break;
  14639. }
  14640. case (uint8_t)WAIT4_QUERY_FRAME: {
  14641. /* keep ignoring the data until a frame is collected */
  14642. break;
  14643. }
  14644. case (uint8_t)WAIT4_EVT_PRIO: {
  14645. l_rx.var.evt.prio = b;
  14646. l_rx.var.evt.sig = 0U;
  14647. l_rx.var.evt.idx = 0U;
  14648. QS_RX_TRAN_(WAIT4_EVT_SIG);
  14649. break;
  14650. }
  14651. case (uint8_t)WAIT4_EVT_SIG: {
  14652. l_rx.var.evt.sig |= (QSignal)((uint32_t)b &lt;&lt; l_rx.var.evt.idx);
  14653. l_rx.var.evt.idx += 8U;
  14654. if (l_rx.var.evt.idx == (uint8_t)(8U * Q_SIGNAL_SIZE)) {
  14655. l_rx.var.evt.len = 0U;
  14656. l_rx.var.evt.idx = 0U;
  14657. QS_RX_TRAN_(WAIT4_EVT_LEN);
  14658. }
  14659. break;
  14660. }
  14661. case (uint8_t)WAIT4_EVT_LEN: {
  14662. l_rx.var.evt.len |= (uint16_t)((uint32_t)b &lt;&lt; l_rx.var.evt.idx);
  14663. l_rx.var.evt.idx += 8U;
  14664. if (l_rx.var.evt.idx == (8U * 2U)) {
  14665. if ((l_rx.var.evt.len + sizeof(QEvt)) &lt;=
  14666. QF_poolGetMaxBlockSize())
  14667. {
  14668. /* report Ack before generating any other QS records */
  14669. QS_rxReportAck_((int8_t)QS_RX_EVENT);
  14670. l_rx.var.evt.e = QF_newX_(
  14671. ((uint_fast16_t)l_rx.var.evt.len + sizeof(QEvt)),
  14672. 0U, /* margin */
  14673. (enum_t)l_rx.var.evt.sig);
  14674. if (l_rx.var.evt.e != (QEvt *)0) { /* evt allocated? */
  14675. l_rx.var.evt.p = (uint8_t *)l_rx.var.evt.e;
  14676. l_rx.var.evt.p = &amp;l_rx.var.evt.p[sizeof(QEvt)];
  14677. if (l_rx.var.evt.len &gt; 0U) {
  14678. QS_RX_TRAN_(WAIT4_EVT_PAR);
  14679. }
  14680. else {
  14681. QS_RX_TRAN_(WAIT4_EVT_FRAME);
  14682. }
  14683. }
  14684. else {
  14685. QS_rxReportError_((int8_t)QS_RX_EVENT);
  14686. QS_RX_TRAN_(ERROR_STATE);
  14687. }
  14688. }
  14689. else {
  14690. QS_rxReportError_((int8_t)QS_RX_EVENT);
  14691. QS_RX_TRAN_(ERROR_STATE);
  14692. }
  14693. }
  14694. break;
  14695. }
  14696. case (uint8_t)WAIT4_EVT_PAR: { /* event parameters */
  14697. *l_rx.var.evt.p = b;
  14698. ++l_rx.var.evt.p;
  14699. --l_rx.var.evt.len;
  14700. if (l_rx.var.evt.len == 0U) {
  14701. QS_RX_TRAN_(WAIT4_EVT_FRAME);
  14702. }
  14703. break;
  14704. }
  14705. case (uint8_t)WAIT4_EVT_FRAME: {
  14706. /* keep ignoring the data until a frame is collected */
  14707. break;
  14708. }
  14709. #ifdef Q_UTEST
  14710. case (uint8_t)WAIT4_TEST_SETUP_FRAME: {
  14711. /* keep ignoring the data until a frame is collected */
  14712. break;
  14713. }
  14714. case (uint8_t)WAIT4_TEST_TEARDOWN_FRAME: {
  14715. /* keep ignoring the data until a frame is collected */
  14716. break;
  14717. }
  14718. case (uint8_t)WAIT4_TEST_CONTINUE_FRAME: {
  14719. /* keep ignoring the data until a frame is collected */
  14720. break;
  14721. }
  14722. case (uint8_t)WAIT4_TEST_PROBE_DATA: {
  14723. l_rx.var.tp.data |= ((uint32_t)b &lt;&lt; l_rx.var.tp.idx);
  14724. l_rx.var.tp.idx += 8U;
  14725. if (l_rx.var.tp.idx == (uint8_t)(8U * sizeof(uint32_t))) {
  14726. l_rx.var.tp.addr = 0U;
  14727. l_rx.var.tp.idx = 0U;
  14728. QS_RX_TRAN_(WAIT4_TEST_PROBE_ADDR);
  14729. }
  14730. break;
  14731. }
  14732. case (uint8_t)WAIT4_TEST_PROBE_ADDR: {
  14733. l_rx.var.tp.addr |= ((QSFun)b &lt;&lt; l_rx.var.tp.idx);
  14734. l_rx.var.tp.idx += 8U;
  14735. if (l_rx.var.tp.idx == (uint8_t)(8U * QS_FUN_PTR_SIZE)) {
  14736. QS_RX_TRAN_(WAIT4_TEST_PROBE_FRAME);
  14737. }
  14738. break;
  14739. }
  14740. case (uint8_t)WAIT4_TEST_PROBE_FRAME: {
  14741. /* keep ignoring the data until a frame is collected */
  14742. break;
  14743. }
  14744. #endif /* Q_UTEST */
  14745. case (uint8_t)ERROR_STATE: {
  14746. /* keep ignoring the data until a good frame is collected */
  14747. break;
  14748. }
  14749. default: { /* unexpected or unimplemented state */
  14750. QS_rxReportError_(0x45);
  14751. QS_RX_TRAN_(ERROR_STATE);
  14752. break;
  14753. }
  14754. }
  14755. }
  14756. /*..........................................................................*/
  14757. static void QS_rxHandleBadFrame_(uint8_t const state) {
  14758. QS_rxReportError_(0x50); /* report error for all bad frames */
  14759. switch (state) {
  14760. case WAIT4_EVT_FRAME: {
  14761. Q_ASSERT_ID(910, l_rx.var.evt.e != (QEvt *)0);
  14762. #if (QF_MAX_EPOOL &gt; 0U)
  14763. QF_gc(l_rx.var.evt.e); /* don't leak an allocated event */
  14764. #endif
  14765. break;
  14766. }
  14767. default: {
  14768. /* intentionally empty */
  14769. break;
  14770. }
  14771. }
  14772. }
  14773. /*..........................................................................*/
  14774. static void QS_rxReportAck_(int8_t const recId) {
  14775. QS_CRIT_STAT_
  14776. QS_CRIT_E_();
  14777. QS_beginRec_((uint_fast8_t)QS_RX_STATUS);
  14778. QS_U8_PRE_(recId); /* record ID */
  14779. QS_endRec_();
  14780. QS_CRIT_X_();
  14781. QS_REC_DONE(); /* user callback (if defined) */
  14782. }
  14783. /*..........................................................................*/
  14784. static void QS_rxReportError_(int8_t const code) {
  14785. QS_CRIT_STAT_
  14786. QS_CRIT_E_();
  14787. QS_beginRec_((uint_fast8_t)QS_RX_STATUS);
  14788. QS_U8_PRE_(0x80U | (uint8_t)code); /* error code */
  14789. QS_endRec_();
  14790. QS_CRIT_X_();
  14791. QS_REC_DONE(); /* user callback (if defined) */
  14792. }
  14793. /*..........................................................................*/
  14794. static void QS_rxReportDone_(int8_t const recId) {
  14795. QS_CRIT_STAT_
  14796. QS_CRIT_E_();
  14797. QS_beginRec_((uint_fast8_t)QS_TARGET_DONE);
  14798. QS_TIME_PRE_(); /* timestamp */
  14799. QS_U8_PRE_(recId); /* record ID */
  14800. QS_endRec_();
  14801. QS_CRIT_X_();
  14802. QS_REC_DONE(); /* user callback (if defined) */
  14803. }
  14804. /*..........................................................................*/
  14805. static void QS_rxPoke_(void) {
  14806. uint8_t *ptr = (uint8_t *)QS_rxPriv_.currObj[AP_OBJ];
  14807. ptr = &amp;ptr[l_rx.var.poke.offs];
  14808. switch (l_rx.var.poke.size) {
  14809. case 1:
  14810. *ptr = (uint8_t)l_rx.var.poke.data;
  14811. break;
  14812. case 2:
  14813. *(uint16_t *)ptr = (uint16_t)l_rx.var.poke.data;
  14814. break;
  14815. case 4:
  14816. *(uint32_t *)ptr = l_rx.var.poke.data;
  14817. break;
  14818. default:
  14819. Q_ERROR_ID(900);
  14820. break;
  14821. }
  14822. l_rx.var.poke.data = 0U;
  14823. l_rx.var.poke.idx = 0U;
  14824. l_rx.var.poke.offs += (uint16_t)l_rx.var.poke.size;
  14825. }</text>
  14826. </file>
  14827. <!--${src::qs::qutest.c}-->
  14828. <file name="qutest.c">
  14829. <text>/*! @file
  14830. * @brief QUTest unit testing harness
  14831. */
  14832. /* Include this content in the build only when Q_UTEST is defined */
  14833. #ifdef Q_UTEST
  14834. #define QP_IMPL /* this is QP implementation */
  14835. #include &quot;qf_port.h&quot; /* QF port */
  14836. #include &quot;qf_pkg.h&quot; /* QF package-scope interface */
  14837. #include &quot;qassert.h&quot; /* QP embedded systems-friendly assertions */
  14838. #include &quot;qs_port.h&quot; /* include QS port */
  14839. #include &quot;qs_pkg.h&quot; /* QS facilities for pre-defined trace records */
  14840. /*==========================================================================*/
  14841. /* QUTest unit testing harness */
  14842. $define ${QUTest}
  14843. /*..........................................................................*/
  14844. Q_NORETURN Q_onAssert(
  14845. char const * module,
  14846. int_t location)
  14847. {
  14848. QS_BEGIN_NOCRIT_PRE_(QS_ASSERT_FAIL, 0U)
  14849. QS_TIME_PRE_();
  14850. QS_U16_PRE_(location);
  14851. QS_STR_PRE_((module != (char *)0) ? module : &quot;?&quot;);
  14852. QS_END_NOCRIT_PRE_()
  14853. QS_onFlush(); /* flush the assertion record to the host */
  14854. QS_onCleanup(); /* cleanup after the failure */
  14855. QS_onReset(); /* reset the target to prevent the code from continuing */
  14856. for (;;) { /* QS_onReset() should not return, but to ensure no-return */
  14857. }
  14858. }
  14859. /*..........................................................................*/
  14860. QSTimeCtr QS_onGetTime(void) {
  14861. return (++QS_testData.testTime);
  14862. }
  14863. /*==========================================================================*/
  14864. /* QP-stub for QUTest
  14865. * NOTE: The QP-stub is needed for unit testing QP applications, but might
  14866. * NOT be needed for testing QP itself. In that case, the build process
  14867. * can define Q_UTEST=0 to exclude the QP-stub from the build.
  14868. */
  14869. #if Q_UTEST != 0
  14870. Q_DEFINE_THIS_MODULE(&quot;qutest&quot;)
  14871. $define ${QUTest-stub}
  14872. #endif /* Q_UTEST != 0 */
  14873. #endif /* Q_UTEST */</text>
  14874. </file>
  14875. <!--${src::qs::qstamp.c}-->
  14876. <file name="qstamp.c">
  14877. <text>/*! @file
  14878. * @brief Application build time-stamp
  14879. * @details
  14880. * This module needs to be re-compiled in every new software build. To achive
  14881. * this, it is recommended to delete the object file (qstamp.o, or qstamp.obj)
  14882. * in the build directory before each build. (Most development tools allow
  14883. * you to specify a pre-build command, which is the ideal place to delete
  14884. * the qstamp object file.)
  14885. */
  14886. #include &quot;qstamp.h&quot;
  14887. /*! the calendar date of the last translation of the form: &quot;Mmm dd yyyy&quot; */
  14888. char const Q_BUILD_DATE[12] = __DATE__;
  14889. /*! the time of the last translation of the form: &quot;hh:mm:ss&quot; */
  14890. char const Q_BUILD_TIME[9] = __TIME__;</text>
  14891. </file>
  14892. </directory>
  14893. </directory>
  14894. </model>