diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-06 12:43:07 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-06 12:43:07 +0000 |
commit | db0b899f5f573e3f55185b96f713e3ecb84c1da5 (patch) | |
tree | 4a6991289585f932017189d26ffe883a1311c0d8 | |
parent | b968a3f9e3bb0b4c6f294fe3933f0ab7de674cb0 (diff) | |
download | ChibiOS-db0b899f5f573e3f55185b96f713e3ecb84c1da5.tar.gz ChibiOS-db0b899f5f573e3f55185b96f713e3ecb84c1da5.tar.bz2 ChibiOS-db0b899f5f573e3f55185b96f713e3ecb84c1da5.zip |
CMSIS RTOS added.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7377 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r-- | os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c | 272 | ||||
-rw-r--r-- | os/rt/ports/ARMCMx/cmsis_os/cmsis_os.h | 136 | ||||
-rw-r--r-- | os/rt/ports/ARMCMx/cmsis_os/cmsis_os.mk | 4 |
3 files changed, 380 insertions, 32 deletions
diff --git a/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c index 94334af5e..454a77d1f 100644 --- a/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c +++ b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c @@ -35,6 +35,12 @@ /* Module local definitions. */
/*===========================================================================*/
+static memory_pool_t sempool;
+static semaphore_t semaphores[CMSIS_CFG_NUM_SEMAPHORES];
+
+static memory_pool_t timpool;
+static struct os_timer_cb timers[CMSIS_CFG_NUM_TIMERS];
+
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
@@ -51,8 +57,274 @@ /* Module local functions. */
/*===========================================================================*/
+/**
+ * @brief Virtual timers common callback.
+ */
+static void timer_cb(void *arg) {
+
+ osTimerId timer_id = (osTimerId)arg;
+ timer_id->ptimer(timer_id->argument);
+ if (timer_id->type == osTimerPeriodic) {
+ chSysLockFromISR();
+ chVTDoSetI(&timer_id->vt, timer_id->millisec, timer_cb, timer_id);
+ chSysUnlockFromISR();
+ }
+}
+
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
+/**
+ * @brief Kernel initialization.
+ */
+osStatus osKernelInitialize(void) {
+
+ chSysInit();
+ chThdSetPriority(HIGHPRIO);
+
+ chPoolObjectInit(&sempool, sizeof(semaphore_t), chCoreAlloc);
+ chPoolLoadArray(&sempool, semaphores, CMSIS_CFG_NUM_SEMAPHORES);
+
+ chPoolObjectInit(&timpool, sizeof(virtual_timer_t), chCoreAlloc);
+ chPoolLoadArray(&timpool, timers, CMSIS_CFG_NUM_TIMERS);
+
+ return osOK;
+}
+
+/**
+ * @brief Kernel start.
+ */
+osStatus osKernelStart(void) {
+
+ chThdSetPriority(NORMALPRIO);
+
+ return osOK;
+}
+
+/**
+ * @brief Change thread priority.
+ * @note This can interfere with the priority inheritance mechanism.
+ */
+osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio) {
+ osPriority oldprio;
+ thread_t * tp = (thread_t *)thread_id;
+
+ chSysLock();
+
+ /* Changing priority.*/
+#if CH_CFG_USE_MUTEXES
+ oldprio = (osPriority)tp->p_realprio;
+ if ((tp->p_prio == tp->p_realprio) || ((tprio_t)newprio > tp->p_prio))
+ tp->p_prio = (tprio_t)newprio;
+ tp->p_realprio = (tprio_t)newprio;
+#else
+ oldprio = tp->p_prio;
+ tp->p_prio = (tprio_t)newprio;
+#endif
+
+ /* The following states need priority queues reordering.*/
+ switch (tp->p_state) {
+#if CH_CFG_USE_MUTEXES | \
+ CH_CFG_USE_CONDVARS | \
+ (CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \
+ (CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY)
+#if CH_CFG_USE_MUTEXES
+ case CH_STATE_WTMTX:
+#endif
+#if CH_CFG_USE_CONDVARS
+ case CH_STATE_WTCOND:
+#endif
+#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY
+ case CH_STATE_WTSEM:
+#endif
+#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
+ case CH_STATE_SNDMSGQ:
+#endif
+ /* Re-enqueues tp with its new priority on the queue.*/
+ queue_prio_insert(queue_dequeue(tp),
+ (threads_queue_t *)tp->p_u.wtobjp);
+ break;
+#endif
+ case CH_STATE_READY:
+#if CH_DBG_ENABLE_ASSERTS
+ /* Prevents an assertion in chSchReadyI().*/
+ tp->p_state = CH_STATE_CURRENT;
+#endif
+ /* Re-enqueues tp with its new priority on the ready list.*/
+ chSchReadyI(queue_dequeue(tp));
+ break;
+ }
+
+ /* Rescheduling.*/
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return oldprio;
+}
+
+/**
+ * @brief Create a timer.
+ */
+osTimerId osTimerCreate (const osTimerDef_t *timer_def,
+ os_timer_type type,
+ void *argument) {
+
+ osTimerId timer = chPoolAlloc(&timpool);
+ chVTObjectInit(&timer->vt);
+ timer->ptimer = timer_def->ptimer;
+ timer->type = type;
+ timer->argument = argument;
+ return timer;
+}
+
+/**
+ * @brief Start a timer.
+ */
+osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
+
+ if (millisec == 0)
+ return osErrorParameter;
+
+ timer_id->millisec = millisec;
+ chVTSet(&timer_id->vt, millisec, timer_cb, timer_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Stop a timer.
+ */
+osStatus osTimerStop (osTimerId timer_id) {
+
+ chVTReset(&timer_id->vt);
+
+ return osOK;
+}
+
+/**
+ * @brief Delete a timer.
+ */
+osStatus osTimerDelete (osTimerId timer_id) {
+
+ chVTReset(&timer_id->vt);
+ chPoolFree(&timpool, (void *)timer_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Create a semaphore.
+ * @note @p semaphore_def is not used.
+ * @note Can involve memory allocation.
+ */
+osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def,
+ int32_t count) {
+
+ (void)semaphore_def;
+
+ semaphore_t *sem = chPoolAlloc(&sempool);
+ chSemObjectInit(sem, (cnt_t)count);
+ return sem;
+}
+
+/**
+ * @brief Wait on a semaphore.
+ */
+int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
+
+ systime_t timeout = millisec == osWaitForever ? TIME_INFINITE :
+ (systime_t)millisec;
+ msg_t msg = chSemWaitTimeout((semaphore_t *)semaphore_id, timeout);
+ switch (msg) {
+ case MSG_OK:
+ return osOK;
+ case MSG_TIMEOUT:
+ return osErrorTimeoutResource;
+ }
+ return osErrorResource;
+}
+
+/**
+ * @brief Release a semaphore.
+ */
+osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ chSemSignalI((semaphore_t *)semaphore_id);
+ chSysRestoreStatusX(sts);
+
+ return osOK;
+}
+
+/**
+ * @brief Deletes a semaphore.
+ * @note After deletion there could be references in the system to a
+ * non-existent semaphore.
+ */
+osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
+
+ chSemReset((semaphore_t *)semaphore_id, 0);
+ chPoolFree(&sempool, (void *)semaphore_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Create a mutex.
+ * @note @p mutex_def is not used.
+ * @note Can involve memory allocation.
+ */
+osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
+
+ (void)mutex_def;
+
+ binary_semaphore_t *mtx = chPoolAlloc(&sempool);
+ chBSemObjectInit(mtx, false);
+ return mtx;
+}
+
+/**
+ * @brief Wait on a mutex.
+ */
+osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
+
+ systime_t timeout = millisec == osWaitForever ? TIME_INFINITE :
+ (systime_t)millisec;
+ msg_t msg = chBSemWaitTimeout((binary_semaphore_t *)mutex_id, timeout);
+ switch (msg) {
+ case MSG_OK:
+ return osOK;
+ case MSG_TIMEOUT:
+ return osErrorTimeoutResource;
+ }
+ return osErrorResource;
+}
+
+/**
+ * @brief Release a mutex.
+ */
+osStatus osMutexRelease (osMutexId mutex_id) {
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ chBSemSignalI((binary_semaphore_t *)mutex_id);
+ chSysRestoreStatusX(sts);
+
+ return osOK;
+}
+
+/**
+ * @brief Deletes a mutex.
+ * @note After deletion there could be references in the system to a
+ * non-existent semaphore.
+ */
+osStatus osMutexDelete (osMutexId mutex_id) {
+
+ chSemReset((semaphore_t *)mutex_id, 0);
+ chPoolFree(&sempool, (void *)mutex_id);
+
+ return osOK;
+}
+
/** @} */
diff --git a/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.h b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.h index 09013df20..784a04b97 100644 --- a/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.h +++ b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.h @@ -83,10 +83,36 @@ /* Module pre-compile time settings. */
/*===========================================================================*/
+/**
+ * @brief Number of pre-allocated static semaphores/mutexes.
+ */
+#if !defined(CMSIS_CFG_NUM_SEMAPHORES)
+#define CMSIS_CFG_NUM_SEMAPHORES 4
+#endif
+
+/**
+ * @brief Number of pre-allocated static timers.
+ */
+#if !defined(CMSIS_CFG_NUM_TIMERS)
+#define CMSIS_CFG_NUM_TIMERS 4
+#endif
+
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
+#if !CH_CFG_USE_MEMPOOLS
+#error "CMSIS RTOS requires CH_CFG_USE_MEMPOOLS"
+#endif
+
+#if !CH_CFG_USE_SEMAPHORES
+#error "CMSIS RTOS requires CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if !CH_CFG_USE_DYNAMIC
+#error "CMSIS RTOS requires CH_CFG_USE_DYNAMIC"
+#endif
+
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
@@ -130,8 +156,8 @@ typedef enum { * @brief Type of a timer mode.
*/
typedef enum {
- osTimerOnce = 0,
- osTimerPeriodic = 1
+ osTimerOnce = 0,
+ osTimerPeriodic = 1
} os_timer_type;
/**
@@ -147,22 +173,28 @@ typedef void (*os_ptimer) (void const *argument); /**
* @brief Type of pointer to thread control block.
*/
-typedef struct os_thread_cb *osThreadId;
+typedef thread_t *osThreadId;
/**
* @brief Type of pointer to timer control block.
*/
-typedef struct os_timer_cb *osTimerId;
+typedef struct os_timer_cb {
+ virtual_timer_t vt;
+ os_timer_type type;
+ os_ptimer ptimer;
+ void *argument;
+ uint32_t millisec;
+} *osTimerId;
/**
* @brief Type of pointer to mutex control block.
*/
-typedef struct os_mutex_cb *osMutexId;
+typedef binary_semaphore_t *osMutexId;
/**
* @brief Type of pointer to semaphore control block.
*/
-typedef struct os_semaphore_cb *osSemaphoreId;
+typedef semaphore_t *osSemaphoreId;
/**
* @brief Type of a thread definition block.
@@ -280,13 +312,25 @@ const osTimerDef_t os_timer_def_##name = { \ #ifdef __cplusplus
extern "C" {
#endif
- osThreadId osThreadGetId(void);
- osStatus osThreadTerminate(osThreadId thread_id);
- osStatus osThreadYield(void);
- osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority);
- osPriority osThreadGetPriority(osThreadId thread_id);
- osStatus osDelay(uint32_t millisec);
+ osStatus osKernelInitialize(void);
+ osStatus osKernelStart(void);
+ osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio);
/*osEvent osWait(uint32_t millisec);*/
+ osTimerId osTimerCreate (const osTimerDef_t *timer_def,
+ os_timer_type type,
+ void *argument);
+ osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
+ osStatus osTimerStop (osTimerId timer_id);
+ osStatus osTimerDelete (osTimerId timer_id);
+ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def,
+ int32_t count);
+ int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
+ osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
+ osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
+ osMutexId osMutexCreate (const osMutexDef_t *mutex_def);
+ osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
+ osStatus osMutexRelease (osMutexId mutex_id);
+ osStatus osMutexDelete (osMutexId mutex_id);
#ifdef __cplusplus
}
#endif
@@ -296,26 +340,6 @@ extern "C" { /*===========================================================================*/
/**
- * @brief Kernel initialization.
- */
-static inline osStatus osKernelInitialize(void) {
-
- chSysSuspend();
-
- return osOK;
-}
-
-/**
- * @brief Kernel start.
- * @note Does nothing, under ChibiOS/RT there is no concept of starting the
- * kernel.
- */
-static inline osStatus osKernelStart(void) {
-
- return osOK;
-}
-
-/**
* @brief To be or not to be.
*/
static inline int32_t osKernelRunning(void) {
@@ -347,6 +371,54 @@ static inline osThreadId osThreadCreate (osThreadDef_t *thread_def, argument);
}
+/**
+ * @brief Returns the current thread.
+ */
+static inline osThreadId osThreadGetId(void) {
+
+ return (osThreadId)chThdGetSelfX();
+}
+
+/**
+ * @brief Thread termination.
+ * @note The thread is not really terminated but asked to terminate which
+ * is not compliant.
+ */
+static inline osStatus osThreadTerminate(osThreadId thread_id) {
+
+ chThdTerminate(thread_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Thread time slice yield.
+ */
+static inline osStatus osThreadYield(void) {
+
+ chThdYield();
+
+ return osOK;
+}
+
+/**
+ * @brief Returns priority of a thread.
+ */
+static inline osPriority osThreadGetPriority(osThreadId thread_id) {
+
+ return thread_id->p_prio;
+}
+
+/**
+ * @brief Thread delay in milliseconds.
+ */
+static inline osStatus osDelay(uint32_t millisec) {
+
+ chThdSleepMilliseconds(millisec);
+
+ return osOK;
+}
+
#endif /* _CMSIS_OS_H_ */
/** @} */
diff --git a/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.mk b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.mk new file mode 100644 index 000000000..d679622ad --- /dev/null +++ b/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.mk @@ -0,0 +1,4 @@ +# List of the ChibiOS/RT CMSIS RTOS wrapper.
+CMSISRTOSSRC = ${CHIBIOS}/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c
+
+CMSISRTOSINC = ${CHIBIOS}/os/rt/ports/ARMCMx/cmsis_os
|