From fa8b45cc5be41840b99d4a5468108568f93513c1 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 3 Sep 2013 13:21:10 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6255 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/nil/include/nil.h | 305 ++++++++++++++------------- os/nil/ports/ARMCMx/compilers/GCC/niltypes.h | 6 + os/nil/ports/ARMCMx/nilcore.c | 15 -- os/nil/ports/ARMCMx/nilcore_v6m.c | 2 +- os/nil/ports/ARMCMx/nilcore_v6m.h | 19 +- os/nil/src/nil.c | 66 ++++-- 6 files changed, 222 insertions(+), 191 deletions(-) (limited to 'os/nil') diff --git a/os/nil/include/nil.h b/os/nil/include/nil.h index b98ea4ecf..6a831d880 100644 --- a/os/nil/include/nil.h +++ b/os/nil/include/nil.h @@ -43,39 +43,21 @@ */ #define _NIL_ /**< @brief Nil RTOS identification.*/ -#define NIL_KERNEL_VERSION "0.0.1" /**< @brief Kernel version string. */ +#define NIL_KERNEL_VERSION "0.1.0alpha" -#define NIL_KERNEL_MAJOR 0 /**< @brief Version major number. */ -#define NIL_KERNEL_MINOR 0 /**< @brief Version minor number. */ -#define NIL_KERNEL_PATCH 1 /**< @brief Version patch number. */ +#define NIL_KERNEL_MAJOR 0 +#define NIL_KERNEL_MINOR 1 +#define NIL_KERNEL_PATCH 0 /** @} */ /** - * @name Common constants - */ -/** - * @brief Generic 'false' boolean constant. - */ -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -/** - * @brief Generic 'true' boolean constant. - */ -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE !FALSE -#endif -/** @} */ - -/** - * @name Wakeup status codes + * @name Wakeup messages * @{ */ -#define NIL_MSG_OK 0 /**< @brief Normal wakeup message. */ -#define NIL_MSG_TMO -1 /**< @brief Wake-up caused by a timeout +#define MSG_OK 0 /**< @brief Normal wakeup message. */ +#define MSG_TIMEOUT -1 /**< @brief Wake-up caused by a timeout condition. */ -#define NIL_MSG_RST -2 /**< @brief Wake-up caused by a reset +#define MSG_RESET -2 /**< @brief Wake-up caused by a reset condition. */ /** @} */ @@ -295,7 +277,7 @@ typedef struct { * @note This field is only present if some debug options have been * activated. */ - const char *dbg_msg; + const char *dbg_panic_msg; #endif } nil_system_t; @@ -303,6 +285,11 @@ typedef struct { /* Module macros. */ /*===========================================================================*/ +/** + * @brief String quotation macro. + */ +#define __NIL_QUOTE(p) #p + /** * @name Threads tables definition macros * @{ @@ -325,18 +312,153 @@ typedef struct { #define NIL_THREADS_TABLE_END() \ {"idle", 0, NULL, NULL, 0} \ }; +/** @} */ +/** + * @name Working Areas and Alignment + */ +/** + * @brief Enforces a correct alignment for a stack area size value. + * + * @param[in] n the stack size to be aligned to the next stack + * alignment boundary + * @return The aligned stack size. + * + * @api + */ +#define THD_ALIGN_STACK_SIZE(n) \ + ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) + +/** + * @brief Calculates the total Working Area size. + * + * @param[in] n the stack size to be assigned to the thread + * @return The total used memory in bytes. + * + * @api + */ +#define THD_WORKING_AREA_SIZE(n) \ + THD_ALIGN_STACK_SIZE(sizeof(thread_t) + PORT_WA_SIZE(n)) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + * + * @api + */ +#define THD_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof(stkalign_t)] /** @} */ /** - * @name Macro Functions + * @name Threads abstraction macros + */ +/** + * @brief Thread declaration macro. + * @note Thread declarations should be performed using this macro because + * the port layer could define optimizations for thread functions. + */ +#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg) +/** @} */ + +/** + * @name ISRs abstraction macros + */ +/** + * @brief IRQ handler enter code. + * @note Usually IRQ handlers functions are also declared naked. + * @note On some architectures this macro can be empty. + * + * @special + */ +#define NIL_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ handler exit code. + * @note Usually IRQ handlers function are also declared naked. + * + * @special + */ +#define NIL_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE() + +/** + * @brief Standard normal IRQ handler declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + * + * @special + */ +#define NIL_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) +/** @} */ + +/** + * @name Fast ISRs abstraction macros + */ +/** + * @brief Standard fast IRQ handler declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + * @note Not all architectures support fast interrupts. + * + * @special + */ +#define NIL_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id) +/** @} */ + +/** + * @name Time conversion utilities * @{ */ /** - * @brief System halt state. + * @brief Seconds to system ticks. + * @details Converts from seconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] sec number of seconds + * @return The number of ticks. + * + * @api */ -#define nilSysHalt() port_halt() +#define S2ST(sec) \ + ((systime_t)((sec) * NIL_CFG_FREQUENCY)) +/** + * @brief Milliseconds to system ticks. + * @details Converts from milliseconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] msec number of milliseconds + * @return The number of ticks. + * + * @api + */ +#define MS2ST(msec) \ + ((systime_t)(((((uint32_t)(msec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\ + 1000UL) + 1UL)) + +/** + * @brief Microseconds to system ticks. + * @details Converts from microseconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] usec number of microseconds + * @return The number of ticks. + * + * @api + */ +#define US2ST(usec) \ + ((systime_t)(((((uint32_t)(usec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\ + 1000000UL) + 1UL)) +/** @} */ + +/** + * @name Macro Functions + * @{ + */ /** * @brief Enters the kernel lock mode. * @@ -525,139 +647,33 @@ typedef struct { #define nilTimeIsWithin(time, start, end) \ ((end) > (start) ? ((time) >= (start)) && ((time) < (end)) : \ ((time) >= (start)) || ((time) < (end))) -/** @} */ - -/** - * @name Threads abstraction macros - */ -/** - * @brief Thread declaration macro. - * @note Thread declarations should be performed using this macro because - * the port layer could define optimizations for thread functions. - */ -#define NIL_THREAD(tname, arg) PORT_THREAD(tname, arg) #if NIL_CFG_ENABLE_ASSERTS || defined(__DOXYGEN__) /** * @brief Condition assertion. - * @details If the condition check fails then the kernel panics with the - * specified message and halts. + * @details If the condition check fails then the kernel panics with a + * message and halts. * @note The condition is tested only if the @p NIL_CFG_ENABLE_ASSERTS - * switch is specified in @p nilconf.h else the macro does nothing. - * @note The convention for the message is the following:
- * @(), #@ + * switch is specified in @p chconf.h else the macro does nothing. * @note The remark string is not currently used except for putting a * comment in the code about the assertion. * * @param[in] c the condition to be verified to be true - * @param[in] m the text message * @param[in] r a remark string * * @api */ #if !defined(nilDbgAssert) -#define nilDbgAssert(c, m, r) { \ - if (!(c)) { \ - nil.dbg_msg = (m); \ - nilSysHalt(); \ - } \ +#define nilDbgAssert(c, r) { \ + if (!(c)) \ + nilSysHalt("A:"__NIL_QUOTE(__FUNCTION__)":"__NIL_QUOTE(__LINE__)); \ } -#endif /* !defined(chDbgAssert) */ +#endif /* !defined(nilDbgAssert) */ #else /* !NIL_CFG_ENABLE_ASSERTS */ -#define nilDbgAssert(c, m, r) {(void)(c);} +#define nilDbgAssert(c, r) /*{(void)(c);}*/ #endif /* !NIL_CFG_ENABLE_ASSERTS */ /** @} */ -/** - * @name ISRs abstraction macros - */ -/** - * @brief IRQ handler enter code. - * @note Usually IRQ handlers functions are also declared naked. - * @note On some architectures this macro can be empty. - * - * @special - */ -#define NIL_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE() - -/** - * @brief IRQ handler exit code. - * @note Usually IRQ handlers function are also declared naked. - * - * @special - */ -#define NIL_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE() - -/** - * @brief Standard normal IRQ handler declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - * - * @special - */ -#define NIL_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) -/** @} */ - -/** - * @name Fast ISRs abstraction macros - */ -/** - * @brief Standard fast IRQ handler declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - * @note Not all architectures support fast interrupts. - * - * @special - */ -#define NIL_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id) -/** @} */ - -/** - * @name Time conversion utilities - * @{ - */ -/** - * @brief Seconds to system ticks. - * @details Converts from seconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] sec number of seconds - * @return The number of ticks. - * - * @api - */ -#define S2ST(sec) \ - ((systime_t)((sec) * NIL_CFG_FREQUENCY)) - -/** - * @brief Milliseconds to system ticks. - * @details Converts from milliseconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] msec number of milliseconds - * @return The number of ticks. - * - * @api - */ -#define MS2ST(msec) \ - ((systime_t)(((((uint32_t)(msec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\ - 1000UL) + 1UL)) - -/** - * @brief Microseconds to system ticks. - * @details Converts from microseconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] usec number of microseconds - * @return The number of ticks. - * - * @api - */ -#define US2ST(usec) \ - ((systime_t)(((((uint32_t)(usec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\ - 1000000UL) + 1UL)) -/** @} */ - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -671,6 +687,7 @@ extern const thread_config_t nil_thd_configs[NIL_CFG_NUM_THREADS + 1]; extern "C" { #endif void nilSysInit(void); + void nilSysHalt(const char *reason); void nilSysTimerHandlerI(void); thread_ref_t nilSchReadyI(thread_ref_t trp, msg_t msg); msg_t nilSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout); diff --git a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h index 59cd42606..88dba58b8 100644 --- a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h +++ b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h @@ -71,6 +71,12 @@ typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ */ #define NOINLINE __attribute__((noinline)) +/** + * @brief Thread function declaration macro optimized for GCC. + */ +#define PORT_THD_FUNCTION(tname, arg) \ + __attribute__((noreturn)) void tname(void *arg) + #endif /* _NILTYPES_H_ */ /** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore.c b/os/nil/ports/ARMCMx/nilcore.c index e50dc5b80..58b86e76b 100644 --- a/os/nil/ports/ARMCMx/nilcore.c +++ b/os/nil/ports/ARMCMx/nilcore.c @@ -52,19 +52,4 @@ /* Module exported functions. */ /*===========================================================================*/ -/** - * @brief Halts the system. - * @note The function is declared as a weak symbol, it is possible - * to redefine it in your application code. - */ -#if !defined(__DOXYGEN__) -__attribute__((naked, weak)) -#endif -void port_halt(void) { - - port_disable(); - while (true) { - } -} - /** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.c b/os/nil/ports/ARMCMx/nilcore_v6m.c index d8772ca54..19f1b9111 100644 --- a/os/nil/ports/ARMCMx/nilcore_v6m.c +++ b/os/nil/ports/ARMCMx/nilcore_v6m.c @@ -112,7 +112,7 @@ void _port_irq_epilogue(regarm_t lr) { port_lock_from_isr(); /* The extctx structure is pointed by the PSP register.*/ - ctxp = (struct extctx *)__get_PSP(); + ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.h b/os/nil/ports/ARMCMx/nilcore_v6m.h index 846378b65..3e3a7f14c 100644 --- a/os/nil/ports/ARMCMx/nilcore_v6m.h +++ b/os/nil/ports/ARMCMx/nilcore_v6m.h @@ -202,13 +202,13 @@ struct context { * @details This code usually setup the context switching frame represented * by an @p port_intctx structure. */ -#define PORT_SETUP_CONTEXT(workspace, wsize, pf, arg) { \ - tp->p_ctx.r13 = (struct port_intctx *)((uint8_t *)workspace + \ - wsize - \ - sizeof(struct port_intctx)); \ - tp->p_ctx.r13->r4 = (regarm_t)(pf); \ - tp->p_ctx.r13->r5 = (regarm_t)(arg); \ - tp->p_ctx.r13->lr = (regarm_t)(_port_thread_start); \ +#define PORT_SETUP_CONTEXT(tp, workspace, wsize, pf, arg) { \ + (tp)->ctxp = (struct port_intctx *)((uint8_t *)workspace + \ + (size_t)wsize - \ + sizeof(struct port_intctx)); \ + (tp)->ctxp->r4 = (regarm_t)(pf); \ + (tp)->ctxp->r5 = (regarm_t)(arg); \ + (tp)->ctxp->lr = (regarm_t)(_port_thread_start); \ } /** @@ -270,8 +270,8 @@ struct context { } #endif -#if CH_CFG_TIMEDELTA > 0 -#include "chcore_timer.h" +#if NIL_CFG_TIMEDELTA > 0 +#include "nilcore_timer.h" #endif /*===========================================================================*/ @@ -281,7 +281,6 @@ struct context { #ifdef __cplusplus extern "C" { #endif - void port_halt(void); void _port_irq_epilogue(regarm_t lr); void _port_switch_from_isr(void); void _port_exit_from_isr(void); diff --git a/os/nil/src/nil.c b/os/nil/src/nil.c index da75ce1a9..b9b44e4c9 100644 --- a/os/nil/src/nil.c +++ b/os/nil/src/nil.c @@ -80,7 +80,7 @@ void nilSysInit(void) { tr->timeout = 0; /* Port dependent thread initialization.*/ - SETUP_CONTEXT(tr, tcp->wap, tcp->size, tcp->funcp, tcp->arg); + PORT_SETUP_CONTEXT(tr, tcp->wap, tcp->size, tcp->funcp, tcp->arg); /* Initialization hook.*/ #if defined(NIL_CFG_THREAD_EXT_INIT_HOOK) @@ -97,6 +97,35 @@ void nilSysInit(void) { nilSysEnable(); } +/** + * @brief Halts the system. + * @details This function is invoked by the operating system when an + * unrecoverable error is detected, for example because a programming + * error in the application code that triggers an assertion while + * in debug mode. + * @note Can be invoked from any system state. + * + * @special + */ +void nilSysHalt(const char *reason) { + + port_disable(); + +#if NIL_DBG_ENABLED + nil.dbg_panic_msg = reason; +#else + (void)reason; +#endif + +#if defined(NIL_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) + NIL_CFG_SYSTEM_HALT_HOOK(reason); +#endif + + /* Harmless infinite loop.*/ + while (true) + ; +} + /** * @brief Time management handler. * @note This handler has to be invoked by a periodic ISR in order to @@ -113,8 +142,7 @@ void nilSysTimerHandlerI(void) { /* Is the thread in a wait state with timeout?.*/ if (tr->timeout > 0) { - nilDbgAssert(!NIL_THD_IS_READY(tr), - "nilSysTimerHandlerI(), #1", "is ready"); + nilDbgAssert(!NIL_THD_IS_READY(tr), "is ready"); /* Did the timer reach zero?*/ if (--tr->timeout == 0) { @@ -124,7 +152,7 @@ void nilSysTimerHandlerI(void) { tr->u1.semp->cnt++; else if (NIL_THD_IS_SUSP(tr)) tr->u1.trp = NULL; - nilSchReadyI(tr, NIL_MSG_TMO); + nilSchReadyI(tr, MSG_TIMEOUT); } } /* Lock released in order to give a preemption chance on those @@ -194,11 +222,9 @@ thread_ref_t nilSchReadyI(thread_ref_t tr, msg_t msg) { nilDbgAssert((tr >= nil.threads) && (tr < &nil.threads[NIL_CFG_NUM_THREADS]), - "nilSchReadyI(), #1", "pointer out of range"); - nilDbgAssert(!NIL_THD_IS_READY(tr), - "nilSchReadyI(), #2", "already ready"); - nilDbgAssert(nil.next <= nil.current, - "nilSchReadyI(), #3", "priority ordering"); + "pointer out of range"); + nilDbgAssert(!NIL_THD_IS_READY(tr), "already ready"); + nilDbgAssert(nil.next <= nil.current, "priority ordering"); tr->u1.msg = msg; tr->state = NIL_THD_READY; @@ -249,7 +275,7 @@ msg_t nilSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { thread_ref_t ntr, otr = nil.current; nilDbgAssert(otr != &nil.threads[NIL_CFG_NUM_THREADS], - "nilSchGoSleepTimeoutS(), #1", "idle cannot sleep"); + "idle cannot sleep"); /* Storing the wait object for the current thread.*/ otr->state = newstate; @@ -304,7 +330,7 @@ msg_t nilSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { /* Points to the next thread in lowering priority order.*/ ntr++; nilDbgAssert(ntr <= &nil.threads[NIL_CFG_NUM_THREADS], - "nilSchGoSleepTimeoutS(), #2", "pointer out of range"); + "pointer out of range"); } } @@ -324,7 +350,7 @@ msg_t nilSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { */ msg_t nilThdSuspendTimeoutS(thread_ref_t *trp, systime_t timeout) { - nilDbgAssert(*trp == NULL, "nilThdSuspendTimeoutS(), #1", "not NULL"); + nilDbgAssert(*trp == NULL, "not NULL"); *trp = nil.current; nil.current->u1.trp = trp; @@ -346,7 +372,7 @@ void nilThdResumeI(thread_ref_t *trp, msg_t msg) { if (*trp != NULL) { thread_ref_t tr = *trp; - nilDbgAssert(NIL_THD_IS_SUSP(tr), "nilThdResumeI(), #1", "not suspended"); + nilDbgAssert(NIL_THD_IS_SUSP(tr), "not suspended"); *trp = NULL; nilSchReadyI(tr, msg); @@ -476,13 +502,13 @@ msg_t nilSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) { cnt_t cnt = sp->cnt; if (cnt <= 0) { if (TIME_IMMEDIATE == timeout) - return NIL_MSG_TMO; + return MSG_TIMEOUT; sp->cnt = cnt - 1; nil.current->u1.semp = sp; return nilSchGoSleepTimeoutS(NIL_THD_WTSEM, timeout); } sp->cnt = cnt - 1; - return NIL_MSG_OK; + return MSG_OK; } /** @@ -523,10 +549,9 @@ void nilSemSignalI(semaphore_t *sp) { /* Is this thread waiting on this semaphore?*/ if (tr->u1.semp == sp) { - nilDbgAssert(NIL_THD_IS_WTSEM(tr), - "nilSemSignalI(), #1", "not waiting"); + nilDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); - nilSchReadyI(tr, NIL_MSG_OK); + nilSchReadyI(tr, MSG_OK); return; } tr++; @@ -585,11 +610,10 @@ void nilSemResetI(semaphore_t *sp, cnt_t n) { /* Is this thread waiting on this semaphore?*/ if (tr->u1.semp == sp) { - nilDbgAssert(NIL_THD_IS_WTSEM(tr), - "nilSemResetI(), #1", "not waiting"); + nilDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); cnt++; - nilSchReadyI(tr, NIL_MSG_RST); + nilSchReadyI(tr, MSG_RESET); } tr++; } -- cgit v1.2.3