123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700 |
- /* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
- * All rights reserved.
- *
- * This software is supplied "AS IS" without any warranties.
- * RDA assumes no responsibility or liability for the use of the software,
- * conveys no license or title under any patent, copyright, or mask work
- * right to the product. RDA reserves the right to make changes in the
- * software without notification. RDA also make no representation or
- * warranty that such application will be suitable for the specified use
- * without further testing or modification.
- */
- #ifndef _OSI_API_H_
- #define _OSI_API_H_
- #include <stdint.h>
- #include <stdbool.h>
- #include <stddef.h>
- #ifndef _MSC_VER
- #include "kernel_config.h"
- #endif
- #include "osi_compiler.h"
- #include "osi_vsmap.h"
- #include "osi_clock.h"
- #include "quec_proj_config.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- #define OSI_WAIT_FOREVER (-1U)
- #define OSI_DELAY_MAX (-1U)
- /**
- * Special value to indicate timer callback will be invoked in
- * timer ISR.
- */
- #define OSI_TIMER_IN_ISR ((osiThread_t *)NULL)
- /**
- * Special value to indicate timer callback will be invoked in
- * timer service thread.
- */
- #define OSI_TIMER_IN_SERVICE ((osiThread_t *)0xffffffff)
- /**
- * reserved event id to indicate nop
- */
- #define OSI_EVENT_ID_NONE (0)
- /**
- * reserved event id to indicate quit event loop
- */
- #define OSI_EVENT_ID_QUIT (8)
- /**
- * elapsed timer for counting elapsed time
- */
- typedef uint32_t osiElapsedTimer_t;
- /**
- * opaque data structure for timer
- */
- typedef struct osiTimer osiTimer_t;
- /**
- * opaque data structure for timer pool
- */
- typedef struct osiTimerPool osiTimerPool_t;
- /**
- * opaque data structure for thread
- */
- typedef struct osiThread osiThread_t;
- /**
- * opaque data structure for message queue
- */
- typedef struct osiMessageQueue osiMessageQueue_t;
- /**
- * opaque data structure for event queue
- *
- * Event queue is just a message queue, and the message is \p osiEvent_t
- * (event itself rather than pointer).
- */
- typedef struct osiEventQueue osiEventQueue_t;
- /**
- * opaque data structure for mutex
- */
- typedef struct osiMutex osiMutex_t;
- /**
- * opaque data structure for semaphore
- */
- typedef struct osiSemaphore osiSemaphore_t;
- /**
- * opaque data structure for work
- */
- typedef struct osiWork osiWork_t;
- /**
- * opaque data structure for work queue
- */
- typedef struct osiWorkQueue osiWorkQueue_t;
- /**
- * opaque data structure for thread notify
- */
- typedef struct osiNotify osiNotify_t;
- /**
- * function type of callback
- */
- typedef void (*osiCallback_t)(void *ctx);
- /**
- * function type of thread entry
- */
- typedef void (*osiThreadEntry_t)(void *argument);
- /**
- * function type of interrupt handler
- */
- typedef void (*osiIrqHandler_t)(void *ctx);
- /**
- * event, with ID and 3 parameters
- */
- typedef struct osiEvent
- {
- uint32_t id; ///< event identifier
- uint32_t param1; ///< 1st parameter
- uint32_t param2; ///< 2nd parameter
- uint32_t param3; ///< 3rd parameter
- } osiEvent_t;
- /**
- * thread priority
- *
- * The definition is independent of implementation. Though some
- * implementation will use larger value for higher priority and
- * others will use smaller value for highe priority, this enum will
- * use larger value for higher priority.
- *
- * \p OSI_PRIORITY_IDLE and \p OSI_PRIORITY_HISR are reserved, can't
- * be used.
- *
- * The definition is the same as CMSIS-RTOS.
- */
- typedef enum
- {
- OSI_PRIORITY_IDLE = 1, // reserved
- OSI_PRIORITY_LOW = 8,
- OSI_PRIORITY_BELOW_NORMAL = 16,
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- OSI_PRIORITY_NORMAL_LOWER = 23,
- #endif
- OSI_PRIORITY_NORMAL = 24,
- OSI_PRIORITY_ABOVE_NORMAL = 32,
- OSI_PRIORITY_HIGH = 40,
- OSI_PRIORITY_REALTIME = 48,
- OSI_PRIORITY_HISR = 56, // reserved
- } osiThreadPriority_t;
- /**
- * suspend mode
- *
- * System behavior of suspend modes will be diffrent among underlay
- * platform. Driver shall take care the difference, and most likely
- * application won't take care it.
- */
- typedef enum osiSuspendMode
- {
- OSI_SUSPEND_PM0, ///< light sleep
- OSI_SUSPEND_PM1, ///< 1st level suspend mode
- OSI_SUSPEND_PM2 ///< 2nd level suspend mode
- } osiSuspendMode_t;
- /**
- * resume wakeup source
- *
- * Resume wakeup source depends on platform. They should be defined in
- * \p hal_chip.h. One bit indicates one source, and multiple sources are
- * possible. \p OSI_RESUME_ABORT is reserved to indicate suspend is
- * aborted.
- */
- typedef enum osiResumeSource
- {
- OSI_RESUME_ABORT = (1 << 31), ///< resume by suspend aborted
- } osiResumeSource_t;
- /**
- * \brief boot cause
- *
- * This list is for cold boot cause. Though it is rare, it is possible
- * there exist multiple boot causes simultanuously.
- *
- * Usually boot cause is determined from hardware status registers.
- */
- typedef enum osiBootCause
- {
- OSI_BOOTCAUSE_UNKNOWN = 0, ///< placeholder for unknown reason
- OSI_BOOTCAUSE_PWRKEY = (1 << 0), ///< boot by power key
- OSI_BOOTCAUSE_PIN_RESET = (1 << 1), ///< boot by pin reset
- OSI_BOOTCAUSE_ALARM = (1 << 2), ///< boot by alarm
- OSI_BOOTCAUSE_CHARGE = (1 << 3), ///< boot by charge in
- OSI_BOOTCAUSE_WDG = (1 << 4), ///< boot by watchdog
- OSI_BOOTCAUSE_PIN_WAKEUP = (1 << 5), ///< boot by gpio wakeup
- OSI_BOOTCAUSE_SMPL_WAKEUP = (1 << 6), ///< boot from SMPL
- OSI_BOOTCAUSE_GPT_WAKEUP = (1 << 7), ///< boot from GPT
- OSI_BOOTCAUSE_WDG_IN_PSM = (1 << 8), ///< boot by watchdog rst
- OSI_BOOTCAUSE_PANIC = (1 << 9), ///< boot by panic reset
- OSI_BOOTCAUSE_PM2BOOT = (1 << 10), ///< boot from PM2 cold boot
- } osiBootCause_t;
- /**
- * boot mode
- *
- * Besides normal boot, there are several other boot modes. For each
- * platform, not all boot modes are supported.
- *
- * Usually, boot mode can be determined by hardware (for example, some
- * GPIO) or software (for example, by flags written at \p osiShutdown).
- */
- typedef enum osiBootMode
- {
- OSI_BOOTMODE_NORMAL = 0, ///< normal boot
- OSI_BOOTMODE_DOWNLOAD = 0x444e, ///< 'DN' boot to download mode
- OSI_BOOTMODE_CALIB = 0x434c, ///< 'CL' boot to calibration mode
- OSI_BOOTMODE_CALIB_POST = 0x4350, ///< 'CP' boot to calibration post mode
- OSI_BOOTMODE_NB_CALIB = 0x4e43, ///< 'NC' boot to NB calibration mode
- OSI_BOOTMODE_BBAT = 0x4241, ///< 'BA' boot to BBAT mode
- OSI_BOOTMODE_UPGRADE = 0x4654, ///< 'FT' boot to bootloader upgrade
- OSI_BOOTMODE_PSM_RESTORE = 0x5053, ///< 'PS' boot to PSM restore
- OSI_SHUTDOWN_OPENCPU_PM2_RESTORE = 0x6045, ///< 'OPM' boot to opencpu PSM restore
- OSI_BOOTMODE_OPENCPU_PSM_RESTORE = 0x6056, ///< 'OPS' boot to opencpu PSM restore
- } osiBootMode_t;
- /**
- * shudown mode
- *
- * For each platform, not all shutdown modes are supported.
- *
- * \p OSI_SHUTDOWN_PANIC is a special case. Though it is a *shutdown mode*,
- * it will appear as \p OSI_BOOTCAUSE_PANIC after reset.
- *
- * \p OSI_SHUTDOWN_PSM_PM2BOOT is a special case. The bootmode will be
- * \p OSI_BOOTMODE_PSM_RESTORE and there is cause \p OSI_BOOTCAUSE_PM2BOOT.
- */
- typedef enum osiShutdownMode
- {
- OSI_SHUTDOWN_RESET = 0, ///< normal reset
- OSI_SHUTDOWN_FORCE_DOWNLOAD = 0x5244, ///< 'RD' reset to force download mode
- OSI_SHUTDOWN_DOWNLOAD = 0x444e, ///< 'DN' reset to download mode
- OSI_SHUTDOWN_BL_DOWNLOAD = 0x4244, ///< 'BD' reset to bootloader download mode
- OSI_SHUTDOWN_CALIB_MODE = 0x434c, ///< 'CL' reset to calibration mode
- OSI_SHUTDOWN_NB_CALIB_MODE = 0x4e43, ///< 'NC' reset to NB calibration mode
- OSI_SHUTDOWN_BBAT_MODE = 0x4241, ///< 'BA' reset to BBAT mode
- OSI_SHUTDOWN_UPGRADE = 0x4654, ///< 'FT' reset to upgrade mode
- OSI_SHUTDOWN_POWER_OFF = 0x4f46, ///< 'OF' power off
- OSI_SHUTDOWN_PSM_SLEEP = 0x5053, ///< 'PS' power saving mode
- OSI_SHUTDOWN_PSM_PM2BOOT = 0x5042, ///< 'PB' power saving mode with PM2
- OSI_SHUTDOWN_PANIC = 0x504e, ///< 'PN' panic reset
- OSI_SHUTDOWN_OPENCPU_PM2_SLEEP = 0x6045, ///< 'OPM' opencpu power mode 2
- OSI_SHUTDOWN_OPENCPU_PSM_SLEEP = 0x6056, ///< 'OPS' opencpu power saving mode
- OSI_SHUTDOWN_OPENCPU_SWITCH = 0x5357, ///< 'SW' opencpu switch system
- OSI_SHUTDOWN_CANCEL = 0xffff, ///< special value for shutdown callback
- } osiShutdownMode_t;
- /**
- * PSM data owner
- */
- typedef enum osiPsmDataOwner
- {
- OSI_PSMDATA_OWNER_KERNEL, ///< kernel
- OSI_PSMDATA_OWNER_STACK, ///< stack
- OSI_PSMDATA_OWNER_AT, ///< AT engine
- OSI_PSMDATA_OWNER_CFW, ///< CFW
- OSI_PSMDATA_OWNER_NBTIMER, ///< NBIOT timers
- OSI_PSMDATA_OWNER_NBSDB, ///< NBIOT sdb
- OSI_PSMDATA_OWNER_NBLPS, ///< NBIOT LPS
- OSI_PSMDATA_OWNER_LWIP, ///< LWIP
- OSI_PSMDATA_OWNER_USER = 100, ///< start owner for user application
- } osiPsmDataOwner_t;
- /**
- * shuwdown callback function type
- *
- * Before shutdown, the registered callbacks will be invokes. The callbacks
- * are executed in system high priority work queue, and with interrupt
- * disabled. So, the callbacks shouldn't rely on system high priority work
- * queue and interrupts. However, thread schedule is still working and
- * multi-thread can work still.
- */
- typedef void (*osiShutdownCallback_t)(void *ctx, osiShutdownMode_t mode);
- /**
- * invoke global constructors
- *
- * Global constructors are not called during boot. Rather, they will be called
- * in \p osiInvokeGlobalCtors, and it shall be called in \p osiAppStart.
- *
- * At \p osiAppStart, RTOS is ready. So, it is permitted to call more OSI
- * APIs at global constructors.
- *
- * Though global constructors are supported. It is not encouraged to use this
- * feature. Only use this feature when you really know what you are doing.
- */
- void osiInvokeGlobalCtors(void);
- /**
- * kernel start
- *
- * Start the kernel. This API will create system threads (at least,
- * idle thread) and start thread scheduler. So, it won't return.
- *
- * Before \p osiKernelStart is called, kernel data structure may be
- * uninitialized, and many osi APIs can be called. Including
- *
- * - timer
- * - IRQ
- * - power management
- */
- OSI_NO_RETURN void osiKernelStart(void);
- /**
- * suspend thread scheduler
- *
- * After scheduler is suspended, there are no thread context switch.
- * However, interrupt handlers will be executed.
- *
- * The meaning of return flag depends on underlay RTOS. Don't assume the
- * meaning of the return value.
- *
- * \return scheduler suspend flag.
- */
- uint32_t osiSchedulerSuspend(void);
- /**
- * resume thread scheduler
- *
- * Scheduler suspend and resume is not *recursive*. That is, after
- * \p osiSchedulerResume is called, scheduler is resumed no matter
- * how many times \p osiSchedulerSuspend are called.
- *
- * \param [in] flag scheduler suspend flag returned by the latest
- * \p osiSchedulerSuspend
- */
- void osiSchedulerResume(uint32_t flag);
- /**
- * \brief enter critical section
- *
- * The underlay RTOS may have different implementation for critical
- * section. It may manipulate CPU IRQ enable bit(s), or manipulate
- * IRQ mask.
- *
- * This can be called in ISR.
- *
- * \return critical section flags
- */
- uint32_t osiEnterCritical(void);
- /**
- * \brief exit critical section
- *
- * Critical section flags is implementation depend. It should be the value
- * returned by \p osiEnterCritical, and don't change the value manually.
- *
- * Critical section is *recursive*. That is, after \p osiExitCritical is
- * called, it doesn't mean system will enter *unprotected* state. Rather,
- * it will return to state before last call of \p osiEnterCritical.
- * For example:
- *
- * \code{.cpp}
- * uint32_t critical1 = osiEnterCritical();
- * uint32_t critical2 = osiEnterCritical();
- * // ...
- * osiExitCritical(critical2);
- * osiExitCritical(critical1);
- * \endcode
- *
- * After the first call of \p osiExitCritical, system is in *protected*
- * state still.
- *
- * In recursive, the exit order must be the reverse order of enter. For
- * example, the following codes are wrong:
- *
- * \code{.cpp}
- * uint32_t critical1 = osiEnterCritical();
- * uint32_t critical2 = osiEnterCritical();
- * // ...
- * osiExitCritical(critical1);
- * osiExitCritical(critical2);
- * \endcode
- *
- * This can be called in ISR.
- *
- * \param critical critical section flags
- */
- void osiExitCritical(uint32_t critical);
- /**
- * \brief get IRQ flags and disable IRQ
- *
- * This will always manipulate CPU IRQ enable bit(s).
- *
- * After this call, \p osiEnterCritical can't be called. When
- * \p osiEnterCritical manipulates IRQ mask, it is very possible that
- * it will change CPU IRQ enable bit(s) without protection.
- *
- * In most cases, \p osiIrqSave and \p osiIrqRestore shouldn't be
- * used, unless you really know what you are doing.
- *
- * \return IRQ flags before disable IRQ
- */
- uint32_t osiIrqSave(void);
- /**
- * \brief restore IRQ flags
- *
- * IRQ flags is arch and implementation depend. It should be the value
- * returned by \p osiIrqSave, and don't change the value manually.
- *
- * \param flags IRQ flags
- */
- void osiIrqRestore(uint32_t flags);
- /**
- * set interrupt handler
- *
- * When interrupt arrived, the registered handler will be called with
- * the registered context pointer.
- *
- * For each interrupt, only one handler can be registered. When a handler
- * is already registered for an interrupt, \p osiIrqSetHandler will
- * replace the old one.
- *
- * \p irqn depends on interrupt controller in system. When GIC is used,
- * it is the number in GIC.
- *
- * \param irqn IRQ number
- * \param handler IRQ handler
- * \param ctx IRQ handler context pointer
- * \return
- * - true on success
- * - false on invalid parameters
- */
- bool osiIrqSetHandler(uint32_t irqn, osiIrqHandler_t handler, void *ctx);
- /**
- * enable interrupt
- *
- * \param irqn IRQ number
- * \return
- * - true on success
- * - false on invalid parameters
- */
- bool osiIrqEnable(uint32_t irqn);
- /**
- * disable interrupt
- *
- * \param irqn IRQ number
- * \return
- * - true on success
- * - false on invalid parameters
- */
- bool osiIrqDisable(uint32_t irqn);
- /**
- * whether interrupt is enabled
- *
- * \param irqn IRQ number
- * \return
- * - true if interrupt is enabled
- * - false if interrupt is disabled
- */
- bool osiIrqEnabled(uint32_t irqn);
- /**
- * set interrupt priority
- *
- * \p priority depends on interrupt controller used on system. When GIC
- * is used, \p priority should follow GIC requirement and meaning.
- *
- * \param irqn IRQ number
- * \param priority IRQ priority
- * \return
- * - true on success
- * - false on invalid parameters
- */
- bool osiIrqSetPriority(uint32_t irqn, uint32_t priority);
- /**
- * get interrupt priority
- *
- * When \p irqn is invalid, 0x80000000U will be returned.
- *
- * \param irqn IRQ number
- * \return IRQ priority
- */
- uint32_t osiIrqGetPriority(uint32_t irqn);
- /**
- * set interrupt group
- *
- * This is only valid when GIC is used.
- *
- * \param irqn IRQ number
- * \param group GIC group
- * \return
- * - true on success
- * - false on invalid parameters
- */
- bool osiIrqSetGroup(uint32_t irqn, uint32_t group);
- /**
- * check whether there are pending interrupt
- *
- * This is for special purpose. It shall be called with interrupt disabled
- * (not masked off).
- *
- * This may be unimplemented in some chips.
- *
- * \return
- * - true if there are interrupt pending.
- */
- bool osiIrqPending(void);
- /**
- * enable D-cache
- *
- * Usually, it shouldn't be called in application. It will only be called
- * once in boot code.
- *
- * Not all platforms implement this API.
- */
- void osiDCacheEnable(void);
- /**
- * disable D-cache
- *
- * Usually, it shouldn't be called in application. And most likely it will
- * never be called. It is provided for completeness.
- *
- * Not all platforms implement this API.
- */
- void osiDCacheDisable(void);
- /**
- * enable I-cache
- *
- * Usually, it shouldn't be called in application. It will only be called
- * once in boot code.
- *
- * Not all platforms implement this API.
- */
- void osiICacheEnable(void);
- /**
- * disable I-cache
- *
- * Usually, it shouldn't be called in application. And most likely it will
- * never be called. It is provided for completeness.
- *
- * Not all platforms implement this API.
- */
- void osiICacheDisable(void);
- /**
- * clean (write back) D-cache
- *
- * Usually it shall be called **before** the cachable memory will be read by
- * not cache coherent hardware.
- *
- * D-cache clean will operate by cache line. So, is the memory range is
- * not cache line aligned, other memory on the cache line will be cleaned
- * also. For example, assuming D-cache line size is 32 byte,
- * \p osiDCacheClean((void *)8, 32) will clean [0-8], [40-64] also.
- *
- * When D-cache coherence is needed to be considered, it is recommended to
- * declare or allocate memory by the following:
- *
- * \code{.cpp}
- * char mem1[SIZE] OSI_CACHE_LINE_ALIGNED;
- * void *mem2 = memalign(CONFIG_CACHE_LINE_SIZE, size);
- * \endcode
- *
- * \param address starting address to be cleaned
- * \param size size to be cleaned
- */
- void osiDCacheClean(const void *address, size_t size);
- /**
- * invalidate D-cache
- *
- * Usually it shall be called **before** the cachable memory will be write by
- * not cache coherent hardware.
- *
- * D-cache line alignment is very important for \p osiDCacheInvalidate.
- * Otherwise, other memory on the cache line will be changed randomly.
- *
- * \param address starting address to be cleaned
- * \param size size to be cleaned
- */
- void osiDCacheInvalidate(const void *address, size_t size);
- /**
- * clean and invalidate D-cache
- *
- * \param address starting address to be cleaned
- * \param size size to be cleaned
- */
- void osiDCacheCleanInvalidate(const void *address, size_t size);
- /**
- * invalidate D-cache range
- *
- * \param address starting address to be cleaned
- * \param size size to be cleaned
- */
- void osiICacheInvalidate(const void *address, size_t size);
- /**
- * sync D-cahce with I-cache
- *
- * It shall be called after code memory is operated as data (such as,
- * copy codes from flash to RAM).
- *
- * \param address starting address to be cleaned
- * \param size size to be cleaned
- */
- void osiICacheSync(const void *address, size_t size);
- /**
- * clean all D-cache
- */
- void osiDCacheCleanAll(void);
- /**
- * invalidate all D-cache
- */
- void osiDCacheInvalidateAll(void);
- /**
- * clean and invalidate all D-cache
- */
- void osiDCacheCleanInvalidateAll(void);
- /**
- * invalidate all I-cache
- */
- void osiICacheInvalidateAll(void);
- /**
- * sync D-cahce with I-cache for all
- */
- void osiICacheSyncAll(void);
- /**
- * create a thread
- *
- * Each \p osiThread_t will have an event queue. So, the event queue
- * depth should be specified at creation.
- *
- * \p name will be copied to thread control block. So, \p name can be dynamic
- * memory.
- *
- * After a thread is created, it will be executed immediately. So, it is
- * possible that \p entry will be executed before the return value is
- * assigned to some variable, if the new thread priority is higher than
- * current thread priority. Pay attention to use thread pointer in
- * \p entry.
- *
- * \code{.cpp}
- * void entry(void *argument) {
- * osiThread_t *thread = osiThreadCurrent();
- * for (;;) {
- * osiEvent_t event = {};
- * osiEventWait(thread, &event);
- * ......
- * }
- * }
- * \endcode
- *
- * In some underlay RTOS, there are limitation on maximum stack size.
- * For example, when \p configSTACK_DEPTH_TYPE is defined as \p uint16_t,
- * the stack size must be less than 64KB*4.
- *
- * \param name thread name
- * \param entry thread entry function
- * \param argument thread entry function argument
- * \param priority thread priority
- * \param stack_size thread stack size in byte
- * \param event_count thread event queue depth (count of events can be hold)
- * \return
- * - thread pointer
- * - NULL if failed
- */
- osiThread_t *osiThreadCreate(const char *name, osiThreadEntry_t entry, void *argument,
- uint32_t priority, uint32_t stack_size,
- uint32_t event_count);
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- /**
- * create a thread
- *
- * Each \p osiThread_t will have an event queue. So, the event queue
- * depth should be specified at creation.
- *
- * \p name will be copied to thread control block. So, \p name can be dynamic
- * memory.
- *
- * After a thread is created, it will be executed immediately. So, it is
- * possible that \p entry will be executed before the return value is
- * assigned to some variable, if the new thread priority is higher than
- * current thread priority. Pay attention to use thread pointer in
- * \p entry.
- *
- * \code{.cpp}
- * void entry(void *argument) {
- * osiThread_t *thread = osiThreadCurrent();
- * for (;;) {
- * osiEvent_t event = {};
- * osiEventWait(thread, &event);
- * ......
- * }
- * }
- * \endcode
- *
- * In some underlay RTOS, there are limitation on maximum stack size.
- * For example, when \p configSTACK_DEPTH_TYPE is defined as \p uint16_t,
- * the stack size must be less than 64KB*4.
- *
- * \param name thread name
- * \param entry thread entry function
- * \param argument thread entry function argument
- * \param priority thread priority
- * \param stack_size thread stack size in byte
- * \param event_count thread event queue depth (count of events can be hold)
- * \return
- * - thread pointer
- * - NULL if failed
- */
- osiThread_t *quec_osiThreadCreate(const char *name, osiThreadEntry_t entry, void *argument,
- uint32_t priority, uint32_t stack_size,
- uint32_t event_count);
- #endif
- /**
- * create a thread with specified stack
- *
- * It is similar to \p osiThreadCreate, and the stack won't be dynamic created.
- * Rather, the specified buffer \p stack will be used at the stack of the
- * thread. Typical usage is to create performance sensitive thread, and set stack
- * in SRAM to improve performance.
- *
- * Application should always use \p osiThreadCreate. It may be unimplemented on
- * some platforms.
- *
- * \param name thread name
- * \param entry thread entry function
- * \param argument thread entry function argument
- * \param priority thread priority
- * \param stack thread stack buffer, must be valid
- * \param stack_size thread stack size in byte
- * \param event_count thread event queue depth (count of events can be hold)
- * \return
- * - thread pointer
- * - NULL if failed
- */
- osiThread_t *osiThreadCreateWithStack(const char *name, osiThreadEntry_t entry, void *argument,
- uint32_t priority, void *stack, uint32_t stack_size,
- uint32_t event_count);
- /**
- * get event queue of thread
- *
- * When \p thread is NULL, return the event queue of current thread.
- *
- * \param thread thread pointer
- * \return event queue of the thread
- */
- osiEventQueue_t *osiThreadEventQueue(osiThread_t *thread);
- /**
- * get current thread pointer
- *
- * \return current thread pointer
- */
- osiThread_t *osiThreadCurrent(void);
- /**
- * set whether current thread need FPU
- *
- * Obsoleted. Floating point can be used in all threads, and ISR. This API
- * is just for compatible, and implemented as empty.
- *
- * \param enabled true for enable FPU, false for disable FPU.
- */
- void osiThreadSetFPUEnabled(bool enabled);
- /**
- * get thread priority
- *
- * When \p thread is NULL, return the priotity of current thread.
- *
- * \param thread thread pointer
- * \return priotity of the thread
- */
- uint32_t osiThreadPriority(osiThread_t *thread);
- /**
- * set thread priority
- *
- * When \p thread is NULL, set the priotity of current thread.
- *
- * After the priority changed, it is possible thread context switch
- * will occur. However, don't depend on this feature.
- *
- * \param thread thread pointer
- * \param priority priority to be set
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiThreadSetPriority(osiThread_t *thread, uint32_t priority);
- /**
- * suspend a thread
- *
- * When \p thread is NULL, suspend current thread.
- *
- * \param thread thread pointer
- */
- void osiThreadSuspend(osiThread_t *thread);
- /**
- * resume a thread
- *
- * \p thread can't be NULL.
- *
- * \param thread thread pointer
- */
- void osiThreadResume(osiThread_t *thread);
- /**
- * current thread yield
- *
- * When there are threads with the same priority, other threads will
- * be scheduled.
- */
- void osiThreadYield(void);
- /**
- * current thread sleep
- *
- * Change current thread into sleep mode, and will be rescheduled
- * after the specified period.
- *
- * This will use the underlay RTOS mechanism. It is possible the sleep
- * time precision is the tick of underlay RTOS.
- *
- * \param ms sleep time in milliseconds
- */
- void osiThreadSleep(uint32_t ms);
- /**
- * current thread sleep with high precision timer
- *
- * It won't use the underlay RTOS mechanism, rather it will use high
- * precision timer.
- *
- * It will be used when high precision sleep time is needed.
- *
- * \param us sleep time in microseconds
- */
- void osiThreadSleepUS(uint32_t us);
- /**
- * current thread sleep with relaxed timeout
- *
- * It is a power optimization version of \p osiThreadSleep. Due to power
- * saving, it is possible that current thread will be wakeup later then
- * *normal timeout*, but it will wakeup no later than *relaxed timeout*
- * even system will enter suspend.
- *
- * When \p relax_ms is \p OSI_DELAY_MAX, it means it can be ignored
- * completed for power saving. However, after system is awoken, the thread
- * will be wakeup still if the *normal timeout* is expired.
- *
- * \param ms sleep time in milliseconds
- * \param relax_ms relaxed sleep time in milliseconds
- */
- void osiThreadSleepRelaxed(uint32_t ms, uint32_t relax_ms);
- /**
- * thread stack unused space
- *
- * It needs underlay RTOS support. When the underlay RTOS doesn't support
- * this feature, it returns 0.
- *
- * The typical method to support this feature in underlay RTOS is to check
- * stack content, and comparing with preset magic byte or word.
- *
- * It is recommended to use it only for debug.
- *
- * \param thread thread pointer, NULL for current thread
- * \return
- * - thread stack unused space in bytes
- * - 0 if the underlay RTOS doesn't support this feature
- */
- uint32_t osiThreadStackUnused(osiThread_t *thread);
- /**
- * space from current stack pointer to current thread stack end
- *
- * When \p refill is true, the current stack space will be fill with magic
- * byte or word for measuring unused stack. When underlay RTOS doesn't
- * support feature to measure stack remain, \p refill will be ignored.
- *
- * It is recommended to use it only for debug.
- *
- * \return
- * - space to current thread stack end, in bytes
- */
- uint32_t osiThreadStackCurrentSpace(bool refill);
- /**
- * current thread exit
- *
- * When a thread is finished, \p osiThreadExit must be called. And
- * kernel will release thread resources at appropriate time.
- */
- OSI_NO_RETURN void osiThreadExit(void);
- /**
- * show thread information through trace
- *
- * It is for debug purpose only.
- */
- void osiShowThreadState(void);
- /**
- * send an event to a thread
- *
- * At send, the body of \p event will be copied to event queue
- * rather then send the pointer of \p event.
- *
- * When event queue of the target thread is full, the caller thread
- * will be block until there are rooms in target thread event queue.
- *
- * This can be called in ISR. And in ISR, it will return false when event
- * queue is full, and not wait.
- *
- * \param thread thread pointer, can't be NULL
- * \param event event to be sent
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiEventSend(osiThread_t *thread, const osiEvent_t *event);
- /**
- * send event loop quit event to a thread
- *
- * This is the normalized method to notify a thread to quit. When \p thread
- * is the current thread, \p wait can't be true.
- *
- * \code{.cpp}
- * // caller thread
- * osiSendQuitEvent(thread);
- *
- * // thread to quit
- * for (;;) {
- * osiEvent_t event = {};
- * osiEventWait(thread, &event);
- * if (event.id == OSI_EVENT_ID_QUIT)
- * break;
- *
- * // ......
- * }
- * osiThreadExit();
- * \endcode
- *
- * \param thread thread pointer, can't be NULL
- * \param wait whether to wait thread exit
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiSendQuitEvent(osiThread_t *thread, bool wait);
- /**
- * send an event to a thread with timeout
- *
- * When \p timeout is 0, this will return false immediately. When \p timeout
- * is \p OSI_WAIT_FOREVER, this will wait forever until there are
- * rooms in target thread event queue.
- *
- * This can be called in ISR. And in ISR, \p timeout will be ignored.
- *
- * \param thread thread pointer, can't be NULL
- * \param event event to be sent
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter, or timeout
- */
- bool osiEventTrySend(osiThread_t *thread, const osiEvent_t *event, uint32_t timeout);
- /**
- * wait an event
- *
- * Wait an event from current thread event queue. When current thread
- * event queue is empty, it will be blocked forever until there are
- * event in event queue.
- *
- * The event body will be copied to \p event.
- *
- * There are some event ID used by system. After system event is received
- * and process, this will return an event with ID of 0. Application can
- * ignore event ID 0 safely.
- *
- * It **can't** be called in ISR. And in ISR, it will return false directly.
- *
- * \param thread thread pointer, can't be NULL
- * \param event event pointer
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiEventWait(osiThread_t *thread, osiEvent_t *event);
- /**
- * wait an event with timeout
- *
- * When \p timeout is 0, this will return false immediately. When \p timeout
- * is \p OSI_WAIT_FOREVER, this will wait forever until there are
- * events in target thread event queue.
- *
- * It **can't** be called in ISR. And in ISR, it will return false directly.
- *
- * \param thread thread pointer, can't be NULL
- * \param event event pointer
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter, or timeout
- */
- bool osiEventTryWait(osiThread_t *thread, osiEvent_t *event, uint32_t timeout);
- /**
- * whether there are pending event in event queue
- *
- * It can be called in both thread context and ISR context.
- *
- * \param thread thread pointer, can't be NULL
- * \return
- * - true if there are pending event
- * - false if not
- */
- bool osiEventPending(osiThread_t *thread);
- /**
- * get the pending event count in event queue
- *
- * It can be called in both thread context and ISR context.
- *
- * \param thread thread pointer, can't be NULL
- * \return
- * - the pending event count in event queue
- * - 0 on invalid parameter
- */
- uint32_t osiEventPendingCount(osiThread_t *thread);
- /**
- * get the space of event count in event queue
- *
- * It can be called in both thread context and ISR context.
- *
- * \param thread thread pointer, can't be NULL
- * \return
- * - the space of event count in event queue
- * - 0 on invalid parameter
- */
- uint32_t osiEventSpaceCount(osiThread_t *thread);
- /**
- * set callback to be executed on thread
- *
- * Thread callback is implemented by \p osiEvent_t.
- *
- * This can be called in ISR. In ISR, the callback event will be lost when
- * the event queue of target thread is full.
- *
- * \param thread thread pointer, can't be NULL
- * \param cb callback to be executed
- * \param cb_ctx callback context
- * \return
- * - true on success
- * - false on invalid parameter, or event queue is full in ISR
- */
- bool osiThreadCallback(osiThread_t *thread, osiCallback_t cb, void *cb_ctx);
- /**
- * \brief create a work
- *
- * \p run can't be NULL, and \p complete can be NULL.
- *
- * \param run execute function of the work
- * \param complete callback to be invoked after the work is finished
- * \param ctx context of \p run and \p complete
- * \return
- * - the created work
- * - NULL if invalid parameter or out of memory
- */
- osiWork_t *osiWorkCreate(osiCallback_t run, osiCallback_t complete, void *ctx);
- /**
- * \brief delete the work
- *
- * When \p work is running when it is called, it will be deleted after the
- * current run finished.
- *
- * \param work the work to be deleted
- */
- void osiWorkDelete(osiWork_t *work);
- /**
- * \brief reset callback of existed work
- *
- * This can change the callbacks of existed work. It can be used to setup
- * a kind of *work flow*. An example:
- *
- * \code{.cpp}
- * static void prvPrepare(void *param) {
- * // ....
- * osiWorkResetCallback(work, prvRealJob, NULL, ctx);
- * }
- *
- * static void prvRealJob(void *param) {
- * // ...
- * }
- *
- * void init(void) {
- * work = osiWorkCreate(prvPrepare, NULL, ctx);
- * osiWorkEnqueue(work, wa);
- * }
- * \endcode
- *
- * This is clearer than creating multiple work instances.
- *
- * Though it is not typical application, the callbacks can be changed when
- * the work is already queued. In this case, there may exist corner cases
- * about whether the previous or the new callbacks will be invoked, depends
- * on thread priorities. Caller should take care about this.
- *
- * When it is called inside work callback, the new callbacks will be invoked
- * at the next timer when work is invoked.
- *
- * \param work the work pointer, must be valid
- * \param run execute function of the work
- * \param complete callback to be invoked after the work is finished
- * \param ctx context of \p run and \p complete
- * \return
- * - true on success
- * - false on fail, invalid parameters
- */
- bool osiWorkResetCallback(osiWork_t *work, osiCallback_t run, osiCallback_t complete, void *ctx);
- /**
- * \brief enqueue a work in specified work queue
- *
- * When \p work is running, it will be queued to \p wq again and then it
- * will be invoked again.
- *
- * When \p work is queued, and \p wq is the same as original work queue,
- * nothing will be done. When \p wq is not the same as the original
- * work queue, it will be removed from the original work queue, and
- * queue the work into the specified work queue.
- *
- * This can be called in ISR.
- *
- * \param work the work pointer, must be valid
- * \param wq work queue to run the work, must be valid
- * \return
- * - true on success
- * - false for invalid parameter, or work is running
- */
- bool osiWorkEnqueue(osiWork_t *work, osiWorkQueue_t *wq);
- /**
- * \brief enqueue a work in the last of specified work queue
- *
- * It is similar to \p osiWorkEnqueue, except it will consider work order.
- * For example:
- *
- * \code{.cpp}
- * osiWorkEnqueue(work1, wq);
- * osiWorkEnqueue(work2, wq);
- * osiWorkEnqueue(work1, wq);
- * \endcode
- *
- * If work queue is busy on another work during these calls, and when work
- * queue processing these works, it will:
- * - execute work1->callback
- * - execute work2->callback
- *
- * So, even the order of works aren't preserved. \p work1 is the last queued
- * work, and the real last executed work is \p work2.
- *
- * With \p osiWorkEnqueueLast, it will ensure that the last queued work will
- * be executed at the last.
- *
- * \param work the work pointer, must be valid
- * \param wq work queue to run the work, must be valid
- * \return
- * - true on success
- * - false for invalid parameter, or work is running
- */
- bool osiWorkEnqueueLast(osiWork_t *work, osiWorkQueue_t *wq);
- /**
- * \brief cancel a work
- *
- * When \p work is running, the current execution won't be interrupted.
- *
- * \param work the work pointer, must be valid
- */
- void osiWorkCancel(osiWork_t *work);
- /**
- * \brief wait a work finish
- *
- * When \p work is running or enqued, this will wait the work finish.
- * When \p timeout is 0, it will return immediately. When \p timeout
- * is \p OSI_WAIT_FOREVER, it will wait infinitely until the work is
- * finished.
- *
- * \param work the work pointer, must be valid
- * \param timeout wait timeout
- * \return
- * - true if the work is finished
- * - false on invalid parameter, or wait timeout
- */
- bool osiWorkWaitFinish(osiWork_t *work, unsigned timeout);
- /**
- * \brief create work queue
- *
- * Multiple threads can be created to reduce work execution latency. For
- * example, when one thread in a work queue is blocked, other threads of
- * the work queue can execute other works queued to the work queue.
- *
- * The maximum thread count is implementation dependent. So, it is possible
- * that the created thread count is less than \p thread_count. And also it is
- * possible that \p thread_count is ignored.
- *
- * The created threads have the same priority and stack size.
- *
- * The work queue thread entry function can't be customized
- *
- * \param name work queue name
- * \param thread_count thread count to be created for the work queue
- * \param priority work queue thread priority
- * \param stack_size thread stack size in byte
- * \return
- * - the work queue pointer
- * - NULL if failed
- */
- osiWorkQueue_t *osiWorkQueueCreate(const char *name, size_t thread_count, uint32_t priority, uint32_t stack_size);
- /**
- * \brief delete work queue
- *
- * All resources of the work queue will be deleted.
- *
- * The works in running will continue, and \p complete will be invoked as
- * normal. However, queued work in the work queue won't be executed any more.
- *
- * \param wq work queue to be deleted
- */
- void osiWorkQueueDelete(osiWorkQueue_t *wq);
- /**
- * \brief get the system high priority work queue
- *
- * A work queue with priority \p OSI_PRIORITY_HIGH will be created at kernel
- * start.
- *
- * \return the system high priority work queue
- */
- osiWorkQueue_t *osiSysWorkQueueHighPriority(void);
- /**
- * \brief get the system low priority work queue
- *
- * A work queue with priority \p OSI_PRIORITY_LOW will be created at kernel
- * start.
- *
- * \return the system low priority work queue
- */
- osiWorkQueue_t *osiSysWorkQueueLowPriority(void);
- /**
- * \brief get the system work queue for asynchronuous file system write
- *
- * A work queue with priority \p OSI_PRIORITY_BELOW_NORMAL will be created
- * at kernel start. This work queue shall be used for asynchronuous file
- * system write.
- *
- * Usually file write is slow, especially for file system on NOR flash.
- * When faster response is needed, file write can be deferred to this
- * work queue. Also, the work queue will be flushed before system shutdown.
- *
- * \return the system file write work queue
- */
- osiWorkQueue_t *osiSysWorkQueueFileWrite(void);
- /**
- * \brief create a thread notify
- *
- * Thread notify is thread callback with state to avoid duplicated event
- * to be sent to thread event queue.
- *
- * \param thread thread to execute the callback, can't be NULL
- * \param cb callback to be executed, can't be NULL
- * \param ctx callback context
- * \return
- * - created notify
- * - NULL if parameters are invalid or out of memory
- */
- osiNotify_t *osiNotifyCreate(osiThread_t *thread, osiCallback_t cb, void *ctx);
- /**
- * \brief delete a thread notify
- *
- * The memory of the thread notify will be released.
- *
- * When the thread notify is already in thread event queue, the callback
- * won't be invoked, and the memory may be released delayed.
- *
- * \param notify thread notify pointer, must be valid
- */
- void osiNotifyDelete(osiNotify_t *notify);
- /**
- * \brief trigger a thread notify
- *
- * When the thread notify event isn't in thread event queue, an event for
- * thread notify will be queued to the tail of thread event queue.
- *
- * \param notify thread notify pointer, must be valid
- */
- void osiNotifyTrigger(osiNotify_t *notify);
- /**
- * \brief cancel a thread notify
- *
- * When the thread notify event has already sent to thread event queue,
- * the invocation of the callback will be cancelled.
- *
- * \param notify thread notify pointer, must be valid
- */
- void osiNotifyCancel(osiNotify_t *notify);
- /**
- * \brief create a timer
- *
- * Create a timer with specified callback and callback context. After create,
- * the timer is in stop state. Application can start it in various mode.
- *
- * When \p thread is \p OSI_TIMER_IN_ISR, the callback will be executed in
- * timer ISR. So, the callback should follow ISR programming guide. This is
- * **not** recommended unless it is absolutely needed.
- *
- * When \p thread is \p OSI_TIMER_IN_SERVICE, the callback will be executed
- * in timer service thread.
- *
- * Otherwise, the callback will be executed in the specified thread through
- * *event* mechanism.
- *
- * It is needed to call \p osiTimerDelete to free resources.
- *
- * \param thread thread to execute the callback
- * \param cb callback to be executed after timer expire
- * \param ctx callback context
- * \return
- * - the created timer instance
- * - NULL at out of memory, or invalid parameter
- */
- osiTimer_t *osiTimerCreate(osiThread_t *thread, osiCallback_t cb, void *ctx);
- /**
- * \brief create a timer, enqueue a work on expiration
- *
- * Create a timer with specified callback and callback context. After create,
- * the timer is in stop state. Application can start it in various mode.
- *
- * At expiration, \p work will be enqueued to \p wq.
- *
- * It is needed to call \p osiTimerDelete to free resources.
- *
- * \param work work to be enqueued at expiration
- * \param wq work queue to be enqueued at expiration
- * \return
- * - the created timer instance
- * - NULL at out of memory, or invalid parameter
- */
- osiTimer_t *osiTimerCreateWork(osiWork_t *work, osiWorkQueue_t *wq);
- /**
- * \brief create a timer, EV_TIMER on expiration
- *
- * This is for legacy codes only. **Don't** use it except at porting
- * legacy codes.
- *
- * Create a timer with specified timerid. After the timer expired, the
- * specified thread will receive an event { EV_TIMER, timerid, 0, 0}.
- *
- * It is needed to call \p osiTimerDelete to free resources.
- *
- * \param thread thread to execute the callback, it can't be NULL
- * \param timerid timerid in expiration event
- * \return
- * - the created timer instance
- * - NULL at out of memory, or invalid parameter
- */
- osiTimer_t *osiTimerEventCreate(osiThread_t *thread, uint32_t timerid);
- /**
- * \brief set/change callback of timer
- *
- * In most cases, timer callback set at create is not needed to be changed.
- *
- * \p timer should be created by \p osiTimerCreate. Special values of
- * \p thread follow \p osiTimerCreate.
- *
- * It is permitted to change \p thread of timer, including special values.
- * For example, it is permitted to change a timer executing in timer service
- * to timer executing in specified thread. However, it is not recommended.
- *
- * This can only be called when \p timer is stopped. Otherwise, it will
- * return false.
- *
- * \param timer timer to be changed
- * \param thread thread to execute the callback
- * \param cb callback to be executed after timer expire
- * \param ctx callback context
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerSetCallback(osiTimer_t *timer, osiThread_t *thread, osiCallback_t cb, void *ctx);
- /**
- * \brief set/change work and work queue of timer
- *
- * In most cases, timer work and work queue set at create is not needed to be changed.
- *
- * \p timer should be created by \p osiTimerCreateWork, to enqueue work to work
- * queue at expiration.
- *
- * \param timer timer to be changed
- * \param work work to be enqueued at expiration
- * \param wq work queue to be enqueued at expiration
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerSetWork(osiTimer_t *timer, osiWork_t *work, osiWorkQueue_t *wq);
- /**
- * \brief set/change timer event
- *
- * In most cases, timer thread and id set at create is not needed to be changed.
- *
- * \p timer should be created by \p osiTimerEventCreate.
- *
- * \param timer timer to be changed
- * \param thread thread to execute the callback, it can't be NULL
- * \param timerid timerid in expiration event
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerSetEvent(osiTimer_t *timer, osiThread_t *thread, uint32_t timerid);
- /**
- * \brief delete a timer
- *
- * Delete the timer, and free associated resources.
- *
- * When the timer callback will be executed in thread rather than ISR, and the
- * event for timer expiration has been sent, some resources won't be freed
- * immediately. Rather, they will be freed after the timer expiration event
- * is popped out from thread event queue. However, the callback won't be
- * executed even delete is delayed.
- *
- * Refer to document about corner case of timer thread callback.
- *
- * \param timer the timer to be deleted
- */
- void osiTimerDelete(osiTimer_t *timer);
- /**
- * \brief change timer relaxed timeout for running timer
- *
- * When the timer is not running, it will return false.
- *
- * When the timer is started, this will change the relaxed timeout
- * specified at start.
- *
- * This can be called for both one shot timer and periodic timer.
- *
- * \p relaxed_ms is the additional time based on normal timeout. It will
- * only be used for sleep. When \p relaxed_ms is 0, this timer will wakeup
- * system even system enter sleep mode. When \p relaxed_ms is
- * \p OSI_DELAY_MAX, this timer will not wakeup system when system enter
- * sleep mode. Otherwise, system will process the timer no later than the
- * normal timeout plus additional timeout.
- *
- * For example, when the period of a timer is 100ms, and relaxed timeout
- * is 500ms, system will process the timer no later than 600ms. This can
- * make system sleep more time, and reduce power consumption.
- *
- * For periodic timer, the additional timeout is add to normal timeout of
- * earch run. For example, a periodic timer period is 100ms, and relaxed
- * timeout is 50ms, then system will process the timer no later than 150ms.
- * And even the timer is delayed to 150ms due to system sleep, the next
- * timeout is 200ms unchanged. Another example, a periodic timer period
- * is 100ms, and relaxed timeout is 500ms, then system will process the
- * timer no later than 600ms. When the timer is delayed to 600ms due to
- * system sleep, the callback will be invoked only once even 6 periods are
- * elapsed. The next timeout is at 700ms.
- *
- * \param timer the timer to be set
- * \param relaxed_ms relaxed timeout in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter, or timer is not running
- */
- bool osiTimerChangeRelaxed(osiTimer_t *timer, uint32_t relaxed_ms);
- /**
- * \brief set timer period for next call
- *
- * The properties will be used by next \p osiTimerStartLast. It can only be
- * called when the timer is not running.
- *
- * It is the same as \p osiTimerSetPeriodRelaxed, with \p relaxed_ms
- * as 0.
- *
- * \param timer the timer to be set
- * \param ms period in milliseconds
- * \param periodic true for periodic, false for one shot
- * \return
- * - true on success
- * - false on invalid parameter, or timer is started
- */
- bool osiTimerSetPeriod(osiTimer_t *timer, uint32_t ms, bool periodic);
- /**
- * \brief set timer period for next call, with relaxed timeout
- *
- * The properties will be used by next \p osiTimerStartLast. It can only be
- * called when the timer is not running.
- *
- * \param timer the timer to be set
- * \param ms period in milliseconds
- * \param relaxed_ms relaxed timeout in milliseconds
- * \param periodic true for periodic, false for one shot
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerSetPeriodRelaxed(osiTimer_t *timer, uint32_t ms, uint32_t relaxed_ms, bool periodic);
- /**
- * \brief whether timer is started
- *
- * \param timer the timer to be set
- * \return
- * - true if the timer is started
- * - false if not started, or invalid parameter
- */
- bool osiTimerIsRunning(osiTimer_t *timer);
- /**
- * \brief get remaining time of timer in milliseconds
- *
- * Even the timer is already timed out, it will return 0 rather then negative
- * value. For example, thread callback timer is already timed out, but the
- * callback hasn't invoked in the specified thread.
- *
- * \param timer the timer to be set
- * \return
- * - remaining time
- * - timer is not started, or invalid parameter
- */
- int64_t osiTimerRemaining(osiTimer_t *timer);
- /**
- * \brief timer expiration time in milliseconds
- *
- * The expiration time is in the same coordinate of \p osiUpTime.
- *
- * When the timer is not running, it will return -1. For already timeed out
- * timer, the return value may be smaller than \p osiUpTime.
- *
- * \param timer the timer to be checked
- * \return
- * - expiration time
- * - -1 if the timer is not running
- */
- int64_t osiTimerExpiration(osiTimer_t *timer);
- /**
- * \brief start a timer with last period
- *
- * The last period is the period set by \p osiTimerSetPeriod, or other start
- * APIs with period parameter.
- *
- * It is recommended that not to mixing start API with period parameter, and
- * start API without period parameter. Though the behavior is determinstic,
- * it is harder to be understood.
- *
- * \param timer the timer to be started
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStartLast(osiTimer_t *timer);
- /**
- * \brief start a timer
- *
- * Start a timer, and the timer will be expired in specified period from
- * now. After the callback is executed, the timer will come to stopped state
- * automatically.
- *
- * When the timer is in stated state before this function, the previous
- * expiration won't be executed.
- *
- * Refer to document about corner case of timer thread callback.
- *
- * It is valid that the timeout period is 0. In this case, the timer will
- * expire very soon.
- *
- * Due to timeout is 32bits of milliseconds, The maximum timeout period is
- * ~50 days.
- *
- * It is the same as \p osiTimerStartRelaxed, with \p relaxed_ms is 0.
- *
- * \param timer the timer to be started
- * \param ms timeout period
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStart(osiTimer_t *timer, uint32_t ms);
- /**
- * \brief start a timer with relaxed timeout
- *
- * It is a power optimization version of \p osiTimerStart.
- *
- * Refer to \p osiTimerChangeRelaxed for explaination of \p relaxed_ms.
- *
- * \param timer the timer to be started
- * \param ms normal timeout period
- * \param relax_ms relaxed timeout period
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStartRelaxed(osiTimer_t *timer, uint32_t ms, uint32_t relax_ms);
- /**
- * \brief start a timer, timeout in unit of microseconds
- *
- * Timeout in microseconds can support higher precision. However, the maximum
- * timeout is shorter, ~1.2 hours.
- *
- * The real precision depends on hardware.
- * \param timer the timer to be started
- * \param us timeout period in microseconds
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStartMicrosecond(osiTimer_t *timer, uint32_t us);
- /**
- * \brief start a periodic timer
- *
- * Internally, the period may be aligned to hardware tick (larger than
- * 16384Hz), there may exist accumulated error in long run. So, don't use
- * periodic timer count for long time time, \p osiUpTime is a better choice.
- *
- * When the period of periodic timer is too small, it will have serious impact
- * on system. Internally, the period taking effect will no less than
- * \p CONFIG_KERNEL_PERIODIC_TIMER_MIN_PERIOD.
- *
- * It is the same as \p osiTimerStartPeriodicRelaxed, with \p relaxed_ms is 0.
- *
- * \param timer the timer to be started
- * \param ms interval in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStartPeriodic(osiTimer_t *timer, uint32_t ms);
- /**
- * \brief start a periodic timer with relaxed timeout
- *
- * It is a power optimization version of \p osiTimerStartPeriodic.
- *
- * Refer to \p osiTimerChangeRelaxed for explaination of \p relaxed_ms.
- *
- * \param timer the timer to be started
- * \param ms interval in milliseconds
- * \param relaxed_ms relaxed timeout period
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStartPeriodicRelaxed(osiTimer_t *timer, uint32_t ms, uint32_t relaxed_ms);
- /**
- * \brief stop a time
- *
- * Stop a not-started or stopped timer is valid, just do nothing.
- *
- * Refer to document about corner case of timer thread callback.
- *
- * \param timer the timer to be stopped
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiTimerStop(osiTimer_t *timer);
- /**
- * create a message queue
- *
- * \param msg_count maximum message count can be hold in queue
- * \param msg_size size of each message in bytes
- * \return
- * - message queue pointer
- * - NULL on invalid parameter or out of memory
- */
- osiMessageQueue_t *osiMessageQueueCreate(uint32_t msg_count, uint32_t msg_size);
- /**
- * delete a message queue
- *
- * When \p mq is NULL, nothing will be done, just as \p free.
- *
- * \param mq message queue pointer
- */
- void osiMessageQueueDelete(osiMessageQueue_t *mq);
- /**
- * put a message to message queue
- *
- * \p msg should hold content size the same as \p msg_size specified at
- * \p osiMessageQueueCreate.
- *
- * After put, the content of \p msg will be copied to message queue.
- *
- * When \p mq is full, it will be blocked until there are rooms.
- *
- * This can be called in ISR. And in ISR, it will return false when queue
- * is full, and not wait.
- *
- * \param mq message queue pointer
- * \param msg mesage pointer
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiMessageQueuePut(osiMessageQueue_t *mq, const void *msg);
- /**
- * put a message to message queue with timeout
- *
- * This can be called in ISR. And in ISR, \p timeout will be ignored.
- *
- * \param mq message queue pointer
- * \param msg mesage pointer
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter or timeout
- */
- bool osiMessageQueueTryPut(osiMessageQueue_t *mq, const void *msg, uint32_t timeout);
- /**
- * get a message to message queue
- *
- * \p msg should be able tp hold content size of \p msg_size specified at
- * \p osiMessageQueueCreate.
- *
- * After get, the content of message will be copied to \p msg.
- *
- * When \p mq is empty, it will be blocked until there are messages.
- *
- * This can be called in ISR. And in ISR, it will return false when queue
- * is empty, and not wait.
- *
- * \param mq message queue pointer
- * \param msg mesage pointer
- * \return
- * - true on success
- * - false on invalid parameter
- */
- bool osiMessageQueueGet(osiMessageQueue_t *mq, void *msg);
- /**
- * get a message to message queue with timeout
- *
- * This can be called in ISR. And in ISR, \p timeout will be ignored.
- *
- * \param mq message queue pointer
- * \param msg mesage pointer
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on invalid parameter or timeout
- */
- bool osiMessageQueueTryGet(osiMessageQueue_t *mq, void *msg, uint32_t timeout);
- /**
- * get the pending message count in message queue
- *
- * It can be called in both thread context and ISR context.
- *
- * \param mq message queue pointer
- * \return
- * - the pending message count in message queue
- * - 0 on invalid parameter
- */
- uint32_t osiMessageQueuePendingCount(osiMessageQueue_t *mq);
- /**
- * get the space of message count in message queue
- *
- * It can be called in both thread context and ISR context.
- *
- * \param mq message queue pointer
- * \return
- * - the space of message count in message queue
- * - 0 on invalid parameter
- */
- uint32_t osiMessageQueueSpaceCount(osiMessageQueue_t *mq);
- /**
- * create a semaphore
- *
- * When \p max_count is 1, it is a binary semaphore. Otherwise, it is
- * counting semaphore.
- *
- * \param max_count maximum count of the semaphore
- * \param init_count initial count of the semaphore
- * \return
- * - semaphore pointer
- * - NULL on invalid parameter or out of memory
- */
- osiSemaphore_t *osiSemaphoreCreate(uint32_t max_count, uint32_t init_count);
- /**
- * delete the semaphore
- *
- * When there are blocked thread on the semaphore, the behavior is undefined
- * for \p osiSemaphoreDelete.
- *
- * \param semaphore semaphore pointer
- */
- void osiSemaphoreDelete(osiSemaphore_t *semaphore);
- /**
- * acquire from semaphore
- *
- * After acquire, the count of semaphore will be decreased by 1.
- *
- * When the count of semaphore is 0, it will be blocked until the count
- * becomes non-zero (increased by \p osiSemaphoreRelease).
- *
- * This can be called in ISR. And in ISR, it will return false when
- * semaphore is unavailable, and not wait.
- *
- * \param semaphore semaphore pointer
- * \return
- * - true on success
- * - false on invalid parameter, or unavailable in ISR
- */
- bool osiSemaphoreAcquire(osiSemaphore_t *semaphore);
- /**
- * acquire from semaphore with timeout
- *
- * This can be called in ISR. And in ISR, \p timeout will be ignored.
- *
- * \param semaphore semaphore pointer
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on timeout
- */
- bool osiSemaphoreTryAcquire(osiSemaphore_t *semaphore, uint32_t timeout);
- /**
- * release to semaphore
- *
- * After release, the count of semaphore will be increased by 1.
- * When there are blocked thread on the semaphore, one of the blocked
- * thread will be unblocked.
- *
- * This can be called in ISR.
- *
- * \param semaphore semaphore pointer
- */
- void osiSemaphoreRelease(osiSemaphore_t *semaphore);
- /**
- * create a mutex
- *
- * After creation, the mutex is in *open* state.
- *
- * \return
- * - mutex pointer
- * - NULL on out of memory
- */
- osiMutex_t *osiMutexCreate(void);
- /**
- * delete the mutex
- *
- * When \p mutex is NULL, nothing will be done, just as \p free.
- *
- * \param mutex mutex pointer to be deleted
- */
- void osiMutexDelete(osiMutex_t *mutex);
- /**
- * lock the mutex
- *
- * When \p mutex is locked by another thread, it will wait forever
- * until the mutex is unlocked.
- *
- * It **can't** be called in ISR. And in ISR, it will return directly.
- *
- * \param mutex mutex pointer to be locked
- */
- void osiMutexLock(osiMutex_t *mutex);
- /**
- * lock the mutex with timeout
- *
- * It **can't** be called in ISR. And in ISR, it will return false directly.
- *
- * \param mutex mutex pointer to be locked
- * \param timeout timeout in milliseconds
- * \return
- * - true on success
- * - false on timeout
- */
- bool osiMutexTryLock(osiMutex_t *mutex, uint32_t timeout);
- /**
- * unlock the mutex
- *
- * It **can't** be called in ISR. And in ISR, it will return directly.
- *
- * \param mutex mutex pointer to be unlocked
- */
- void osiMutexUnlock(osiMutex_t *mutex);
- /**
- * \brief monoclinic system time
- *
- * It is a relative time from system boot. Even after suspend and resume,
- * the monoclinic system time will be contiguous.
- *
- * At PSM wakeup (if supported), it is not contiguous.
- *
- * \return monoclinic system time in milliseconds
- */
- int64_t osiUpTime(void);
- /**
- * \brief monoclinic system time in microsecond
- *
- * The monoclinic system time in unit of microsecond.
- *
- * \return monoclinic system time in microseconds
- */
- int64_t osiUpTimeUS(void);
- /**
- * \brief set monoclinic system time
- *
- * When it is known that the hardware resource for monoclinic system time
- * is discontinued, such as power off during deep sleep, this is called to
- * set monoclinic system time.
- *
- * When up time is changed, epoch time and local time aren't be changed.
- *
- * It should only be called in system integration.
- *
- * \param ms target monoclinic system time in milliseconds
- */
- void osiSetUpTime(int64_t ms);
- /**
- * \brief set monoclinic system time
- *
- * When it is known that the hardware resource for monoclinic system time
- * is discontinued, such as power off during deep sleep, this is called to
- * set monoclinic system time.
- *
- * When up time is changed, epoch time and local time aren't be changed.
- *
- * It should only be called in system integration.
- *
- * \param us target monoclinic system time in microseconds
- */
- void osiSetUpTimeUS(int64_t us);
- /**
- * \brief get the epoch time
- *
- * The time is millisecond (1/1000 second) from 1970-01-01 UTC. To avoid
- * overflow, the data type is 64 bits.
- *
- * Epoch time is not monoclinic time. For example, when system time is
- * synchronized with network, there may exist a jump (forward or backward)
- * of epoch time.
- *
- * In 2 cases, this system time may be not reliable:
- * - During boot, and before RTC is initialized.
- * - During wakeup, and the elapsed sleep time hasn't compensated.
- *
- * \return epoch time in milliseconds
- */
- int64_t osiEpochTime(void);
- /**
- * \brief get the epoch time in second
- *
- * The time is seconds from 1970-01-01 UTC. To avoid overflow, the data
- * type is 64 bits.
- * - signed 32bits will overflow at year 2038
- * - unsigned 32bits will overflow at year 2106
- *
- * Epoch time is not monoclinic time. For example, when system time is
- * synchronized with network, there may exist a jump (forward or backward)
- * of epoch time.
- *
- * In 2 cases, this system time may be not reliable:
- * - During boot, and before RTC is initialized.
- * - During wakeup, and the elapsed sleep time hasn't compensated.
- *
- * \return epoch time in seconds
- */
- int64_t osiEpochSecond(void);
- /**
- * \brief set the monoclinic system time
- *
- * After the system time is changed, RTC won't be updated automatically.
- * It is needed to call RTC API to sync system time to RTC.
- *
- * When epoch time is changed, the monoclilinc system up time isn't changed,
- * and local time is changed correspondingly. The delta bewteen epoch time
- * and local time is only affected by timezone.
- *
- * \param ms epoch time in milliseconds
- *
- * \return true on succeed else fail
- */
- bool osiSetEpochTime(int64_t ms);
- /**
- * \brief set the monoclinic system time
- *
- * After the system time is changed, RTC won't be updated automatically.
- * It is needed to call RTC API to sync system time to RTC.
- *
- * When epoch time is changed, the monoclilinc system up time isn't changed,
- * and local time is changed correspondingly. The delta bewteen epoch time
- * and local time is only affected by timezone.
- *
- * \param us epoch time in microseconds
- *
- * \return true on succeed else fail
- */
- bool osiSetEpochTimeUS(int64_t us);
- /**
- * \brief get time zone in second
- *
- * Time zone is the offset between local time and epoch time:
- * local_time = epoch_time + time_zone
- *
- * OSI won't keep time zone at power off. Other module should store
- * time zone in NVRAM, and set to OSI at boot.
- *
- * \return time zone in second
- */
- int osiTimeZoneOffset(void);
- /**
- * \brief set time zone in second
- *
- * Time zone is the offset between local time and epoch time:
- * local_time = epoch_time + time_zone
- *
- * Time zone should be in [-12*3600, 12*3600]. However, it is not checked
- * inside this. The caller should make sure the \p offset is reasonable.
- *
- * \param offset time zone in second
- */
- void osiSetTimeZoneOffset(int offset);
- /**
- * \brief get the local time
- *
- * It is just: epoch_time + time_zone
- *
- * \return local time in milliseconds
- */
- int64_t osiLocalTime(void);
- /**
- * \brief get the local time in seconds
- *
- * It is just: epoch_time + time_zone
- *
- * \return local time in seconds
- */
- int64_t osiLocalSecond(void);
- /**
- * \brief convert epoch time to up time
- *
- * When some values has special meanings, such as INT64_MAX means invalid or not
- * exist, caller should check special values before call this.
- *
- * \param epoch epoch time in milliseconds
- * \return up time in milliseconds
- */
- int64_t osiEpochToUpTime(int64_t epoch);
- /**
- * \brief start counting of elsapsed timer
- *
- * \param timer elapsed timer, must be valid
- */
- void osiElapsedTimerStart(osiElapsedTimer_t *timer);
- /**
- * \brief elapsed milliseconds after start
- *
- * \param timer elapsed timer, must be valid
- * \return
- * - elapsed milliseconds after start
- */
- uint32_t osiElapsedTime(osiElapsedTimer_t *timer);
- /**
- * \brief elapsed microseconds after start
- *
- * \param timer elapsed timer, must be valid
- * \return
- * - elapsed microseconds after start
- */
- uint32_t osiElapsedTimeUS(osiElapsedTimer_t *timer);
- /**
- * \brief convert uptime to epoch time
- *
- * When some values has special meanings, such as INT64_MAX means invalid or not
- * exist, caller should check special values before call this.
- *
- * \param uptime up time in milliseconds
- * \return epoch time in milliseconds
- */
- int64_t osiUpTimeToEpoch(int64_t uptime);
- /**
- * \brief PM source callbacks
- *
- * All the callbacks are called with interrupt disabled. So, it is not
- * needed to call \p osiEnterCritical or \p osiIrqSave for protection.
- * And it is not error to call them.
- *
- * Don't call blocking API in the callback.
- */
- typedef struct osiPmSourceOps
- {
- void (*suspend)(void *ctx, osiSuspendMode_t mode); ///< callback to be called before suspend
- void (*resume)(void *ctx, osiSuspendMode_t mode, uint32_t source); ///< callback to be called after resume
- bool (*prepare)(void *ctx); ///< callback to be called at suspend check
- void (*prepare_abort)(void *ctx); ///< callback to be called at suspend check fail
- } osiPmSourceOps_t;
- /**
- * PM source opaque data struct
- */
- typedef struct osiPmSource osiPmSource_t;
- /**
- * \brief power management module initialization
- *
- * It should be called in early stage of boot, due to many other modules
- * may register suspend and resume callback at initialization.
- */
- void osiPmInit(void);
- /**
- * \brief power management core start
- *
- * To avoid suspend too early, PM core won't be started at initialization
- * automatically. After system is initialized, and necessary PM sources
- * are created, \p osiPmStart shall be called.
- *
- * Only after \p osiPmStart is called, PM core will check and enter suspend.
- */
- void osiPmStart(void);
- /**
- * \brief power management core stop
- *
- * Stop PM core, and systen will never suspend.
- *
- * It is only for debug. And it shouldn't be used in real application.
- */
- void osiPmStop(void);
- /**
- * \brief create PM source
- *
- * Modules are distinguished by FOURCC *tag*. So, tag should be unique
- * system wise.
- *
- * When the *tag* is already registered, it will return existed PM source.
- *
- * \p ops is permitted to be NULL, and all callbacks inside it are permitted
- * to be NULL.
- *
- * Resume callbacks are called in create order, suspend callbacks are called
- * in revered order. When resume order does matter, call \p osiPmResumeReorder
- * or \p osiPmResumeFirst to change resume order.
- *
- * The returned pointer should be destroyed and freed by \p osiPmSourceDelete.
- *
- * PM source lock and unlock is binary. That is, there is no *counter* inside.
- * When \p osiPmWakeUnlock is called, the PM source won't prevent system
- * suspend, no matter how many times of \p osiPmWakeLock is called.
- *
- * \param tag module tag
- * \param ops callbacks during suspend and resume
- * \param ctx callback context, shared by all callbacks
- * \return
- * - PM source pointer
- * - NULL on out of memory
- */
- osiPmSource_t *osiPmSourceCreate(uint32_t tag, const osiPmSourceOps_t *ops, void *ctx);
- /**
- * \brief destroy PM source
- *
- * \param ps PM source
- */
- void osiPmSourceDelete(osiPmSource_t *ps);
- /**
- * \brief ensure resume callback order
- *
- * In cases that the resume callback order is important, this API will check
- * and change resume callback order if needed. After the call, the resumed
- * order is ensured.
- *
- * When resume callback order is changed, suspend callback order is changed
- * also.
- *
- * It won't be checked whether the tags are valid.
- *
- * \param tag_later module tag to be resumed laster
- * \param tag_earlier module tag to be resumed earlier
- */
- void osiPmResumeReorder(uint32_t tag_later, uint32_t tag_earlier);
- /**
- * \brief move PM source to the first in resume order
- *
- * Find the PM source, and move it to the head of resume list. When PM source
- * with \p tag is not found in resume list, nothing will be done.
- *
- * \param tag module tag to be moved
- */
- void osiPmResumeFirst(uint32_t tag);
- /**
- * \brief wake lock to prevent suspend
- *
- * Indicate the PM source will prevent system suspend. PM source is *NOT*
- * counting, \p osiPmWakeLock will just set the PM source state. Multiple
- * calls of \p osiPmWakeLock is equivalent to a single call.
- *
- * When \p ops.prepare is not NULL, the internal state of PM source is
- * *suspend possible* rather than *active*. When system wants to
- * suspend, \p ops.prepare will be called to double check whether
- * suspend is permitted.
- *
- * \param ps PM source
- */
- void osiPmWakeLock(osiPmSource_t *ps);
- /**
- * \brief wake unlock to permit suspend
- *
- * Indicate the PM source won't prevent system suspend. PM source is *NOT*
- * counting. No matter how many calls of \p osiPmWakeLock are called,
- * \p osiPmWakeUnlock will set the PM source to unlock state.
- *
- * \param ps PM source
- */
- void osiPmWakeUnlock(osiPmSource_t *ps);
- /**
- * \brief set 32K sleep flag
- *
- * For platforms support both 32K sleep and suspend, the default sleep
- * mode is suspend. When it is needed to use 32K sleep forcedly, it is
- * needed to call this API.
- *
- * Each bit of \p flag represents a request source. When there are any
- * 32K sleep requests, system will use 32K sleep rather than suspend.
- *
- * The 32K sleep request sources depend on platform. And they are
- * defined in platform dependent hal_chip.h.
- *
- * \param flag 32K sleep request flag
- */
- void osiSet32KSleepFlag(uint32_t flag);
- /**
- * \brief clear 32K sleep flag
- *
- * \param flag 32K sleep request flag
- */
- void osiClear32KSleepFlag(uint32_t flag);
- /**
- * \brief register a shutdown callback
- *
- * When the callback and context is already registered, it will return
- * false.
- *
- * The order to invoke callbacks is undefined.
- *
- * *Don't* call \p osiRegisterShutdownCallback or
- * \p osiUnregisterShutdownCallback inside the callbacks.
- *
- * \param cb shutdown callback to be registered, can't be NULL
- * \param ctx shutdown callback context
- * \return
- * - true if callback registered
- * - false if callback is already registered, or callback is NULL
- */
- bool osiRegisterShutdownCallback(osiShutdownCallback_t cb, void *ctx);
- /**
- * \brief unregister a shutdown callback
- *
- * \param cb shutdown callback to be unregistered, can't be NULL
- * \param ctx shutdown callback context
- * \return
- * - true if callback unregistered
- * - false if callback isn't found
- */
- bool osiUnregisterShutdownCallback(osiShutdownCallback_t cb, void *ctx);
- /**
- * \brief set PSM sleep ready
- *
- * \param start_time the start time of psm request, in uptime
- * \param sleep_time psm sleep time
- */
- void osiSetPsmSleepReady(int64_t start_time, int64_t sleep_time);
- /**
- * \brief set PSM sleep not ready
- */
- void osiSetPsmSleepNotReady(void);
- /**
- * \brief whether PSM sleep is ready
- *
- * \return
- * - true if PSM sleep is ready
- * - false if PSM sleep is not ready
- */
- bool osiIsPsmSleepReady(void);
- /**
- * \brief get PSM elapsed time in milliseconds
- *
- * The elapsed time is starting from \p start_time parameter of
- * \p osiSetPsmSleepReady.
- *
- * \return
- * - PSM elsapsed time
- * - 0 if PSM is not ready
- */
- int64_t osiGetPsmElapsedTime(void);
- /**
- * \brief get cp deep sleep time in milliseconds
- *
- * \return cp deep sleep time
- */
- uint64_t osiCpDeepSleepTime(void);
- /**
- * \brief shutdown to specified mode
- *
- * When parameter is wrong, it will return false:
- * - When \p mode is OSI_SHUTDOWN_PSM_SLEEP, and PSM isn't enabled.
- * Caller should check whether PSM is enabled before calling
- * \p osiShutdown.
- * - When \p mode is not supported in the platform.
- *
- * It never return true.
- *
- * \param mode shutdown mode
- * \return
- * - false on parameter error
- */
- bool osiShutdown(osiShutdownMode_t mode);
- /**
- * \brief get boot causes
- *
- * It is possible there are multiple boot causes. The returned value is
- * bit or of all boot causes.
- *
- * It is possible hardware registers will be cleared after accessed. So,
- * always call \p osiGetBootCauses to get the boot causes, rather than
- * accessing hardware registers directly.
- *
- * \return boot causes
- */
- uint32_t osiGetBootCauses(void);
- /**
- * \brief set a boot cause
- *
- * It is intended only for system integration.
- *
- * \param cause boot cause
- */
- void osiSetBootCause(osiBootCause_t cause);
- /**
- * \brief clear a boot cause
- *
- * It is intended only for system integration.
- *
- * \param cause boot cause
- */
- void osiClearBootCause(osiBootCause_t cause);
- /**
- * \brief get boot mode
- *
- * \return boot mode
- */
- osiBootMode_t osiGetBootMode(void);
- /**
- * \brief set boot mode
- *
- * It is intended only for system integration. At calling, caller should
- * take care conflict of other boot mode detection.
- *
- * \param mode boot mode
- */
- void osiSetBootMode(osiBootMode_t mode);
- /**
- * \brief PSM restore
- *
- * It should be called in system initialization, after file system
- * initialization.
- */
- void osiPsmRestore(void);
- /**
- * \brief save PSM data
- *
- * PSM data save is implemented in platform. PSM data should be saved in
- * persistent storage, which can be flash or aon memory. Caller shouldn't
- * assume the storage type.
- *
- * It should only be called in \p osiShutdown callbacks.
- *
- * For each owner, \p osiPsmDataSave shall be called only once at most.
- *
- * It is recommended to use fixed size buffer, which is the same at each
- * PSM shutdown. However, variable size buffer is also supported.
- *
- * As a special case, \p size of 0 is permitted. It just keep record that
- * the owner is saved without real data.
- *
- * \param owner PSM data owner
- * \param buf owner's PSM data buffer
- * \param size owner's PSM data buffer size
- * \return
- * - true on success
- * - false on fail
- * - duplicated owner
- * - out of memory
- */
- bool osiPsmDataSave(osiPsmDataOwner_t owner, const void *buf, uint32_t size);
- /**
- * \brief restore PSM data
- *
- * Restore PSM data. At PSM resume boot, PSM data owner calls this to get
- * the data saved by \p osiPsmDataSave
- *
- * The buffer size should be equal or larger than the saved size. If it is
- * smaller than saved size, return -1.
- *
- * When \p buf is NULL, it will return PSM data size without copy. It can
- * be used to get the PSM data size.
- *
- * \param owner PSM data owner
- * \param buf buffer for owner's PSM data
- * \param size buffer size
- * \return
- * - PSM data size on success
- * - 0 if there are no PSM data
- * - -1 on error
- */
- int osiPsmDataRestore(osiPsmDataOwner_t owner, void *buf, uint32_t size);
- /**
- * send out debug event to trace tool
- *
- * If system and trace tool support debug event, this will send
- * a word to trace tool.
- *
- * It should be only used in quick debug. It is possible that platform
- * can't support debug event, and debug event output may be turned off
- * by compiling option.
- *
- * It is possible that debughost may be blocked. And then debughost event
- * sent will timeout.
- *
- * NOTE: Debug event output will take times. For example, when debug host
- * baud rate is 921600, it may take up to 109us. And when debughost is
- * blocked, it may take 200us for timeout.
- *
- * \param event word which will appear on trace tool
- * \return
- * - true if the event is sent
- * - false if the event sent timeout
- */
- bool osiDebugEvent(uint32_t event);
- /**
- * panic
- *
- * Called on fatal error, and system can't go on.
- *
- * It is different from \p assert. It will always cause system panic,
- * and there are no compiling option to ignore it.
- */
- void osiPanic(void);
- /**
- * panic with specified address
- *
- * It is the same as \p osiPanic, except \p address is shown in log,
- * rather than the return address of caller.
- */
- void osiPanicAt(void *address);
- /**
- * panic with no_return keyword
- *
- * Called on fatal error, and system can't go on.
- *
- * It is used for posix API, eg exit and abort
- */
- OSI_NO_RETURN void osiPanicPosix(void);
- /**
- * whether system is in panic mode
- *
- * In panic mode, system will still run a small daemon. And there is no
- * interrupt in panic mode. So, features used in panic daemon shall take
- * care of this.
- *
- * \return
- * - true if system is in panic mode
- * - false if system is not in panic mode
- */
- bool osiIsPanic(void);
- /**
- * register enter and polling callback at blue screen mode
- *
- * The maximum panic handler is pre-configured.
- *
- * \param enter callback to be caled when entering panic mode
- * \param poll callback to be caled when during panic mode
- * \param param callback parameter
- * \return
- * - true on success
- * - false on fail, invalid paramters or too many handlers
- */
- bool osiRegisterBlueScreenHandler(osiCallback_t enter, osiCallback_t poll, void *param);
- /**
- * optional assert
- *
- * It is a macro. When \p CONFIG_KERNEL_ASSERT_ENABLED is defined, it will
- * panic when \p expect_true is not true. When \p CONFIG_KERNEL_ASSERT_ENABLED
- * is not defined, it will be expanded as empty.
- *
- * \p info is just a remainder in source code. It won't be used.
- */
- #ifdef CONFIG_KERNEL_ASSERT_ENABLED
- #define OSI_ASSERT(expect_true, info) OSI_DO_WHILE0(if (!(expect_true)) osiPanic();)
- #else
- #define OSI_ASSERT(expect_true, info)
- #endif
- /**
- * busy loop delay
- *
- * The precision of delay depends on platform. And it will ensure to delay
- * at least the specified time.
- *
- * \param us delay time in microseconds
- */
- OSI_NO_MIPS16 void osiDelayUS(uint32_t us);
- /**
- * delay by CPU loop
- *
- * The absolute delay time depends on CPU frequency. \p count is the loop
- * count, not the delayed instruction count.
- *
- * \param count delay loop count
- */
- void osiDelayLoops(uint32_t count);
- /**
- * call function with specified stack
- *
- * This will only be called with low level codes, and most likely, it is not
- * needed for application.
- *
- * This function is located in SRAM. So, it can be called even the external
- * RAM in unavailable.
- *
- * \p function shall have 2 parameters at most. It can return one word. When
- * \p function doesn't return value, the return value of this wrapper is
- * undefined.
- *
- * \p sp should be 8 bytes aligned.
- *
- * \param sp the stack to be used for \p function
- * \param function the real function
- * \param param0 the first parameter for \p function
- * \param param1 the second parameter for \p function
- * \return
- * - the return value of \p function
- */
- uint32_t osiCallWithStack(void *sp, void *function, uint32_t param0, uint32_t param1);
- #ifdef __cplusplus
- }
- #endif
- #endif
|