xos.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /** @file */
  2. // xos.h - XOS API interface and data structures visible to user code.
  3. // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining
  6. // a copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to
  10. // permit persons to whom the Software is furnished to do so, subject to
  11. // the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included
  14. // in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. #ifndef __XOS_H__
  24. #define __XOS_H__
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28. #include "xos_types.h"
  29. #include <xtensa/config/core.h>
  30. #if XCHAL_HAVE_INTERRUPTS
  31. #include <xtensa/tie/xt_core.h>
  32. #include <xtensa/tie/xt_interrupt.h>
  33. #endif
  34. #include "xos_common.h"
  35. #include "xos_errors.h"
  36. #include "xos_regaccess.h"
  37. //-----------------------------------------------------------------------------
  38. // Convert x into a literal string.
  39. //-----------------------------------------------------------------------------
  40. #define _XOS_STR(x) __XOS_STR(x)
  41. #define __XOS_STR(x) #x
  42. //-----------------------------------------------------------------------------
  43. // XOS version.
  44. //-----------------------------------------------------------------------------
  45. #define XOS_VERSION_MAJOR 1
  46. #define XOS_VERSION_MINOR 10
  47. #define XOS_VERSION_STRING "1.10" ///< XOS version string.
  48. //-----------------------------------------------------------------------------
  49. // Runtime error handling.
  50. //-----------------------------------------------------------------------------
  51. //-----------------------------------------------------------------------------
  52. ///
  53. /// Reports a fatal error and halts XOS operation, i.e. halts the system. This
  54. /// function will call a user-registered error handler (if one has been set)
  55. /// and then halt the system. The user handler may do system-specific things
  56. /// such as record the error reason in nonvolatile memory etc.
  57. ///
  58. /// \param errcode Error code. May be any user defined value < 0.
  59. /// Values >=0 are reserved for use by the system.
  60. ///
  61. /// \param errmsg Optional text string describing the error.
  62. ///
  63. /// \return This function does not return.
  64. ///
  65. //-----------------------------------------------------------------------------
  66. void
  67. xos_fatal_error(int32_t errcode, const char * errmsg);
  68. #if XOS_DEBUG
  69. // Do not call directly.
  70. void
  71. xos_assert(const char * file, int32_t line);
  72. //-----------------------------------------------------------------------------
  73. ///
  74. /// Check condition and fail if condition expression is false.
  75. /// In debug builds, an assertion failure will cause a fatal error to be
  76. /// reported. In non-debug builds, assertions are compiled out.
  77. ///
  78. /// NOTE: Remember that any code in XOS_ASSERT() statements gets compiled out
  79. /// for non-debug builds.
  80. ///
  81. //-----------------------------------------------------------------------------
  82. #define XOS_ASSERT(expr) if ((expr) == 0) xos_assert(__FILE__, __LINE__)
  83. #else
  84. #define XOS_ASSERT(expr)
  85. #endif
  86. //-----------------------------------------------------------------------------
  87. ///
  88. /// Interrupt handler function pointer type.
  89. ///
  90. //-----------------------------------------------------------------------------
  91. typedef void (XosIntFunc)(void * arg);
  92. //-----------------------------------------------------------------------------
  93. ///
  94. /// Print handler function pointer type.
  95. ///
  96. //-----------------------------------------------------------------------------
  97. typedef int32_t (XosPrintFunc)(void * arg, const char * fmt, ...);
  98. //-----------------------------------------------------------------------------
  99. ///
  100. /// Fatal error handler function pointer type.
  101. ///
  102. //-----------------------------------------------------------------------------
  103. typedef void (XosFatalErrFunc)(int32_t errcode, const char * errmsg);
  104. //-----------------------------------------------------------------------------
  105. ///
  106. /// Exception handler function pointer type.
  107. ///
  108. //-----------------------------------------------------------------------------
  109. typedef void (XosExcHandlerFunc)(XosExcFrame * frame);
  110. //-----------------------------------------------------------------------------
  111. ///
  112. /// Install a user defined exception handler for the specified exception type.
  113. /// This will override the default XOS exception handler. The handler is a C
  114. /// function that is passed one parameter -- a pointer to the exception frame.
  115. /// The exception frame is allocated on the stack of the thread that caused the
  116. /// exception, and contains saved state and exception information. For details
  117. /// of the exception frame see the structure XosExcFrame.
  118. ///
  119. /// \param exc Exception type (number) to override. The exception
  120. /// numbers are enumerated in <xtensa/corebits.h>.
  121. ///
  122. /// \param handler Pointer to handler function to be installed.
  123. /// To revert to the default handler, pass NULL.
  124. ///
  125. /// \return Returns a pointer to previous handler installed, if any.
  126. ///
  127. //-----------------------------------------------------------------------------
  128. XosExcHandlerFunc *
  129. xos_register_exception_handler(int32_t exc, XosExcHandlerFunc * handler);
  130. //-----------------------------------------------------------------------------
  131. ///
  132. /// Install a user defined fatal error handler. This function will be called if
  133. /// a fatal error is reported either by user code or by XOS itself. It will be
  134. /// passed the same arguments that are passed to xos_fatal_error().
  135. ///
  136. /// The handler need not return. It should make minimal assumptions about the
  137. /// state of the system. In particular, it should not assume that further XOS
  138. /// system calls will succeed.
  139. ///
  140. /// \param handler Pointer to handler function to be installed.
  141. ///
  142. /// \return Returns a pointer to previous handler installed, if any.
  143. ///
  144. //-----------------------------------------------------------------------------
  145. XosFatalErrFunc *
  146. xos_register_fatal_error_handler(XosFatalErrFunc * handler);
  147. #ifdef _XOS_INCLUDE_INTERNAL_
  148. # include "xos_internal.h"
  149. #endif
  150. #include "xos_thread.h"
  151. #include "xos_timer.h"
  152. #include "xos_cond.h"
  153. #include "xos_event.h"
  154. #include "xos_mutex.h"
  155. #include "xos_msgq.h"
  156. #include "xos_semaphore.h"
  157. #include "xos_stopwatch.h"
  158. //-----------------------------------------------------------------------------
  159. ///
  160. /// Register a handler function to call when interrupt "num" occurs.
  161. ///
  162. /// For level-triggered and timer interrupts, the handler function will have
  163. /// to clear the source of the interrupt before returning, to avoid infinitely
  164. /// retaking the interrupt. Edge-triggered and software interrupts are
  165. /// automatically cleared by the OS interrupt dispatcher (see xos_handlers.S).
  166. ///
  167. /// \param num Xtensa internal interrupt number (0..31). To
  168. /// refer to a specific external interrupt number
  169. /// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM
  170. /// where 'x' is the external number.
  171. ///
  172. /// \param handler Pointer to handler function.
  173. ///
  174. /// \param arg Argument passed to handler.
  175. ///
  176. /// \return Returns XOS_OK if successful, else error code.
  177. ///
  178. //-----------------------------------------------------------------------------
  179. int32_t
  180. xos_register_interrupt_handler(int32_t num, XosIntFunc * handler, void * arg);
  181. //-----------------------------------------------------------------------------
  182. ///
  183. /// Unregister a handler function for interrupt "num". If no handler was
  184. /// installed, this function will have no effect.
  185. ///
  186. /// \param num Xtensa internal interrupt number (0..31). To
  187. /// refer to a specific external interrupt number
  188. /// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM
  189. /// where 'x' is the external number.
  190. ///
  191. /// \return Returns XOS_OK if successful, else error code.
  192. ///
  193. //-----------------------------------------------------------------------------
  194. int32_t
  195. xos_unregister_interrupt_handler(int32_t num);
  196. //-----------------------------------------------------------------------------
  197. ///
  198. /// Register a high priority interrupt handler for interrupt level "level".
  199. ///
  200. /// Unlike low and medium priority interrupt handlers, high priority handlers
  201. /// are not installed for a specific interrupt number, but for an interrupt
  202. /// level. The level must be above XCHAL_EXCM_LEVEL. The handler function must
  203. /// be written in assembly since C handlers are not supported for levels above
  204. /// XCHAL_EXCM_LEVEL. The handler function must preserve all registers except
  205. /// a0, and must return to the dispatcher via a "ret" instruction, not "rfi".
  206. ///
  207. /// NOTE: This method of dispatch takes a few cycles of overhead. If you wish
  208. /// to save even these cycles, then you can define your own dispatch function
  209. /// to override the built-in dispatcher. See xos_handlers.S for more details.
  210. ///
  211. /// \param level The interrupt level to be handled.
  212. ///
  213. /// \param handler Pointer to handler function.
  214. ///
  215. /// \return Returns XOS_OK if successful, else error code.
  216. ///
  217. //-----------------------------------------------------------------------------
  218. int32_t
  219. xos_register_hp_interrupt_handler(int32_t level, void * handler);
  220. //-----------------------------------------------------------------------------
  221. ///
  222. /// Enable a specific interrupt, by interrupt number.
  223. /// The state (enabled vs. disabled) of individual interrupts is global, i.e.
  224. /// not associated with any specific thread. Depending on system options and
  225. /// implementation, this state may be stored in one of two ways:
  226. /// - directly in the INTENABLE register, or
  227. /// - in a global variable (this is generally the case when INTENABLE is used
  228. /// not just to control what interrupts are enabled globally, but also for
  229. /// software interrupt prioritization within an interrupt level, effectively
  230. /// providing finer grained levels; in this case XOS takes care to update
  231. /// INTENABLE whenever either the global enabled-state variable or the
  232. /// per-thread fine-grained-level variable change).
  233. /// Thus it is best to never access the INTENABLE register directly.
  234. ///
  235. /// To modify thread-specific interrupt priority level, use one of:
  236. /// - xos_set_int_pri_level()
  237. /// - xos_restore_int_pri_level()
  238. /// - xos_disable_interrupts()
  239. /// - xos_restore_interrupts()
  240. ///
  241. /// NOTE: To refer to a specific external interrupt number (BInterrupt pin),
  242. /// use HAL macro XCHAL_EXTINTx_NUM where 'x' is the external interrupt
  243. /// number. For example, to enable external interrupt 3 (BInterrupt[3]),
  244. /// you can use:
  245. ///
  246. /// xos_interrupt_enable( XCHAL_EXTINT3_NUM );
  247. ///
  248. /// \param intnum Interrupt number to enable. Must range between 0-31.
  249. ///
  250. /// \return Returns nothing.
  251. ///
  252. //-----------------------------------------------------------------------------
  253. void
  254. xos_interrupt_enable(uint32_t intnum);
  255. //-----------------------------------------------------------------------------
  256. ///
  257. /// Disable a specific individual interrupt, by interrupt number.
  258. ///
  259. /// This is the counterpart to xos_interrupt_enable(). See the description
  260. /// of xos_interrupt_enable() for further comments and notes.
  261. ///
  262. /// \param intnum Interrupt number to disable. Must range between 0-31.
  263. ///
  264. /// \return Returns nothing.
  265. ///
  266. //-----------------------------------------------------------------------------
  267. void
  268. xos_interrupt_disable(uint32_t intnum);
  269. //-----------------------------------------------------------------------------
  270. ///
  271. /// Get the CPU's current interrupt priority level. Interrupts at or below this
  272. /// priority level are blocked.
  273. ///
  274. /// \return Returns the current IPL, ranging from 0 to XCHAL_NUM_INTLEVELS.
  275. ///
  276. //-----------------------------------------------------------------------------
  277. static inline uint32_t
  278. xos_get_int_pri_level(void)
  279. {
  280. #if XCHAL_HAVE_INTERRUPTS
  281. return XT_RSR_PS() & 0xF;
  282. #else
  283. return 0;
  284. #endif
  285. }
  286. //-----------------------------------------------------------------------------
  287. ///
  288. /// Set the CPU's interrupt priority level to the specified level, but only if
  289. /// the current IPL is below the one requested. This function will never cause
  290. /// the interrupt priority level to be lowered from the current level.
  291. /// Call this function to block interrupts at or below the specified priority
  292. /// level.
  293. ///
  294. /// When setting the IPL temporarily (such as in a critical section), call
  295. /// xos_set_int_pri_level(), execute the critical code section, and then call
  296. /// xos_restore_int_pri_level().
  297. ///
  298. /// The interrupt priority level is part of the thread context, so it is saved
  299. /// and restored across context switches. To enable and disable individual
  300. /// interrupts globally, use the functions xos_interrupt_enable() and
  301. /// xos_interrupt_disable() instead.
  302. ///
  303. /// NOTE: It is usually not required to disable interrupts at a level higher
  304. /// than that of the highest priority interrupt that interacts with the OS
  305. /// (i.e. calls into XOS such that threads may be woken / blocked /
  306. /// reprioritized / switched, or otherwise access XOS data structures).
  307. /// In XOS, that maximum level is XOS_MAX_OS_INTLEVEL, which defaults to
  308. /// XCHAL_EXCM_LEVEL. This may be modified by editing xos_params.h and
  309. /// rebuilding XOS.
  310. ///
  311. /// \param level The new interrupt priority level (IPL).
  312. ///
  313. /// \return Returns a value that can be used to restore the previous
  314. /// priority level by calling xos_restore_int_pri_level(). This
  315. /// value should be treated as opaque by application code, and
  316. /// should be passed unchanged to the restore function.
  317. ///
  318. //-----------------------------------------------------------------------------
  319. __attribute__((always_inline))
  320. static inline uint32_t
  321. xos_set_int_pri_level(uint32_t level)
  322. {
  323. #if XCHAL_HAVE_INTERRUPTS
  324. #pragma no_reorder
  325. uint32_t ps = XT_RSR_PS();
  326. if (level > (ps & 0xF)) {
  327. level = (ps & ~0xF) | level;
  328. XT_WSR_PS(level);
  329. XT_RSYNC();
  330. }
  331. return ps;
  332. #else
  333. return 0;
  334. #endif
  335. }
  336. //-----------------------------------------------------------------------------
  337. ///
  338. /// Restores the CPU to a previously saved interrupt priority level. This level
  339. /// must have been obtained by calling xos_set_int_pri_level().
  340. ///
  341. /// \param oldval Return value from xos_set_int_pri_level().
  342. ///
  343. /// \return Returns nothing.
  344. ///
  345. //-----------------------------------------------------------------------------
  346. __attribute__((always_inline))
  347. static inline void
  348. xos_restore_int_pri_level(const uint32_t oldval)
  349. {
  350. #if XCHAL_HAVE_INTERRUPTS
  351. #pragma no_reorder
  352. XT_WSR_PS(oldval);
  353. XT_RSYNC();
  354. #else
  355. // Nothing
  356. #endif
  357. }
  358. //-----------------------------------------------------------------------------
  359. ///
  360. /// Disable all interrupts that can interact directly with the OS. This is a
  361. /// convenience function, shorthand for setting the IPL to XOS_MAX_OS_INTLEVEL.
  362. ///
  363. /// Returns: A value that can be used to restore the previous priority level
  364. /// by calling xos_restore_interrupts(). This value should be treated as
  365. /// opaque by application code, and should be passed unchanged to the restore
  366. /// function.
  367. ///
  368. //-----------------------------------------------------------------------------
  369. static inline uint32_t
  370. xos_disable_interrupts(void)
  371. {
  372. return xos_set_int_pri_level(XOS_MAX_OS_INTLEVEL);
  373. }
  374. //-----------------------------------------------------------------------------
  375. ///
  376. /// Restore the CPU's previously saved interrupt status. This is a convenience
  377. /// function, the counterpart to xos_disable_interrupts().
  378. ///
  379. /// \return rval Return value from xos_disable_interrupts().
  380. ///
  381. /// \return Returns nothing.
  382. ///
  383. //-----------------------------------------------------------------------------
  384. static inline void
  385. xos_restore_interrupts(uint32_t rval)
  386. {
  387. xos_restore_int_pri_level(rval);
  388. }
  389. #ifdef _XOS_INCLUDE_INTERNAL_
  390. //-----------------------------------------------------------------------------
  391. // Enter an OS critical section, i.e. get exclusive access to OS critical
  392. // state and data structures. Code that manipulates the state of OS objects
  393. // or modifies internal OS state must call this function first, to ensure
  394. // that it has exclusive access. On a single-core system, this is equivalent
  395. // to blocking all interrupts that can interact directly with the OS, i.e.
  396. // all interrupts at or below XOS_MAX_OS_INTLEVEL. In a multi-core system
  397. // this is likely to be implemented differently to achieve the same effect.
  398. //
  399. // Returns: A value that is to be used to restore the state of the CPU when
  400. // exiting the critical section. This must be treated as opaque and passed
  401. // unmodified to xos_critical_exit().
  402. //
  403. // NOTE: This function is meant for use in OS code, not in applications.
  404. //-----------------------------------------------------------------------------
  405. __attribute__((always_inline))
  406. static inline uint32_t
  407. xos_critical_enter(void)
  408. {
  409. #if XCHAL_HAVE_INTERRUPTS
  410. // This function cannot be called by high-level interrupt handlers,
  411. // i.e. it can never be called with intlevel > XOS_MAX_OS_INTLEVEL.
  412. // So, we do not need to check current intlevel because we will not
  413. // ever be lowering it by setting it to XOS_MAX_OS_INTLEVEL.
  414. // NOTE: sync after RSIL not needed.
  415. return XT_RSIL(XOS_MAX_OS_INTLEVEL);
  416. #else
  417. return 0;
  418. #endif
  419. }
  420. //-----------------------------------------------------------------------------
  421. // Exit an OS critical section and restore CPU state. See the documentation
  422. // for xos_critical_enter().
  423. //
  424. // cflags Return value from xos_critical_enter().
  425. // Must be treated as an opaque value.
  426. //
  427. // Returns: Nothing.
  428. //
  429. // NOTE: This function is meant for use in OS code, not in applications.
  430. //-----------------------------------------------------------------------------
  431. __attribute__((always_inline))
  432. static inline void
  433. xos_critical_exit(uint32_t cflags)
  434. {
  435. xos_restore_int_pri_level(cflags);
  436. }
  437. #endif // _XOS_INCLUDE_INTERNAL_
  438. // This file uses things defined above
  439. #include "xos_syslog.h"
  440. // Misc
  441. //-----------------------------------------------------------------------------
  442. // Helper function to list all threads in system. Useful for debug.
  443. //-----------------------------------------------------------------------------
  444. void
  445. xos_display_threads(void * arg, XosPrintFunc * print_fn);
  446. #ifdef __cplusplus
  447. }
  448. #endif
  449. #endif // __XOS_H__