| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- /*
- * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * -----------------------------------------------------------------------------
- *
- * Project: CMSIS-RTOS RTX
- * Title: Timer functions
- *
- * -----------------------------------------------------------------------------
- */
- #include "rtx_lib.h"
- // ==== Helper functions ====
- /// Insert Timer into the Timer List sorted by Time.
- /// \param[in] timer timer object.
- /// \param[in] tick timer tick.
- static void os_TimerInsert (os_timer_t *timer, uint32_t tick) {
- os_timer_t *prev, *next;
- prev = NULL;
- next = os_Info.timer.list;
- while ((next != NULL) && (next->tick <= tick)) {
- tick -= next->tick;
- prev = next;
- next = next->next;
- }
- timer->tick = tick;
- timer->prev = prev;
- timer->next = next;
- if (next != NULL) {
- next->tick -= timer->tick;
- next->prev = timer;
- }
- if (prev != NULL) {
- prev->next = timer;
- } else {
- os_Info.timer.list = timer;
- }
- }
- /// Remove Timer from the Timer List.
- /// \param[in] timer timer object.
- static void os_TimerRemove (os_timer_t *timer) {
- if (timer->next != NULL) {
- timer->next->tick += timer->tick;
- timer->next->prev = timer->prev;
- }
- if (timer->prev != NULL) {
- timer->prev->next = timer->next;
- } else {
- os_Info.timer.list = timer->next;
- }
- }
- /// Unlink Timer from the Timer List Head.
- /// \param[in] timer timer object.
- static void os_TimerUnlink (os_timer_t *timer) {
- if (timer->next != NULL) {
- timer->next->prev = timer->prev;
- }
- os_Info.timer.list = timer->next;
- }
- // ==== Library functions ====
- /// Timer Tick (called each SysTick).
- void os_TimerTick (void) {
- os_timer_t *timer;
- osStatus_t status;
- timer = os_Info.timer.list;
- if (timer == NULL) {
- return;
- }
- timer->tick--;
- while ((timer != NULL) && (timer->tick == 0U)) {
- os_TimerUnlink(timer);
- status = osMessageQueuePut((osMessageQueueId_t)os_Info.timer.mq, &timer->finfo, 0U, 0U);
- if (status != osOK) {
- os_Error(os_ErrorTimerQueueOverflow, timer);
- }
- if (timer->type == os_TimerPeriodic) {
- os_TimerInsert(timer, timer->load);
- } else {
- timer->state = os_TimerStopped;
- }
- timer = os_Info.timer.list;
- }
- }
- /// Timer Thread
- void *os_TimerThread (void *argument) {
- os_timer_finfo_t finfo;
- osStatus_t status;
- (void) argument;
- for (;;) {
- status = osMessageQueueGet((osMessageQueueId_t)os_Info.timer.mq, &finfo, NULL, osWaitForever);
- if (status == osOK) {
- (*(os_timer_func_t)finfo.fp)(finfo.arg);
- }
- }
-
- return NULL;
- }
- // ==== Service Calls ====
- // Service Calls definitions
- SVC0_4(TimerNew, osTimerId_t, os_timer_func_t, osTimerType_t, void *, const osTimerAttr_t *)
- SVC0_2(TimerStart, osStatus_t, osTimerId_t, uint32_t)
- SVC0_1(TimerStop, osStatus_t, osTimerId_t)
- SVC0_1(TimerIsRunning, uint32_t, osTimerId_t)
- SVC0_1(TimerDelete, osStatus_t, osTimerId_t)
- /// Create and Initialize a timer.
- /// \note API identical to osTimerNew
- osTimerId_t os_svcTimerNew (os_timer_func_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
- os_timer_t *timer;
- uint8_t flags;
- const char *name;
- // Create common timer message queue if not yet active
- if (os_Info.timer.mq == NULL) {
- os_Info.timer.mq = (os_message_queue_t *)(os_svcMessageQueueNew(
- os_Config.timer_mq_mcnt,
- sizeof(os_timer_finfo_t),
- os_Config.timer_mq_attr));
- if (os_Info.timer.mq == NULL) {
- return (osTimerId_t)NULL;
- }
- }
- // Create common timer thread if not yet active
- if (os_Info.timer.thread == NULL) {
- os_Info.timer.thread = (os_thread_t *)(os_svcThreadNew(
- os_TimerThread,
- NULL,
- os_Config.timer_thread_attr));
- if (os_Info.timer.thread == NULL) {
- return (osTimerId_t)NULL;
- }
- }
- // Check parameters
- if ((func == NULL) || ((type != osTimerOnce) && (type != osTimerPeriodic))) {
- return (osTimerId_t)NULL;
- }
- // Check timer objects
- if ((os_Info.timer.thread == NULL) || (os_Info.timer.mq == NULL)) {
- return (osTimerId_t)NULL;
- }
- // Process attributes
- if (attr != NULL) {
- name = attr->name;
- timer = attr->cb_mem;
- if (timer != NULL) {
- if (((uint32_t)timer & 3U) || (attr->cb_size < sizeof(os_timer_t))) {
- return (osTimerId_t)NULL;
- }
- } else {
- if (attr->cb_size != 0U) {
- return (osTimerId_t)NULL;
- }
- }
- } else {
- name = NULL;
- timer = NULL;
- }
- // Allocate object memory if not provided
- if (timer == NULL) {
- if (os_Info.mpi.timer != NULL) {
- timer = os_MemoryPoolAlloc(os_Info.mpi.timer);
- } else {
- timer = os_MemoryAlloc(os_Info.mem.cb, sizeof(os_timer_t));
- }
- if (timer == NULL) {
- return (osTimerId_t)NULL;
- }
- flags = os_FlagSystemObject;
- } else {
- flags = 0U;
- }
- // Initialize control block
- timer->id = os_IdTimer;
- timer->state = os_TimerStopped;
- timer->flags = flags;
- timer->type = (uint8_t)type;
- timer->name = name;
- timer->prev = NULL;
- timer->next = NULL;
- timer->tick = 0U;
- timer->load = 0U;
- timer->finfo.fp = (void *)func;
- timer->finfo.arg = argument;
- return (osTimerId_t)timer;
- }
- /// Start or restart a timer.
- /// \note API identical to osTimerStart
- osStatus_t os_svcTimerStart (osTimerId_t timer_id, uint32_t millisec) {
- os_timer_t *timer = (os_timer_t *)timer_id;
- // Check parameters
- if ((timer == NULL) ||
- (timer->id != os_IdTimer)) {
- return osErrorParameter;
- }
- if (millisec == 0U) {
- return osErrorParameter;
- }
- // Check object state
- switch (timer->state) {
- case os_TimerStopped:
- timer->state = os_TimerRunning;
- timer->load = millisec;
- break;
- case os_TimerRunning:
- os_TimerRemove(timer);
- break;
- case os_TimerInactive:
- default:
- return osErrorResource;
- }
- os_TimerInsert(timer, millisec);
- return osOK;
- }
- /// Stop a timer.
- /// \note API identical to osTimerStop
- osStatus_t os_svcTimerStop (osTimerId_t timer_id) {
- os_timer_t *timer = (os_timer_t *)timer_id;
- // Check parameters
- if ((timer == NULL) ||
- (timer->id != os_IdTimer)) {
- return osErrorParameter;
- }
- // Check object state
- if (timer->state != os_TimerRunning) {
- return osErrorResource;
- }
- timer->state = os_TimerStopped;
- os_TimerRemove(timer);
- return osOK;
- }
- /// Check if a timer is running.
- /// \note API identical to osTimerIsRunning
- uint32_t os_svcTimerIsRunning (osTimerId_t timer_id) {
- os_timer_t *timer = (os_timer_t *)timer_id;
- // Check parameters
- if ((timer == NULL) ||
- (timer->id != os_IdTimer)) {
- return 0U;
- }
- // Check object state
- if (timer->state == os_TimerRunning) {
- return 1U;
- }
- return 0U;
- }
- /// Delete a timer.
- /// \note API identical to osTimerDelete
- osStatus_t os_svcTimerDelete (osTimerId_t timer_id) {
- os_timer_t *timer = (os_timer_t *)timer_id;
- // Check parameters
- if ((timer == NULL) ||
- (timer->id != os_IdTimer)) {
- return osErrorParameter;
- }
- // Check object state
- switch (timer->state) {
- case os_TimerStopped:
- break;
- case os_TimerRunning:
- os_TimerRemove(timer);
- break;
- case os_TimerInactive:
- default:
- return osErrorResource;
- }
- // Mark object as inactive
- timer->state = os_TimerInactive;
- // Free object memory
- if (timer->flags & os_FlagSystemObject) {
- if (os_Info.mpi.timer != NULL) {
- os_MemoryPoolFree(os_Info.mpi.timer, timer);
- } else {
- os_MemoryFree(os_Info.mem.cb, timer);
- }
- }
- return osOK;
- }
- // ==== Public API ====
- /// Create and Initialize a timer.
- osTimerId_t osTimerNew (os_timer_func_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
- if (__get_IPSR() != 0U) {
- return (osTimerId_t)NULL; // Not allowed in ISR
- }
- if ((os_KernelGetState() == os_KernelReady) && ((__get_CONTROL() & 1U) == 0U)) {
- // Kernel Ready (not running) and in Priviledged mode
- return os_svcTimerNew(func, type, argument, attr);
- } else {
- return __svcTimerNew(func, type, argument, attr);
- }
- }
- /// Start or restart a timer.
- osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t millisec) {
- if (__get_IPSR() != 0U) {
- return osErrorISR; // Not allowed in ISR
- }
- return __svcTimerStart(timer_id, millisec);
- }
- /// Stop a timer.
- osStatus_t osTimerStop (osTimerId_t timer_id) {
- if (__get_IPSR() != 0U) {
- return osErrorISR; // Not allowed in ISR
- }
- return __svcTimerStop(timer_id);
- }
- /// Check if a timer is running.
- uint32_t osTimerIsRunning (osTimerId_t timer_id) {
- if (__get_IPSR() != 0U) {
- return 0U; // Not allowed in ISR
- }
- return __svcTimerIsRunning(timer_id);
- }
- /// Delete a timer.
- osStatus_t osTimerDelete (osTimerId_t timer_id) {
- if (__get_IPSR() != 0U) {
- return osErrorISR; // Not allowed in ISR
- }
- return __svcTimerDelete(timer_id);
- }
|