/** * Set a timer. * * This function is used to set a timer for a time sometime in the * future. The function timer_expired() will evaluate to true after * the timer has expired. * * \param t A pointer to the timer * \param interval The interval before the timer expires. * */ void timer_set(struct timer *t, clock_time_t interval) { do_init(t); if (t->started) { timer_stop(t); } switch (sys_execution_context_type_get()) { case NANO_CTX_FIBER: nano_fiber_timer_start(&t->nano_timer, interval); break; case NANO_CTX_TASK: nano_task_timer_start(&t->nano_timer, interval); break; default: return; } PRINTF("%s():%d timer %p started interval %d\n", __FUNCTION__, __LINE__, t, interval); t->started = true; t->interval = interval; t->start = clock_time(); t->triggered = false; }
void fiber_sending(void) { struct nano_timer timer; uint32_t data[2] = {0, 0}; struct net_context *ctx; int i = 0; ctx = get_context(&loopback_addr, DEST_PORT, &any_addr, SRC_PORT); if (!ctx) { PRINT("Cannot get network context\n"); return; } nano_timer_init(&timer, data); while (1) { if (CONFIG_NET_15_4_LOOPBACK_NUM != 0 && i >= CONFIG_NET_15_4_LOOPBACK_NUM) { nano_fiber_timer_stop(&timer); return; } send_data("sendFiber", ctx); nano_fiber_timer_start(&timer, SLEEPTICKS); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); i++; } }
static void myDelay(int ticks) { #ifdef CONFIG_MICROKERNEL task_sleep(ticks); #else struct nano_timer timer; nano_timer_init(&timer, (void *) 0); nano_fiber_timer_start(&timer, ticks); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); #endif }
int fiberLifoWaitTest(void) { void *data; /* ptr to data retrieved from LIFO */ /* * The LIFO is empty; wait for an item to be added to the LIFO * from the task. */ TC_PRINT("Fiber waiting on an empty LIFO\n"); nano_fiber_sem_give(&taskWaitSem); data = nano_fiber_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != &lifoItem[0]) { fiberDetectedFailure = 1; return -1; } nano_fiber_sem_take(&fiberWaitSem, TICKS_UNLIMITED); data = nano_fiber_lifo_get(&test_lifo, TICKS_UNLIMITED); if (data != &lifoItem[2]) { fiberDetectedFailure = 1; return -1; } /* * Give the task some time to check the results. Ideally, this would * be waiting for a semaphore instead of a using a delay, but if the * main task wakes the fiber before it blocks on the LIFO, the fiber * will add the item to the LIFO too soon. Obviously, a semaphore could * not be given if the task is blocked on the LIFO; hence the delay. */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); /* The task is waiting on an empty LIFO. Wake it up. */ nano_fiber_lifo_put(&test_lifo, &lifoItem[3]); nano_fiber_lifo_put(&test_lifo, &lifoItem[1]); /* * Wait for the task to check the results. If the results pass, then the * the task will wake the fiber. If the results do not pass, then the * fiber will wait forever. */ nano_fiber_sem_take(&fiberWaitSem, TICKS_UNLIMITED); return 0; }
static void _gpio_sch_poll_status(int data, int unused) { struct device *dev = INT_TO_POINTER(data); struct gpio_sch_config *info = dev->config->config_info; struct gpio_sch_data *gpio = dev->driver_data; ARG_UNUSED(unused); /* Cleaning up GTS first */ _write_gts(_read_gts(info->regs), info->regs); while (gpio->poll) { uint32_t status; if (!gpio->callback) { goto loop; } status = _read_gts(info->regs); if (!status) { goto loop; } if (gpio->port_cb) { gpio->callback(dev, status); goto ack; } if (gpio->cb_enabled) { uint32_t valid_int = status & gpio->cb_enabled; int i; for (i = 0; i < info->bits; i++) { if (valid_int & BIT(i)) { gpio->callback(dev, i); } } } ack: /* It's not documented but writing the same status value * into GTS tells to the controller it got handled. */ _write_gts(status, info->regs); loop: nano_fiber_timer_start(&gpio->poll_timer, GPIO_SCH_POLLING_TICKS); nano_fiber_timer_test(&gpio->poll_timer, TICKS_UNLIMITED); } }
static void test_nano_timers(int unused1, int unused2) { struct nano_timer timer; ARG_UNUSED(unused1); ARG_UNUSED(unused2); nano_timer_init(&timer, (void *)0xdeadbeef); TC_PRINT("starting nano timer to expire in %d seconds\n", TEST_NANO_TIMERS_DELAY); nano_fiber_timer_start(&timer, SECONDS(TEST_NANO_TIMERS_DELAY)); TC_PRINT("fiber pending on timer\n"); nano_fiber_timer_wait(&timer); TC_PRINT("fiber back from waiting on timer: giving semaphore.\n"); nano_task_sem_give(&test_nano_timers_sem); TC_PRINT("fiber semaphore given.\n"); /* on failure, don't give semaphore, main test will not obtain it */ }
void fiberEntry(void) { struct nano_timer timer; uint32_t data[2] = {0, 0}; nano_sem_init(&nanoSemFiber); nano_timer_init(&timer, data); while (1) { /* wait for task to let us have a turn */ nano_fiber_sem_take_wait(&nanoSemFiber); /* say "hello" */ PRINT("%s: Hello World!\n", __FUNCTION__); /* wait a while, then let task have a turn */ nano_fiber_timer_start(&timer, SLEEPTICKS); nano_fiber_timer_wait(&timer); nano_fiber_sem_give(&nanoSemTask); } }
/** * Restart the timer from the current point in time * * This function restarts a timer with the same interval that was * given to the timer_set() function. The timer will start at the * current time. * * \note A periodic timer will drift if this function is used to reset * it. For preioric timers, use the timer_reset() function instead. * * \param t A pointer to the timer. * * \sa timer_reset() */ void timer_restart(struct timer *t) { do_init(t); if (t->started) { timer_stop(t); } switch (sys_execution_context_type_get()) { case NANO_CTX_FIBER: nano_fiber_timer_start(&t->nano_timer, t->interval); break; case NANO_CTX_TASK: nano_task_timer_start(&t->nano_timer, t->interval); break; default: return; } t->started = true; t->start = clock_time(); t->triggered = false; }
void fiber3(void) { void *pData; /* Wait for fiber3 to be activated */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); /* Put two items onto <nanoFifoObj2> to unblock fibers #1 and #2. */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[0]); /* Wake fiber1 */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[1]); /* Wake fiber2 */ /* Wait for fiber3 to be re-activated */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); /* Immediately get the data from <nanoFifoObj2>. */ pData = nano_fiber_fifo_get(&nanoFifoObj2, TICKS_UNLIMITED); if (pData != pPutList2[0]) { retCode = TC_FAIL; TC_ERROR("fiber3 (1) - got 0x%x from <nanoFifoObj2>, expected 0x%x\n", pData, pPutList2[0]); } /* Put three items onto the FIFO for the task to get */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[0]); nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[1]); nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[2]); /* Sleep for 2 seconds */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); /* Put final item onto the FIFO for the task to get */ nano_fiber_fifo_put(&nanoFifoObj2, pPutList2[3]); /* Wait for fiber3 to be re-activated (not expected to occur) */ nano_fiber_sem_take(&nanoSemObj3, TICKS_UNLIMITED); }
void fiber3(void) { nano_fiber_timer_start(&timer, SECONDS(1)); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); nano_fiber_stack_push(&nanoStackObj, myData[0]); }
static void fiberEntry(int arg1, int arg2) { int rv; /* return value from a test */ ARG_UNUSED(arg1); ARG_UNUSED(arg2); rv = testSemFiberNoWait(); if (rv != TC_PASS) { return; } /* * At this point <testSem> is not available. Wait for <testSem> to become * available (the main task will give it). */ nano_fiber_sem_take_wait(&testSem); semTestState = STS_TASK_WOKE_FIBER; /* * Delay for two seconds. This gives the main task time to print * any messages (very important if I/O link is slow!), and wait * on <testSem>. Once the delay is done, this fiber will give <testSem> * thus waking the main task. */ nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_wait(&timer); /* * The main task is now waiting on <testSem>. Give the semaphore <testSem> * to wake it. */ nano_fiber_sem_give(&testSem); /* * Some small delay must be done so that the main task can process the * semaphore signal. */ semTestState = STS_FIBER_WOKE_TASK; nano_fiber_timer_start(&timer, SECONDS(2)); nano_fiber_timer_wait(&timer); /* * The main task should be waiting on <testSem> again. This time, instead * of giving the semaphore from the semaphore, give it from an ISR to wake * the main task. */ isrSemInfo.data = 0; isrSemInfo.sem = &testSem; _trigger_nano_isr_sem_give(); if (isrSemInfo.data == 1) { semTestState = STS_ISR_WOKE_TASK; } }
/** * Main function of the timer task. This function is in charge of * calling the callbacks associated with the timers. * * This function is run in a high priority task on microkernel builds. * This function is run in a high priority fiber on nanokernel builds. * It implements an infinite loop that waits for any of the semaphores from * g_TimerSem. * When a semaphore is signaled, this function fetches the pointer to the * associated callback in g_TimerDesc, then calls it. * * @param dummy1 not used (required by ZEPHYR API) * @param dummy2 not used (required by ZEPHYR API) * * */ void timer_task(int dummy1, int dummy2) { uint32_t timeout; uint32_t now; UNUSED(dummy1); UNUSED(dummy2); timeout = OS_WAIT_FOREVER; while (1) /* the Timer task shall never stop */ { #ifdef CONFIG_MICROKERNEL /********************** MICRO KERNEL SPECIFIC: */ /* block until g_TimerSem is signaled or until the next timeout expires */ (void) task_sem_take_wait_timeout(g_TimerSem, timeout); #else if (NULL == g_CurrentTimerHead) { /* Start a background timer with max positive delay */ nano_fiber_timer_start (&g_NanoTimer, 0x7FFFFFFF); /* wait until the next timer expires or one is added or removed */ nano_fiber_timer_wait (&g_NanoTimer); } #endif now = _GET_TICK(); /* task is unblocked: check for expired timers */ while (is_after_expiration (now, &(g_CurrentTimerHead->desc))) { execute_callback(g_CurrentTimerHead); } /* Compute timeout until the expiration of the next timer */ if ( NULL != g_CurrentTimerHead ) { now = _GET_TICK(); /* In micro kernel context, timeout = 0 or timeout < 0 works. * In nano kernel context timeout must be a positive value. */ #ifdef CONFIG_NANOKERNEL if (g_CurrentTimerHead->desc.expiration > now) { #endif timeout = g_CurrentTimerHead->desc.expiration - now; if (OS_WAIT_FOREVER == timeout) { /* cannot have timeout = OS_WAIT_FOREVER while there is still at least one active timer */ timeout++; } #ifdef CONFIG_NANOKERNEL nano_fiber_timer_start (&g_NanoTimer, timeout); /* wait until the next timer expires or one is added or removed */ nano_fiber_timer_wait (&g_NanoTimer); /* nano_fiber_timer_wait will wait until "natural" timer * expiration, or until nano_fiber_timer_stop(&g_NanoTimer) * is called by the timer_callback or by timer_stop() */ } #endif } #ifdef CONFIG_MICROKERNEL else { timeout = OS_WAIT_FOREVER; } #endif #ifdef __DEBUG_OS_ABSTRACTION_TIMER if (NULL != g_CurrentTimerHead ) _log ("\nINFO : timer_task : now = %u, next timer expires at %u, timeout = %u", _GET_TICK() , g_CurrentTimerHead->desc.expiration, timeout ); else _log ("\nINFO : timer_task : now = %u, no next timer, timeout = OS_WAIT_FOREVER", _GET_TICK() ); #endif } /* end while(1) */ }