kernel: Introduce sys_thread_busy_wait() API
Provides a way for a fiber or task to busy wait for a specified period of time. This is useful in situations where a delay needs to be performed without switching execution to another context, such as: 1) It would take longer to switch to another context and then switch back again than to simply busy wait. 2) A delay is required by the kernel's main task (i.e. the nanokernel's background task or the microkernel's idle task). This task is not allowed to voluntarily relinquish the CPU because this would leave the kernel with nothing to execute in its place. Change-Id: Icbe28613014f659e9528893ae58f7b8008c18a61 Original-work-by: Jeff Blais <jeff.blais@windriver.com> Further-adapted-by: Benjamin Walsh <benjamin.walsh@windriver.com> Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
This commit is contained in:
parent
136c18e683
commit
6ac33f2b9f
2 changed files with 50 additions and 0 deletions
|
@ -125,6 +125,23 @@ extern nano_context_type_t sys_execution_context_type_get(void);
|
|||
|
||||
extern int _is_thread_essential(nano_thread_id_t pCtx);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Busy wait the currently executing thread
|
||||
*
|
||||
* This routine causes the current task or fiber to execute a "do nothing"
|
||||
* loop for a specified period of time.
|
||||
*
|
||||
* @warning This routine utilizes the system clock, so it must not be invoked
|
||||
* until the system clock is fully operational or while interrupts
|
||||
* are locked.
|
||||
*
|
||||
* @param usec_to_wait Number of microseconds to busy wait.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
extern void sys_thread_busy_wait(uint32_t usec_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Nanokernel Fibers
|
||||
* @defgroup nanokernel_fiber Nanokernel Fibers
|
||||
|
|
|
@ -41,6 +41,8 @@ tasks or fibers.
|
|||
|
||||
#include <nano_private.h>
|
||||
#include <misc/printk.h>
|
||||
#include <sys_clock.h>
|
||||
#include <drivers/system_timer.h>
|
||||
|
||||
|
||||
nano_thread_id_t sys_thread_self_get(void)
|
||||
|
@ -105,6 +107,37 @@ int _is_thread_essential(struct tcs *pCtx /* pointer to thread */
|
|||
return ((pCtx == NULL) ? _nanokernel.current : pCtx)->flags & ESSENTIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't build sys_thread_busy_wait() for ARM, since intrinsics libraries in
|
||||
* current Zephyr SDK use non-Thumb code that isn't supported on Cortex-M CPUs.
|
||||
* For the time being any ARM-based application that attempts to use this API
|
||||
* will get a link error (which is preferable to a mysterious exception).
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_ARM
|
||||
|
||||
void sys_thread_busy_wait(uint32_t usec_to_wait)
|
||||
{
|
||||
/* use 64-bit math to prevent overflow when multiplying */
|
||||
uint32_t cycles_to_wait = (uint32_t)(
|
||||
(uint64_t)usec_to_wait *
|
||||
(uint64_t)sys_clock_hw_cycles_per_sec /
|
||||
(uint64_t)USEC_PER_SEC
|
||||
);
|
||||
uint32_t start_cycles = _sys_clock_cycle_get();
|
||||
|
||||
for (;;) {
|
||||
uint32_t current_cycles = _sys_clock_cycle_get();
|
||||
|
||||
/* this handles the rollover on an unsigned 32-bit value */
|
||||
if ((current_cycles - start_cycles) >= cycles_to_wait) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM */
|
||||
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue