Skip to content

Commit

Permalink
sys_util: wait_for, spin on an expression
Browse files Browse the repository at this point in the history
Hardware has asynchronous actions where the expectation is to spin on
registers and expressions against those registers for completion of the
action. This provides a common macro to spin, with a delay and timeout,
on such expressions.

Signed-off-by: Tom Burdick <[email protected]>
  • Loading branch information
teburd authored and nashif committed Mar 11, 2022
1 parent af9a6a6 commit 3ab10f2
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 0 deletions.
25 changes: 25 additions & 0 deletions include/sys/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,31 @@ char *utf8_lcpy(char *dst, const char *src, size_t n);
/** @brief Number of Hz in @p x MHz */
#define MHZ(x) (KHZ(x) * 1000)

/**
* @brief Wait for an expression to return true with a timeout
*
* Spin on an expression with a timeout and optional delay between iterations
*
* Commonly needed when waiting on hardware to complete an asynchronous
* request to read/write/initialize/reset, but useful for any expression.
*
* @param expr Truth expression upon which to poll, e.g.: XYZREG & XYZREG_EN
* @param timeout Timeout to wait for in microseconds, e.g.: 1000 (1ms)
* @param delay_stmt Delay statement to perform each poll iteration
* e.g.: NULL, k_yield(), k_msleep(1) or k_busy_wait(1)
*
* @retval expr As a boolean return, if false then it has timed out.
*/
#define wait_for(expr, timeout, delay_stmt) \
({ \
uint32_t cycle_count = (sys_clock_hw_cycles_per_sec() / USEC_PER_SEC) * (timeout); \
uint32_t start = k_cycle_get_32(); \
while (!(expr) && (cycle_count > (k_cycle_get_32() - start))) { \
delay_stmt; \
} \
(expr); \
})

/**
* @}
*/
Expand Down
10 changes: 10 additions & 0 deletions tests/lib/sys_util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(sys_util)

target_sources(app PRIVATE
src/main.c
src/wait_for.c
)
1 change: 1 addition & 0 deletions tests/lib/sys_util/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_ZTEST=y
22 changes: 22 additions & 0 deletions tests/lib/sys_util/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <ztest.h>

extern void test_wait_for(void);

/**
* @defgroup sys_util_tests Sys Util Tests
* @ingroup all_tests
* @{
* @}
*/

void test_main(void)
{
ztest_test_suite(sys_util, ztest_unit_test(test_wait_for));
ztest_run_test_suite(sys_util);
}
42 changes: 42 additions & 0 deletions tests/lib/sys_util/src/wait_for.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2022 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <sys/util.h>
#include <kernel.h>
#include <ztest.h>

/**
* @addtogroup sys_util_tests
* @{
*/

/**
* @brief Test wait_for works as expected with typical use cases
*
* @see wait_for()
*/
void test_wait_for(void)
{
uint32_t start, end, expected;

zassert_true(wait_for(true, 0, NULL), "true, no wait, NULL");
zassert_true(wait_for(true, 0, k_yield()), "true, no wait, yield");
zassert_false(wait_for(false, 0, k_yield()), "false, no wait, yield");
zassert_true(wait_for(true, 1, k_yield()), "true, 1usec, yield");
zassert_false(wait_for(false, 1, k_yield()), "false, 1usec, yield");
zassert_true(wait_for(true, 1000, k_yield()), "true, 1msec, yield");


expected = 1000*(sys_clock_hw_cycles_per_sec()/USEC_PER_SEC);
start = k_cycle_get_32();
zassert_false(wait_for(false, 1000, k_yield()), "true, 1msec, yield");
end = k_cycle_get_32();
zassert_true(end-start >= expected, "wait for 1ms");
}

/**
* @}
*/
4 changes: 4 additions & 0 deletions tests/lib/sys_util/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
tests:
lib.sys_util:
platform_exclude: native_posix native_posix_64
tags: sys_util

0 comments on commit 3ab10f2

Please sign in to comment.