-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
testsuite: Add busy simulator #36662
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright (c) 2021 Nordic Semiconductor ASA | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: | | ||
CPU load simulator | ||
|
||
compatible: "vnd,busy-sim" | ||
|
||
properties: | ||
counter: | ||
type: phandle | ||
required: true | ||
description: | | ||
Counter device used for generating intervals. | ||
|
||
active-gpios: | ||
type: phandle-array | ||
required: false | ||
description: | | ||
Debug pin is set to active state when cpu load is active. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
* Copyright (c) 2021 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#include <drivers/entropy.h> | ||
#include <drivers/counter.h> | ||
#include <drivers/gpio.h> | ||
#include "busy_sim.h" | ||
#include <sys/ring_buffer.h> | ||
|
||
#define BUFFER_SIZE 32 | ||
|
||
struct busy_sim_data { | ||
uint32_t idle_avg; | ||
uint32_t active_avg; | ||
uint16_t idle_delta; | ||
uint16_t active_delta; | ||
uint32_t us_tick; | ||
struct counter_alarm_cfg alarm_cfg; | ||
struct k_work work; | ||
struct ring_buf rnd_rbuf; | ||
uint8_t rnd_buf[BUFFER_SIZE]; | ||
}; | ||
|
||
struct busy_sim_config { | ||
const struct device *entropy; | ||
const struct device *counter; | ||
struct gpio_dt_spec pin_spec; | ||
}; | ||
|
||
#define DT_BUSY_SIM DT_COMPAT_GET_ANY_STATUS_OKAY(vnd_busy_sim) | ||
|
||
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(vnd_busy_sim) == 1, | ||
"add exactly one vnd,busy-sim node to the devicetree"); | ||
|
||
static const struct busy_sim_config sim_config = { | ||
.entropy = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)), | ||
.counter = DEVICE_DT_GET(DT_PHANDLE(DT_BUSY_SIM, counter)), | ||
.pin_spec = GPIO_DT_SPEC_GET_OR(DT_BUSY_SIM, active_gpios, {0}), | ||
}; | ||
|
||
static struct busy_sim_data sim_data; | ||
static const struct device *busy_sim_dev = DEVICE_DT_GET_ONE(vnd_busy_sim); | ||
|
||
static inline struct busy_sim_data *get_dev_data(const struct device *dev) | ||
{ | ||
return dev->data; | ||
} | ||
|
||
static inline const struct busy_sim_config *get_dev_config(const struct device *dev) | ||
{ | ||
return dev->config; | ||
} | ||
|
||
static void rng_pool_work_handler(struct k_work *work) | ||
{ | ||
uint8_t *buf; | ||
uint32_t len; | ||
struct busy_sim_data *data = get_dev_data(busy_sim_dev); | ||
const struct busy_sim_config *config = get_dev_config(busy_sim_dev); | ||
|
||
len = ring_buf_put_claim(&data->rnd_rbuf, &buf, BUFFER_SIZE - 1); | ||
if (len) { | ||
int err = entropy_get_entropy(config->entropy, buf, len); | ||
|
||
if (err == 0) { | ||
ring_buf_put_finish(&data->rnd_rbuf, len); | ||
return; | ||
} | ||
} | ||
|
||
k_work_submit(work); | ||
} | ||
|
||
|
||
static uint32_t get_timeout(bool idle) | ||
{ | ||
struct busy_sim_data *data = get_dev_data(busy_sim_dev); | ||
uint32_t avg = idle ? data->idle_avg : data->active_avg; | ||
uint32_t delta = idle ? data->idle_delta : data->active_delta; | ||
uint16_t rand_val; | ||
uint32_t len; | ||
|
||
len = ring_buf_get(&data->rnd_rbuf, (uint8_t *)&rand_val, sizeof(rand_val)); | ||
if (len < sizeof(rand_val)) { | ||
k_work_submit(&data->work); | ||
rand_val = 0; | ||
} | ||
|
||
avg *= data->us_tick; | ||
delta *= data->us_tick; | ||
|
||
return avg - delta + 2 * (rand_val % delta); | ||
} | ||
|
||
static void counter_alarm_callback(const struct device *dev, | ||
uint8_t chan_id, uint32_t ticks, | ||
void *user_data) | ||
{ | ||
int err; | ||
const struct busy_sim_config *config = get_dev_config(busy_sim_dev); | ||
struct busy_sim_data *data = get_dev_data(busy_sim_dev); | ||
|
||
data->alarm_cfg.ticks = get_timeout(true); | ||
|
||
if (config->pin_spec.port) { | ||
err = gpio_pin_set_dt(&config->pin_spec, 1); | ||
__ASSERT_NO_MSG(err >= 0); | ||
} | ||
|
||
/* Busy loop */ | ||
k_busy_wait(get_timeout(false) / data->us_tick); | ||
|
||
if (config->pin_spec.port) { | ||
err = gpio_pin_set_dt(&config->pin_spec, 0); | ||
__ASSERT_NO_MSG(err >= 0); | ||
} | ||
|
||
err = counter_set_channel_alarm(config->counter, 0, &data->alarm_cfg); | ||
__ASSERT_NO_MSG(err == 0); | ||
|
||
} | ||
|
||
void busy_sim_start(uint32_t active_avg, uint32_t active_delta, | ||
uint32_t idle_avg, uint32_t idle_delta) | ||
{ | ||
int err; | ||
const struct busy_sim_config *config = get_dev_config(busy_sim_dev); | ||
struct busy_sim_data *data = get_dev_data(busy_sim_dev); | ||
|
||
data->active_avg = active_avg; | ||
data->active_delta = active_delta; | ||
data->idle_avg = idle_avg; | ||
data->idle_delta = idle_delta; | ||
|
||
err = k_work_submit(&data->work); | ||
__ASSERT_NO_MSG(err >= 0); | ||
|
||
data->alarm_cfg.ticks = counter_us_to_ticks(config->counter, 100); | ||
err = counter_set_channel_alarm(config->counter, 0, &data->alarm_cfg); | ||
__ASSERT_NO_MSG(err == 0); | ||
|
||
err = counter_start(config->counter); | ||
__ASSERT_NO_MSG(err == 0); | ||
} | ||
|
||
void busy_sim_stop(void) | ||
{ | ||
int err; | ||
const struct busy_sim_config *config = get_dev_config(busy_sim_dev); | ||
struct busy_sim_data *data = get_dev_data(busy_sim_dev); | ||
|
||
k_work_cancel(&data->work); | ||
err = counter_stop(config->counter); | ||
__ASSERT_NO_MSG(err == 0); | ||
} | ||
|
||
static int busy_sim_init(const struct device *dev) | ||
{ | ||
uint32_t freq; | ||
const struct busy_sim_config *config = get_dev_config(dev); | ||
struct busy_sim_data *data = get_dev_data(dev); | ||
|
||
if ((config->pin_spec.port && !device_is_ready(config->pin_spec.port)) || | ||
!device_is_ready(config->counter) || !device_is_ready(config->entropy)) { | ||
__ASSERT(0, "Devices needed by busy simulator not ready."); | ||
return -EIO; | ||
} | ||
|
||
if (config->pin_spec.port) { | ||
gpio_pin_configure_dt(&config->pin_spec, GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW); | ||
} | ||
|
||
freq = counter_get_frequency(config->counter); | ||
if (freq < 1000000) { | ||
__ASSERT(0, "Counter device has too low frequency for busy simulator."); | ||
return -EINVAL; | ||
} | ||
|
||
k_work_init(&data->work, rng_pool_work_handler); | ||
ring_buf_init(&data->rnd_rbuf, BUFFER_SIZE, data->rnd_buf); | ||
|
||
data->us_tick = freq / 1000000; | ||
data->alarm_cfg.callback = counter_alarm_callback; | ||
data->alarm_cfg.flags = COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE; | ||
|
||
return 0; | ||
} | ||
|
||
DEVICE_DT_DEFINE(DT_BUSY_SIM, busy_sim_init, NULL, | ||
&sim_data, &sim_config, | ||
APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, | ||
NULL); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (c) 2021 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#ifndef BUSY_SIM_H__ | ||
#define BUSY_SIM_H__ | ||
|
||
/** | ||
* @brief Start busy simulator. | ||
* | ||
* When started, it is using counter device to generate interrupts at random | ||
* intervals and busy loop for random period of time in that interrupt. Interrupt | ||
* source and priority is configured in the devicetree. Default entropy source | ||
* is used for getting random numbers. System work queue is used to get random | ||
* values and keep them in a ring buffer. | ||
* | ||
* @param active_avg Avarage time of busy looping in the counter callback (in microseconds). | ||
* @param active_delta Specifies deviation from avarage time of busy looping (in microseconds). | ||
* @param idle_avg Avarage time of counter alarm timeout (in microseconds). | ||
* @param idle_delta Specifies deviation from avarage time of counter alarm (in microseconds). | ||
*/ | ||
void busy_sim_start(uint32_t active_avg, uint32_t active_delta, | ||
uint32_t idle_avg, uint32_t idle_delta); | ||
|
||
/** @brief Stop busy simulator. */ | ||
void busy_sim_stop(void); | ||
|
||
#endif /* BUSY_SIM_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.13.1) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(uart_basic_api) | ||
|
||
target_sources(app PRIVATE | ||
src/main.c | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
CONFIG_COUNTER_TIMER0=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright (c) 2021 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
&timer0 { | ||
status = "okay"; | ||
interrupts = <8 0>; | ||
}; | ||
|
||
/ { | ||
busy-sim { | ||
compatible = "vnd,busy-sim"; | ||
status = "okay"; | ||
counter = <&timer0>; | ||
}; | ||
}; |
19 changes: 19 additions & 0 deletions
19
tests/ztest/busy_sim/boards/nrf52840dk_nrf52840_pin.overlay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (c) 2021 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
&timer0 { | ||
status = "okay"; | ||
interrupts = <8 0>; | ||
}; | ||
|
||
/ { | ||
busy-sim { | ||
compatible = "vnd,busy-sim"; | ||
status = "okay"; | ||
counter = <&timer0>; | ||
active-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
CONFIG_ZTEST=y | ||
CONFIG_TEST_BUSY_SIM=y | ||
CONFIG_ZTEST_THREAD_PRIORITY=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright (c) 2021 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <ztest.h> | ||
#include <busy_sim.h> | ||
|
||
static void test_busy_sim(void) | ||
{ | ||
uint32_t ms = 1000; | ||
uint32_t delta = 80; | ||
uint32_t busy_ms; | ||
uint32_t t = k_uptime_get_32(); | ||
|
||
k_busy_wait(1000 * ms); | ||
t = k_uptime_get_32() - t; | ||
|
||
zassert_true((t > (ms - delta)) && (t < (ms + delta)), NULL); | ||
|
||
/* Start busy simulator and check that k_busy_wait last longer */ | ||
t = k_uptime_get_32(); | ||
busy_sim_start(500, 200, 1000, 400); | ||
k_busy_wait(1000 * ms); | ||
t = k_uptime_get_32() - t; | ||
busy_ms = (3 * ms) / 2; | ||
|
||
busy_sim_stop(); | ||
/* due to clock imprecision, randomness and addtional cpu load overhead | ||
* expected time range is increased. | ||
*/ | ||
zassert_true((t > (busy_ms - 2 * delta)) && (t < (busy_ms + 4 * delta)), | ||
"expected in range: %d-%d, k_busy_wait lasted %d", | ||
busy_ms - 2 * delta, busy_ms + 4 * delta, t); | ||
|
||
/* Check that k_busy_wait is not interrupted after busy_sim_stop. */ | ||
t = k_uptime_get_32(); | ||
k_busy_wait(1000 * ms); | ||
t = k_uptime_get_32() - t; | ||
zassert_true((t > (ms - delta)) && (t < (ms + delta)), NULL); | ||
} | ||
|
||
void test_main(void) | ||
{ | ||
ztest_test_suite(busy_sim_tests, | ||
ztest_unit_test(test_busy_sim) | ||
); | ||
|
||
ztest_run_test_suite(busy_sim_tests); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
common: | ||
tags: test_framework | ||
depends_on: counter | ||
tests: | ||
testing.ztest.busy_sim: | ||
platform_allow: nrf52840dk_nrf52840 | ||
testing.ztest.busy_sim_nrf52840dk_pin: | ||
platform_allow: nrf52840dk_nrf52840 | ||
extra_args: DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840_pin.overlay |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some descriptions of these parameters would be helpful.