unit_tests: replace legacy timer group with gptimer

pull/8219/head
morris 2022-01-02 16:19:49 +08:00
rodzic 6bf3af7c8e
commit 705788a13f
18 zmienionych plików z 415 dodań i 663 usunięć

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -324,5 +324,5 @@ template<typename T> __attribute__((unused)) static void test_binary_operators()
}
//Add more types here. If any flags cannot pass the build, use FLAG_ATTR in esp_attr.h
#include "driver/timer.h"
#include "driver/timer_types_legacy.h"
template void test_binary_operators<timer_intr_t>();

Wyświetl plik

@ -8,8 +8,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_private/periph_ctrl.h"
#include "driver/timer.h"
#include "esp_event.h"
#include "esp_event_private.h"

Wyświetl plik

@ -7,8 +7,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_private/periph_ctrl.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "esp_event.h"
#include "esp_event_private.h"
@ -302,10 +301,6 @@ static void test_teardown(void)
TEST_ESP_OK(esp_event_loop_delete_default());
}
#define TIMER_DIVIDER 16 // Hardware timer clock divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds
#define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer
TEST_CASE("can create and delete event loops", "[event]")
{
/* this test aims to verify that:
@ -1973,63 +1968,51 @@ static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t
xSemaphoreGive(*sem);
}
void IRAM_ATTR test_event_on_timer_alarm(void* para)
bool test_event_on_timer_alarm(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
/* Retrieve the interrupt status and the counter value
from the timer that reported the interrupt */
uint64_t timer_counter_value =
timer_group_get_counter_value_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, TIMER_0, timer_counter_value);
int data = (int) para;
int data = (int)user_ctx;
gptimer_stop(timer);
// Posting events with data more than 4 bytes should fail.
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL));
// This should succeedd, as data is int-sized. The handler for the event checks that the passed event data
// is correct.
BaseType_t task_unblocked;
TEST_ESP_OK(esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked));
if (task_unblocked == pdTRUE) {
portYIELD_FROM_ISR();
}
return task_unblocked == pdTRUE;
}
TEST_CASE("can post events from interrupt handler", "[event]")
{
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
gptimer_handle_t gptimer = NULL;
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.intr_type = TIMER_INTR_LEVEL,
.auto_reload = false,
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick = 1us
};
timer_init(TIMER_GROUP_0, TIMER_0, &config);
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
/* Configure the alarm value and the interrupt on alarm. */
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE);
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm,
(void *) sem, ESP_INTR_FLAG_IRAM, NULL);
timer_start(TIMER_GROUP_0, TIMER_0);
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 500000,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = test_event_on_timer_alarm
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, sem));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
TEST_SETUP();
TEST_ESP_OK(esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1,
test_handler_post_from_isr, &sem));
test_handler_post_from_isr, &sem));
xSemaphoreTake(sem, portMAX_DELAY);
TEST_TEARDOWN();
TEST_ESP_OK(gptimer_del_timer(gptimer));
}
#endif // CONFIG_ESP_EVENT_POST_FROM_ISR

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,6 +8,7 @@
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "esp_types.h"
#include "esp_rom_sys.h"
#include "freertos/FreeRTOS.h"
@ -16,84 +17,52 @@
#include "freertos/queue.h"
#include "unity.h"
#include "esp_intr_alloc.h"
#include "esp_private/periph_ctrl.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "soc/soc_caps.h"
#include "soc/spi_periph.h"
#include "hal/spi_ll.h"
#include "sdkconfig.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/gptimer.h"
#define TIMER_DIVIDER (16) /*!< Hardware timer clock divider */
#define TIMER_SCALE (APB_CLK_FREQ / TIMER_DIVIDER) /*!< used to calculate counter value */
#define TIMER_INTERVAL0_SEC (3) /*!< test interval for timer 0 */
#define TIMER_INTERVAL1_SEC (5) /*!< test interval for timer 1 */
static void my_timer_init(int timer_group, int timer_idx, uint64_t alarm_value)
static bool on_timer_alarm(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
timer_config_t config = {
.alarm_en = 1,
.auto_reload = 1,
.counter_dir = TIMER_COUNT_UP,
.divider = TIMER_DIVIDER,
};
/*Configure timer*/
timer_init(timer_group, timer_idx, &config);
/*Stop timer counter*/
timer_pause(timer_group, timer_idx);
/*Load counter value */
timer_set_counter_value(timer_group, timer_idx, 0);
/*Set alarm value*/
timer_set_alarm_value(timer_group, timer_idx, alarm_value);
/*Enable timer interrupt*/
timer_enable_intr(timer_group, timer_idx);
}
static volatile int count[SOC_TIMER_GROUP_TOTAL_TIMERS] = {0};
static void timer_isr(void *arg)
{
int timer_idx = (int)arg;
int group_id = timer_idx / SOC_TIMER_GROUP_TIMERS_PER_GROUP;
int timer_id = timer_idx % SOC_TIMER_GROUP_TIMERS_PER_GROUP;
count[timer_idx]++;
timer_group_clr_intr_status_in_isr(group_id, timer_id);
timer_group_enable_alarm_in_isr(group_id, timer_id);
volatile int *count = (volatile int *)user_ctx;
(*count)++;
return false;
}
static void timer_test(int flags)
{
timer_isr_handle_t inth[SOC_TIMER_GROUP_TOTAL_TIMERS];
for (int i = 0; i < SOC_TIMER_GROUPS; i++) {
for (int j = 0; j < SOC_TIMER_GROUP_TIMERS_PER_GROUP; j++) {
my_timer_init(i, j, 100000 + 10000 * (i * SOC_TIMER_GROUP_TIMERS_PER_GROUP + j + 1));
}
}
timer_isr_register(0, 0, timer_isr, (void *)0, flags | ESP_INTR_FLAG_INTRDISABLED, &inth[0]);
printf("Interrupts allocated: %d (dis)\r\n", esp_intr_get_intno(inth[0]));
static int count[SOC_TIMER_GROUP_TOTAL_TIMERS] = {0};
gptimer_handle_t gptimers[SOC_TIMER_GROUP_TOTAL_TIMERS];
intr_handle_t inth[SOC_TIMER_GROUP_TOTAL_TIMERS];
for (int j = 1; j < SOC_TIMER_GROUP_TIMERS_PER_GROUP; j++) {
timer_isr_register(0, j, timer_isr, (void *)1, flags, &inth[j]);
printf("Interrupts allocated: %d\r\n", esp_intr_get_intno(inth[j]));
}
for (int i = 1; i < SOC_TIMER_GROUPS; i++) {
for (int j = 0; j < SOC_TIMER_GROUP_TIMERS_PER_GROUP; j++) {
timer_isr_register(i, j, timer_isr, (void *)(i * SOC_TIMER_GROUP_TIMERS_PER_GROUP + j), flags, &inth[i * SOC_TIMER_GROUP_TIMERS_PER_GROUP + j]);
printf("Interrupts allocated: %d\r\n", esp_intr_get_intno(inth[i * SOC_TIMER_GROUP_TIMERS_PER_GROUP + j]));
}
}
for (int i = 0; i < SOC_TIMER_GROUPS; i++) {
for (int j = 0; j < SOC_TIMER_GROUP_TIMERS_PER_GROUP; j++) {
timer_start(i, j);
}
}
printf("Timer values on start:");
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000,
.flags.intr_shared = (flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED,
};
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
count[i] = 0;
printf(" %d", count[i]);
TEST_ESP_OK(gptimer_new_timer(&config, &gptimers[i]));
}
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 100000,
.flags.auto_reload_on_alarm = true,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = on_timer_alarm,
};
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ESP_OK(gptimer_register_event_callbacks(gptimers[i], &cbs, &count[i]));
alarm_config.alarm_count += 10000 * i;
TEST_ESP_OK(gptimer_set_alarm_action(gptimers[i], &alarm_config));
TEST_ESP_OK(gptimer_start(gptimers[i]));
TEST_ESP_OK(gptimer_get_intr_handle(gptimers[i], &inth[i]));
printf("Interrupts allocated: %d\r\n", esp_intr_get_intno(inth[i]));
}
printf("\r\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("Timer values after 1 sec:");
@ -102,19 +71,13 @@ static void timer_test(int flags)
}
printf("\r\n");
TEST_ASSERT(count[0] == 0);
for (int i = 1; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ASSERT(count[i] != 0);
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ASSERT_NOT_EQUAL(0, count[i]);
}
printf("Disabling half of timers' interrupt...\r\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i++) {
esp_intr_disable(inth[i]);
}
for (int i = SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
esp_intr_enable(inth[i]);
}
printf("Disabling timers' interrupt...\r\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
esp_intr_disable(inth[i]);
count[i] = 0;
}
@ -124,38 +87,13 @@ static void timer_test(int flags)
printf(" %d", count[i]);
}
printf("\r\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i++) {
TEST_ASSERT(count[i] == 0);
}
for (int i = SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ASSERT(count[i] != 0);
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ASSERT_EQUAL(0, count[i]);
}
printf("Disabling another half...\r\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i++) {
esp_intr_enable(inth[i]);
}
for (int i = SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
esp_intr_disable(inth[i]);
}
for (int x = 0; x < SOC_TIMER_GROUP_TOTAL_TIMERS; x++) {
count[x] = 0;
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("Timer values after 1 sec:");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
printf(" %d", count[i]);
}
printf("\r\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i++) {
TEST_ASSERT(count[i] != 0);
}
for (int i = SOC_TIMER_GROUP_TOTAL_TIMERS / 2; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
TEST_ASSERT(count[i] == 0);
}
printf("Done.\n");
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
esp_intr_free(inth[i]);
TEST_ESP_OK(gptimer_stop(gptimers[i]));
TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
}
}

Wyświetl plik

@ -10,9 +10,10 @@
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "driver/rtc_io.h"
#include "soc/rtc.h"
#include "esp_private/gptimer.h"
#include "soc/rtc_periph.h"
#include "esp_rom_sys.h"
#include "esp_private/esp_clk.h"
@ -53,7 +54,8 @@ static void switch_freq(int mhz)
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
printf("Waiting for frequency to be set to %d MHz...\n", mhz);
while (esp_clk_cpu_freq() / MHZ != mhz) {
while (esp_clk_cpu_freq() / MHZ != mhz)
{
vTaskDelay(pdMS_TO_TICKS(200));
printf("Frequency is %d MHz\n", esp_clk_cpu_freq() / MHZ);
}
@ -70,7 +72,7 @@ TEST_CASE("Can switch frequency using esp_pm_configure", "[pm]")
{
int orig_freq_mhz = esp_clk_cpu_freq() / MHZ;
for (int i = 0; i < sizeof(test_freqs)/sizeof(int); i++) {
for (int i = 0; i < sizeof(test_freqs) / sizeof(int); i++) {
switch_freq(test_freqs[i]);
}
@ -125,16 +127,23 @@ static void light_sleep_disable(void)
TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
{
/* To figure out if light sleep takes place, use Timer Group timer.
gptimer_handle_t gptimer = NULL;
/* To figure out if light sleep takes place, use GPTimer
* It will stop working while in light sleep.
*/
timer_config_t config = {
.counter_dir = TIMER_COUNT_UP,
.divider = 80 /* 1 us per tick */
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, /* 1 us per tick */
};
timer_init(TIMER_GROUP_0, TIMER_0, &config);
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
timer_start(TIMER_GROUP_0, TIMER_0);
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
TEST_ESP_OK(gptimer_start(gptimer));
// if GPTimer is clocked from APB, when PM is enabled, the driver will acquire the PM lock
// causing the auto light sleep doesn't take effect
// so we manually release the lock here
esp_pm_lock_handle_t gptimer_pm_lock;
TEST_ESP_OK(gptimer_get_pm_lock(gptimer, &gptimer_pm_lock));
TEST_ESP_OK(esp_pm_lock_release(gptimer_pm_lock));
light_sleep_enable();
@ -147,11 +156,10 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
/* The following delay should cause light sleep to start */
uint64_t count_start;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &count_start);
vTaskDelay(ticks_to_delay);
uint64_t count_end;
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &count_end);
TEST_ESP_OK(gptimer_get_raw_count(gptimer, &count_start));
vTaskDelay(ticks_to_delay);
TEST_ESP_OK(gptimer_get_raw_count(gptimer, &count_end));
int timer_diff_us = (int) (count_end - count_start);
const int us_per_tick = 1 * portTICK_PERIOD_MS * 1000;
@ -161,6 +169,9 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]")
}
light_sleep_disable();
TEST_ESP_OK(esp_pm_lock_acquire(gptimer_pm_lock));
TEST_ESP_OK(gptimer_stop(gptimer));
TEST_ESP_OK(gptimer_del_timer(gptimer));
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
@ -185,22 +196,22 @@ TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm][ignore]")
rtc_gpio_set_direction(ext1_wakeup_gpio, RTC_GPIO_MODE_INPUT_OUTPUT);
rtc_gpio_set_level(ext1_wakeup_gpio, 0);
/* Enable wakeup */
/* Enable wakeup */
TEST_ESP_OK(esp_sleep_enable_ext1_wakeup(1ULL << ext1_wakeup_gpio, ESP_EXT1_WAKEUP_ANY_HIGH));
/* To simplify test environment, we'll use a ULP program to set GPIO high */
ulp_insn_t ulp_code[] = {
I_DELAY(65535), /* about 8ms, given 8MHz ULP clock */
I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 0),
I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 1),
I_DELAY(1000),
I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 0),
I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 1),
I_END(),
I_HALT()
I_DELAY(65535), /* about 8ms, given 8MHz ULP clock */
I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 0),
I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 1),
I_DELAY(1000),
I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 0),
I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 1),
I_END(),
I_HALT()
};
TEST_ESP_OK(ulp_set_wakeup_period(0, 1000 /* us */));
size_t size = sizeof(ulp_code)/sizeof(ulp_insn_t);
size_t size = sizeof(ulp_code) / sizeof(ulp_insn_t);
TEST_ESP_OK(ulp_process_macros_and_load(0, ulp_code, &size));
light_sleep_enable();
@ -249,9 +260,9 @@ typedef struct {
SemaphoreHandle_t done;
} delay_test_arg_t;
static void test_delay_task(void* p)
static void test_delay_task(void *p)
{
delay_test_arg_t* arg = (delay_test_arg_t*) p;
delay_test_arg_t *arg = (delay_test_arg_t *) p;
vTaskDelay(1);
uint64_t start = esp_clk_rtc_time();
@ -266,9 +277,11 @@ static void test_delay_task(void* p)
TEST_CASE("vTaskDelay duration is correct with light sleep enabled", "[pm]")
{
light_sleep_enable();
SemaphoreHandle_t done_sem = xSemaphoreCreateBinary();
TEST_ASSERT_NOT_NULL(done_sem);
delay_test_arg_t args = {
.done = xSemaphoreCreateBinary()
.done = done_sem,
};
const int delays[] = { 10, 20, 50, 100, 150, 200, 250 };
@ -278,19 +291,19 @@ TEST_CASE("vTaskDelay duration is correct with light sleep enabled", "[pm]")
int delay_ms = delays[i];
args.delay_us = delay_ms * 1000;
xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void*) &args, 3, NULL, 0);
TEST_ASSERT( xSemaphoreTake(args.done, delay_ms * 10 / portTICK_PERIOD_MS) );
xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void *) &args, 3, NULL, 0);
TEST_ASSERT( xSemaphoreTake(done_sem, delay_ms * 10 / portTICK_PERIOD_MS) );
printf("CPU0: %d %d\n", args.delay_us, args.result);
TEST_ASSERT_INT32_WITHIN(1000 * portTICK_PERIOD_MS * 2, args.delay_us, args.result);
#if portNUM_PROCESSORS == 2
xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void*) &args, 3, NULL, 1);
TEST_ASSERT( xSemaphoreTake(args.done, delay_ms * 10 / portTICK_PERIOD_MS) );
xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void *) &args, 3, NULL, 1);
TEST_ASSERT( xSemaphoreTake(done_sem, delay_ms * 10 / portTICK_PERIOD_MS) );
printf("CPU1: %d %d\n", args.delay_us, args.result);
TEST_ASSERT_INT32_WITHIN(1000 * portTICK_PERIOD_MS * 2, args.delay_us, args.result);
#endif
}
vSemaphoreDelete(args.done);
vSemaphoreDelete(done_sem);
light_sleep_disable();
}
@ -312,16 +325,15 @@ TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]")
SemaphoreHandle_t done;
} test_args_t;
void timer_func(void* arg)
{
test_args_t* p_args = (test_args_t*) arg;
void timer_func(void *arg) {
test_args_t *p_args = (test_args_t *) arg;
int64_t t_end = esp_clk_rtc_time();
int32_t ms_diff = (t_end - p_args->t_start) / 1000;
printf("timer #%d %dms\n", p_args->cur_interval, ms_diff);
p_args->intervals[p_args->cur_interval++] = ms_diff;
// Deliberately make timer handler run longer.
// We check that this doesn't affect the result.
esp_rom_delay_us(10*1000);
esp_rom_delay_us(10 * 1000);
if (p_args->cur_interval == NUM_INTERVALS) {
printf("done\n");
TEST_ESP_OK(esp_timer_stop(p_args->timer));
@ -335,9 +347,9 @@ TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]")
test_args_t args = {0};
esp_timer_handle_t timer1;
esp_timer_create_args_t create_args = {
.callback = &timer_func,
.arg = &args,
.name = "timer1",
.callback = timer_func,
.arg = &args,
.name = "timer1",
};
TEST_ESP_OK(esp_timer_create(&create_args, &timer1));
@ -365,7 +377,7 @@ TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]")
static void timer_cb1(void *arg)
{
++*((int*) arg);
++*((int *) arg);
}
TEST_CASE("esp_timer with SKIP_UNHANDLED_EVENTS does not wake up CPU from sleep", "[pm]")
@ -374,10 +386,10 @@ TEST_CASE("esp_timer with SKIP_UNHANDLED_EVENTS does not wake up CPU from sleep"
int timer_interval_ms = 50;
const esp_timer_create_args_t timer_args = {
.name = "timer_cb1",
.arg = &count_calls,
.callback = &timer_cb1,
.skip_unhandled_events = true,
.name = "timer_cb1",
.arg = &count_calls,
.callback = &timer_cb1,
.skip_unhandled_events = true,
};
esp_timer_handle_t periodic_timer;
esp_timer_create(&timer_args, &periodic_timer);

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -11,7 +11,7 @@
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "esp_heap_caps.h"
#include "esp_spi_flash.h"
#include "unity.h"
@ -29,7 +29,8 @@
static const uint8_t small_item[SMALL_ITEM_SIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
static const uint8_t large_item[LARGE_ITEM_SIZE] = { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
};
static RingbufHandle_t buffer_handles[NO_OF_RB_TYPES];
static SemaphoreHandle_t done_sem;
@ -87,9 +88,9 @@ static void receive_check_and_return_item_allow_split(RingbufHandle_t handle, co
uint8_t *item1, *item2;
BaseType_t ret;
if (in_isr) {
ret = xRingbufferReceiveSplitFromISR(handle, (void**)&item1, (void **)&item2, &item_size1, &item_size2);
ret = xRingbufferReceiveSplitFromISR(handle, (void **)&item1, (void **)&item2, &item_size1, &item_size2);
} else {
ret = xRingbufferReceiveSplit(handle, (void**)&item1, (void **)&item2, &item_size1, &item_size2, ticks_to_wait);
ret = xRingbufferReceiveSplit(handle, (void **)&item1, (void **)&item2, &item_size1, &item_size2, ticks_to_wait);
}
TEST_ASSERT_MESSAGE(ret == pdTRUE, "Failed to receive item");
TEST_ASSERT_MESSAGE(item1 != NULL, "Failed to receive item");
@ -643,7 +644,7 @@ static void queue_set_receiving_task(void *queue_set_handle)
//Allow-split buffer
receive_check_and_return_item_allow_split(buffer_handles[1], small_item, SMALL_ITEM_SIZE, 0, false);
items_rec_count[1] ++;
} else if (xRingbufferCanRead(buffer_handles[2], member) == pdTRUE){
} else if (xRingbufferCanRead(buffer_handles[2], member) == pdTRUE) {
//Byte buffer
receive_check_and_return_item_byte_buffer(buffer_handles[2], small_item, SMALL_ITEM_SIZE, 0, false);
items_rec_count[2] ++;
@ -653,8 +654,8 @@ static void queue_set_receiving_task(void *queue_set_handle)
//Check for completion
if (items_rec_count[0] == no_of_items &&
items_rec_count[1] == no_of_items &&
items_rec_count[2] == no_of_items) {
items_rec_count[1] == no_of_items &&
items_rec_count[2] == no_of_items) {
done = pdTRUE;
}
}
@ -676,7 +677,7 @@ TEST_CASE("Test ring buffer with queue sets", "[esp_ringbuf]")
}
//Create a task to send items to each ring buffer
int no_of_items = BUFFER_SIZE / SMALL_ITEM_SIZE;
xTaskCreatePinnedToCore(queue_set_receiving_task, "rec tsk", 2048, (void *)queue_set, UNITY_FREERTOS_PRIORITY + 1 , NULL, 0);
xTaskCreatePinnedToCore(queue_set_receiving_task, "rec tsk", 2048, (void *)queue_set, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
//Send multiple items to each type of ring buffer
for (int i = 0; i < no_of_items; i++) {
@ -687,7 +688,7 @@ TEST_CASE("Test ring buffer with queue sets", "[esp_ringbuf]")
xSemaphoreTake(done_sem, portMAX_DELAY);
vSemaphoreDelete(done_sem);
//Remove and delete ring buffers from queue sets
//Remove and delete ring buffers from queue sets
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
TEST_ASSERT_MESSAGE(xRingbufferRemoveFromQueueSetRead(buffer_handles[i], queue_set) == pdTRUE, "Failed to remove from read queue set");
vRingbufferDelete(buffer_handles[i]);
@ -703,19 +704,14 @@ TEST_CASE("Test ring buffer with queue sets", "[esp_ringbuf]")
* will send then receive an item to a ring buffer.
*/
#define TIMER_GROUP 0
#define TIMER_NUMBER 0
#define ISR_ITERATIONS ((BUFFER_SIZE / SMALL_ITEM_SIZE) * 2)
intr_handle_t ringbuffer_isr_handle;
static int buf_type;
static int iterations;
static void ringbuffer_isr(void *arg)
static bool on_timer_alarm(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
//Clear timer interrupt
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, xPortGetCoreID());
bool need_yield = false;
//Test sending to buffer from ISR from ISR
if (buf_type < NO_OF_RB_TYPES) {
@ -740,63 +736,56 @@ static void ringbuffer_isr(void *arg)
if (iterations < ISR_ITERATIONS) {
iterations++;
buf_type = 0; //Reset and iterate through each buffer type again
return;
goto out;
} else {
//Signal complete
BaseType_t task_woken = pdFALSE;
xSemaphoreGiveFromISR(done_sem, &task_woken);
if (task_woken == pdTRUE) {
buf_type++;
portYIELD_FROM_ISR();
need_yield = true;
}
}
}
}
static void setup_timer(void)
{
//Setup timer for ISR
int timer_group = TIMER_GROUP;
int timer_idx = TIMER_NUMBER;
timer_config_t config = {
.alarm_en = 1,
.auto_reload = 1,
.counter_dir = TIMER_COUNT_UP,
.divider = 10000,
.intr_type = TIMER_INTR_LEVEL,
.counter_en = TIMER_PAUSE,
};
timer_init(timer_group, timer_idx, &config); //Configure timer
timer_pause(timer_group, timer_idx); //Stop timer counter
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); //Load counter value
timer_set_alarm_value(timer_group, timer_idx, 20); //Set alarm value
timer_enable_intr(timer_group, timer_idx); //Enable timer interrupt
timer_set_auto_reload(timer_group, timer_idx, 1); //Auto Reload
timer_isr_register(timer_group, timer_idx, ringbuffer_isr, NULL, 0, &ringbuffer_isr_handle); //Set ISR handler
}
static void cleanup_timer(void)
{
timer_disable_intr(TIMER_GROUP, TIMER_NUMBER);
esp_intr_free(ringbuffer_isr_handle);
out:
return need_yield;
}
TEST_CASE("Test ring buffer ISR", "[esp_ringbuf]")
{
gptimer_handle_t gptimer;
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
buffer_handles[i] = xRingbufferCreate(BUFFER_SIZE, i);
}
done_sem = xSemaphoreCreateBinary();
buf_type = 0;
iterations = 0;
setup_timer();
//Start timer to trigger ISR
timer_start(TIMER_GROUP, TIMER_NUMBER);
//Setup timer for ISR
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000,
};
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 2000,
.flags.auto_reload_on_alarm = true,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = on_timer_alarm,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
//Wait for ISR to complete multiple iterations
xSemaphoreTake(done_sem, portMAX_DELAY);
//Cleanup
cleanup_timer();
TEST_ESP_OK(gptimer_stop(gptimer));
TEST_ESP_OK(gptimer_del_timer(gptimer));
vSemaphoreDelete(done_sem);
for (int i = 0; i < NO_OF_RB_TYPES; i++) {
vRingbufferDelete(buffer_handles[i]);
@ -819,7 +808,8 @@ static const char continuous_data[] = {"A_very_long_string_that_will_be_split_in
"items_of_random_lengths_and_sent_to_the_ring_"
"buffer._The_maximum_random_length_will_also_"
"be_increased_over_multiple_iterations_in_this"
"_test"};
"_test"
};
#define CONT_DATA_LEN sizeof(continuous_data)
//32-bit aligned size that guarantees a wrap around at some point
#define CONT_DATA_TEST_BUFF_LEN (((CONT_DATA_LEN/2) + 0x03) & ~0x3)
@ -847,7 +837,7 @@ static void send_to_buffer(RingbufHandle_t buffer, size_t max_item_size)
}
//Send item
TEST_ASSERT_MESSAGE(xRingbufferSend(buffer, (void *)&(continuous_data[bytes_sent]), next_item_size, TIMEOUT_TICKS) == pdTRUE, "Failed to send an item");
TEST_ASSERT_MESSAGE(xRingbufferSend(buffer, (void *) & (continuous_data[bytes_sent]), next_item_size, TIMEOUT_TICKS) == pdTRUE, "Failed to send an item");
bytes_sent += next_item_size;
}
xSemaphoreGive(tx_done);
@ -907,7 +897,7 @@ static void send_task(void *args)
//Test sending short length items
send_to_buffer(buffer, 1);
//Test sending mid length items
send_to_buffer(buffer, max_item_len/2);
send_to_buffer(buffer, max_item_len / 2);
//Test sending long length items
send_to_buffer(buffer, max_item_len);
vTaskDelete(NULL);
@ -921,7 +911,7 @@ static void rec_task(void *args)
//Test receiving short length items
read_from_buffer(buffer, ((task_args_t *)args)->type, 1);
//Test receiving mid length items
read_from_buffer(buffer, ((task_args_t *)args)->type, max_rec_len/2);
read_from_buffer(buffer, ((task_args_t *)args)->type, max_rec_len / 2);
//Test receiving long length items
read_from_buffer(buffer, ((task_args_t *)args)->type, max_rec_len);
@ -988,10 +978,10 @@ TEST_CASE("Test static ring buffer SMP", "[esp_ringbuf]")
//Allocate memory and create semaphores
#if CONFIG_SPIRAM_USE_CAPS_ALLOC //When SPIRAM can only be allocated using heap_caps_malloc()
buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM);
buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*CONT_DATA_TEST_BUFF_LEN, MALLOC_CAP_SPIRAM);
buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t) * CONT_DATA_TEST_BUFF_LEN, MALLOC_CAP_SPIRAM);
#else //Case where SPIRAM is disabled or when SPIRAM is allocatable through malloc()
buffer_struct = (StaticRingbuffer_t *)malloc(sizeof(StaticRingbuffer_t));
buffer_storage = (uint8_t *)malloc(sizeof(uint8_t)*CONT_DATA_TEST_BUFF_LEN);
buffer_storage = (uint8_t *)malloc(sizeof(uint8_t) * CONT_DATA_TEST_BUFF_LEN);
#endif
TEST_ASSERT(buffer_struct != NULL && buffer_storage != NULL);

Wyświetl plik

@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* FreeModbus Libary: ESP32 Port Demo Application
@ -39,7 +39,6 @@
/* ----------------------- Platform includes --------------------------------*/
#include "driver/uart.h"
#include "driver/timer.h"
#include "esp_log.h" // for ESP_LOGE macro
#include "mb_m.h"
#include "port.h"

Wyświetl plik

@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* FreeModbus Libary: ESP32 Port Demo Application
@ -40,7 +40,6 @@
/* ----------------------- Platform includes --------------------------------*/
#include "driver/uart.h"
#include "driver/timer.h"
#include "esp_log.h"
#include "port.h"

Wyświetl plik

@ -5,15 +5,9 @@
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "unity.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define int_clr_timers int_clr
#define update update.update
#define int_st_timers int_st
#endif
#define BIT_CALL (1 << 0)
#define BIT_RESPONSE(TASK) (1 << (TASK+1))
#define ALL_RESPONSE_BITS (((1 << NUM_TASKS) - 1) << 1)
@ -72,7 +66,7 @@ TEST_CASE("FreeRTOS Event Groups", "[freertos]")
/* Ensure all tasks cleaned up correctly */
for (int c = 0; c < NUM_TASKS; c++) {
TEST_ASSERT( xSemaphoreTake(done_sem, 100/portTICK_PERIOD_MS) );
TEST_ASSERT( xSemaphoreTake(done_sem, 100 / portTICK_PERIOD_MS) );
}
vSemaphoreDelete(done_sem);
@ -117,7 +111,7 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
/* Ensure all tasks cleaned up correctly */
for (int c = 0; c < NUM_TASKS; c++) {
TEST_ASSERT( xSemaphoreTake(done_sem, 100/portTICK_PERIOD_MS) );
TEST_ASSERT( xSemaphoreTake(done_sem, 100 / portTICK_PERIOD_MS) );
}
vSemaphoreDelete(done_sem);
@ -132,63 +126,27 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
*/
//Use a timer to trigger an ISr
#define TIMER_DIVIDER 10000
#define TIMER_COUNT 100
#define TIMER_NUMBER 0
#define BITS 0xAA
static timer_isr_handle_t isr_handle;
static gptimer_handle_t gptimer;
static bool test_set_bits;
static bool test_clear_bits;
static void IRAM_ATTR event_group_isr(void *arg)
static bool on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
portBASE_TYPE task_woken = pdFALSE;
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, xPortGetCoreID());
if(test_set_bits){
gptimer_stop(timer);
if (test_set_bits) {
xEventGroupSetBitsFromISR(eg, BITS, &task_woken);
timer_pause(TIMER_GROUP_0, TIMER_NUMBER);
test_set_bits = false;
} else if (test_clear_bits){
} else if (test_clear_bits) {
xEventGroupClearBitsFromISR(eg, BITS);
xSemaphoreGiveFromISR(done_sem, &task_woken);
timer_pause(TIMER_GROUP_0, TIMER_NUMBER);
test_clear_bits = false;
}
//Switch context if necessary
if(task_woken == pdTRUE){
portYIELD_FROM_ISR();
}
}
static void setup_timer(void)
{
//Setup timer for ISR
int timer_group = TIMER_GROUP_0;
int timer_idx = TIMER_NUMBER;
timer_config_t config = {
.alarm_en = 1,
.auto_reload = 1,
.counter_dir = TIMER_COUNT_UP,
.divider = TIMER_DIVIDER,
.intr_type = TIMER_INTR_LEVEL,
.counter_en = TIMER_PAUSE,
};
timer_init(timer_group, timer_idx, &config); //Configure timer
timer_pause(timer_group, timer_idx); //Stop timer counter
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); //Load counter value
timer_set_alarm_value(timer_group, timer_idx, TIMER_COUNT); //Set alarm value
timer_enable_intr(timer_group, timer_idx); //Enable timer interrupt
timer_set_auto_reload(timer_group, timer_idx, 1); //Auto Reload
timer_isr_register(timer_group, timer_idx, event_group_isr, NULL, ESP_INTR_FLAG_IRAM, &isr_handle); //Set ISR handler
}
static void cleanup_timer(void)
{
timer_disable_intr(TIMER_GROUP_0, TIMER_NUMBER);
esp_intr_free(isr_handle);
return task_woken == pdTRUE;
}
TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
@ -197,23 +155,41 @@ TEST_CASE("FreeRTOS Event Group ISR", "[freertos]")
eg = xEventGroupCreate();
test_set_bits = false;
test_clear_bits = false;
setup_timer(); //Init timer to trigger ISR
//Setup timer for ISR
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000,
};
TEST_ESP_OK(gptimer_new_timer(&config, &gptimer));
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 200000,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = on_timer_alarm_cb,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
//Test set bits
printf("test set bits\r\n");
test_set_bits = true;
timer_start(TIMER_GROUP_0, TIMER_NUMBER);
TEST_ESP_OK(gptimer_start(gptimer));
TEST_ASSERT_EQUAL(BITS, xEventGroupWaitBits(eg, BITS, pdFALSE, pdTRUE, portMAX_DELAY)); //Let ISR set event group bits
//Test clear bits
printf("test clear bits\r\n");
xEventGroupSetBits(eg, BITS); //Set bits to be cleared
test_clear_bits = true;
timer_start(TIMER_GROUP_0, TIMER_NUMBER);
TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0));
TEST_ESP_OK(gptimer_start(gptimer));
xSemaphoreTake(done_sem, portMAX_DELAY); //Wait for ISR to clear bits
vTaskDelay(10); //Event group clear bits runs via daemon task, delay so daemon can run
TEST_ASSERT_EQUAL(0, xEventGroupGetBits(eg)); //Check bits are cleared
//Clean up
cleanup_timer();
TEST_ESP_OK(gptimer_del_timer(gptimer));
vEventGroupDelete(eg);
vSemaphoreDelete(done_sem);
vTaskDelay(10); //Give time for idle task to clear up deleted tasks

Wyświetl plik

@ -9,30 +9,20 @@
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <freertos/semphr.h>
#include "driver/timer.h"
#ifndef CONFIG_FREERTOS_UNICORE
#include "esp_ipc.h"
#endif
#include "freertos/semphr.h"
#include "driver/gptimer.h"
#include "unity.h"
#include "test_utils.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define int_clr_timers int_clr
#define update update.update
#define int_st_timers int_st
#endif
#define NO_OF_NOTIFS 4
#define NO_OF_TASKS 2 //Sender and receiver
#define TIMER_DIVIDER 10000
#define TIMER_COUNT 100
#define MESSAGE 0xFF
#define MESSAGE 0xFF
static uint32_t send_core_message = 0;
static TaskHandle_t rec_task_handle;
static TaskHandle_t recv_task_handle;
static bool isr_give = false;
static bool test_start = false;
static gptimer_handle_t gptimers[portNUM_PROCESSORS];
static SemaphoreHandle_t trigger_send_semphr;
static SemaphoreHandle_t task_delete_semphr;
@ -41,40 +31,77 @@ static volatile uint32_t notifs_sent = 0;
static volatile uint32_t notifs_rec = 0;
static bool wrong_core = false;
static void sender_task (void* arg){
static bool on_alarm_sender_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
gptimer_stop(timer);
if (!test_start) {
return false;
}
int curcore = xPortGetCoreID();
if (isr_give) { //Test vTaskNotifyGiveFromISR() on same core
notifs_sent++;
vTaskNotifyGiveFromISR(recv_task_handle, NULL);
} else { //Test xTaskNotifyFromISR()
notifs_sent++;
xTaskNotifyFromISR(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
}
// always trigger a task switch when exit ISR context
return true;
}
static void test_gptimer_start(void *arg)
{
gptimer_handle_t gptimer = (gptimer_handle_t)arg;
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 1000,
};
TEST_ESP_OK(gptimer_set_raw_count(gptimer, 0));
gptimer_event_callbacks_t cbs = {
.on_alarm = on_alarm_sender_cb,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
}
static void sender_task(void *arg)
{
gptimer_handle_t gptimer = (gptimer_handle_t)arg;
int curcore = xPortGetCoreID();
//Test xTaskNotify
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
notifs_sent++;
xTaskNotify(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
xTaskNotify(recv_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite);
//Test xTaskNotifyGive
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
notifs_sent++;
xTaskNotifyGive(rec_task_handle);
xTaskNotifyGive(recv_task_handle);
//Test xTaskNotifyFromISR
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
isr_give = false;
timer_start(TIMER_GROUP_0, curcore);
test_gptimer_start(gptimer);
//Test vTaskNotifyGiveFromISR
xSemaphoreTake(trigger_send_semphr, portMAX_DELAY);
isr_give = true;
timer_start(TIMER_GROUP_0, curcore);
test_gptimer_start(gptimer);
//Delete Task and Semaphores
xSemaphoreGive(task_delete_semphr);
vTaskDelete(NULL);
}
static void receiver_task (void* arg){
static void receiver_task(void *arg)
{
uint32_t notify_value;
//Test xTaskNotifyWait from task
xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
if(notify_value != send_core_message){
if (notify_value != send_core_message) {
wrong_core = true;
}
notifs_rec++;
@ -87,7 +114,7 @@ static void receiver_task (void* arg){
//Test xTaskNotifyWait from ISR
xSemaphoreGive(trigger_send_semphr);
xTaskNotifyWait(0, 0xFFFFFFFF, &notify_value, portMAX_DELAY);
if(notify_value != send_core_message){
if (notify_value != send_core_message) {
wrong_core = true;
}
notifs_rec++;
@ -102,111 +129,62 @@ static void receiver_task (void* arg){
vTaskDelete(NULL);
}
static void IRAM_ATTR sender_ISR (void *arg)
static void install_gptimer_on_core(void *arg)
{
int curcore = xPortGetCoreID();
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, curcore);
timer_group_set_counter_enable_in_isr(TIMER_GROUP_0, curcore, TIMER_PAUSE);
//Re-enable alarm
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, curcore);
if(isr_give){ //Test vTaskNotifyGiveFromISR() on same core
notifs_sent++;
vTaskNotifyGiveFromISR(rec_task_handle, NULL);
}
else { //Test xTaskNotifyFromISR()
notifs_sent++;
xTaskNotifyFromISR(rec_task_handle, (MESSAGE << curcore), eSetValueWithOverwrite, NULL);
}
portYIELD_FROM_ISR();
return;
}
static void timerg0_init(void *isr_handle)
{
int timer_group = TIMER_GROUP_0;
int timer_idx = xPortGetCoreID();
timer_config_t config = {
.alarm_en = 1,
.auto_reload = 1,
.counter_dir = TIMER_COUNT_UP,
.divider = TIMER_DIVIDER,
.intr_type = TIMER_INTR_LEVEL,
.counter_en = TIMER_PAUSE,
int core_id = (int)arg;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick = 1us
};
/*Configure timer*/
timer_init(timer_group, timer_idx, &config);
/*Stop timer counter*/
timer_pause(timer_group, timer_idx);
/*Load counter value */
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
/*Set alarm value*/
timer_set_alarm_value(timer_group, timer_idx, TIMER_COUNT);
/*Enable timer interrupt*/
timer_enable_intr(timer_group, timer_idx);
//Auto Reload
timer_set_auto_reload(timer_group, timer_idx, 1);
/*Set ISR handler*/
timer_isr_register(timer_group, timer_idx, sender_ISR, NULL, ESP_INTR_FLAG_IRAM, (intr_handle_t *)isr_handle);
}
static void timerg0_deinit(void* isr_handle)
{
int timer_group = TIMER_GROUP_0;
int timer_idx = xPortGetCoreID();
intr_handle_t handle = *((intr_handle_t *) isr_handle);
//Pause timer then free registered ISR
timer_pause(timer_group, timer_idx);
esp_intr_free(handle);
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimers[core_id]));
test_gptimer_start(gptimers[core_id]);
xSemaphoreGive(task_delete_semphr);
vTaskDelete(NULL);
}
TEST_CASE("Test Task_Notify", "[freertos]")
{
//Initialize and pause timers. Used to trigger ISR
intr_handle_t isr_handle_0 = NULL;
timerg0_init(&isr_handle_0); //Core 0 timer
#ifndef CONFIG_FREERTOS_UNICORE
intr_handle_t isr_handle_1 = NULL;
esp_ipc_call(1, timerg0_init, &isr_handle_1); //Core 1 timer
#endif
test_start = false;
trigger_send_semphr = xSemaphoreCreateBinary();
task_delete_semphr = xQueueCreateCountingSemaphore(NO_OF_TASKS, 0);
for(int i = 0; i < portNUM_PROCESSORS; i++){ //Sending Core
for(int j = 0; j < portNUM_PROCESSORS; j++){ //Receiving Core
task_delete_semphr = xQueueCreateCountingSemaphore(10, 0);
for (int i = 0; i < portNUM_PROCESSORS; i++) {
xTaskCreatePinnedToCore(install_gptimer_on_core, "install_gptimer", 4096, (void *const)i, UNITY_FREERTOS_PRIORITY + 1, NULL, i);
TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(1000)));
}
// wait the gptimer installation done on specific core
vTaskDelay(10);
// test start
test_start = true;
for (int i = 0; i < portNUM_PROCESSORS; i++) { //Sending Core
for (int j = 0; j < portNUM_PROCESSORS; j++) { //Receiving Core
//Reset Values
notifs_sent = 0;
notifs_rec = 0;
wrong_core = false;
send_core_message = (0xFF << i); //0xFF if core 0, 0xFF0 if core 1
xTaskCreatePinnedToCore(receiver_task, "rec task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &rec_task_handle, j);
xTaskCreatePinnedToCore(sender_task, "send task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 1, NULL, i);
send_core_message = (0xFF << i); //0xFF if core 0, 0xFF0 if core 1
// receiver task has higher priority than sender task
xTaskCreatePinnedToCore(receiver_task, "recv task", 1000, NULL, UNITY_FREERTOS_PRIORITY + 2, &recv_task_handle, j);
xTaskCreatePinnedToCore(sender_task, "send task", 1000, gptimers[i], UNITY_FREERTOS_PRIORITY + 1, NULL, i);
vTaskDelay(5); //Wait for task creation to complete
xSemaphoreGive(trigger_send_semphr); //Trigger sender task
for(int k = 0; k < NO_OF_TASKS; k++){ //Wait for sender and receiver task deletion
TEST_ASSERT( xSemaphoreTake(task_delete_semphr, 1000 / portTICK_PERIOD_MS) );
for (int k = 0; k < NO_OF_TASKS; k++) { //Wait for sender and receiver task deletion
TEST_ASSERT(xSemaphoreTake(task_delete_semphr, pdMS_TO_TICKS(2000)));
}
vTaskDelay(5); //Give time tasks to delete
TEST_ASSERT(notifs_sent == NO_OF_NOTIFS);
TEST_ASSERT(notifs_rec == NO_OF_NOTIFS);
TEST_ASSERT(wrong_core == false);
TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_sent);
TEST_ASSERT_EQUAL(NO_OF_NOTIFS, notifs_rec);
TEST_ASSERT_EQUAL(false, wrong_core);
}
}
//Delete Semaphroes and timer ISRs
vSemaphoreDelete(trigger_send_semphr);
vSemaphoreDelete(task_delete_semphr);
timerg0_deinit(&isr_handle_0);
isr_handle_0 = NULL;
#ifndef CONFIG_FREERTOS_UNICORE
esp_ipc_call(1, timerg0_deinit, &isr_handle_1);
isr_handle_1 = NULL;
#endif
for (int i = 0; i < portNUM_PROCESSORS; i++) {
TEST_ESP_OK(gptimer_stop(gptimers[i]));
TEST_ESP_OK(gptimer_del_timer(gptimers[i]));
}
}

Wyświetl plik

@ -8,7 +8,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <freertos/semphr.h>
#include "driver/timer.h"
#include "unity.h"
#include "test_utils.h"

Wyświetl plik

@ -7,33 +7,24 @@
#include "freertos/queue.h"
#include "unity.h"
#include "test_utils.h"
#include "driver/timer.h"
#include "esp_intr_alloc.h"
#include "driver/gptimer.h"
#include "esp_private/gptimer.h"
#include "sdkconfig.h"
#include "esp_rom_sys.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define int_clr_timers int_clr
#define update update.update
#define int_st_timers int_st
#endif
static SemaphoreHandle_t isr_semaphore;
static volatile unsigned isr_count;
/* Timer ISR increments an ISR counter, and signals a
mutex semaphore to wake up another counter task */
static void timer_group0_isr(void *vp_arg)
static bool on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
portBASE_TYPE higher_awoken = pdFALSE;
isr_count++;
xSemaphoreGiveFromISR(isr_semaphore, &higher_awoken);
if (higher_awoken == pdTRUE) {
portYIELD_FROM_ISR();
}
return higher_awoken == pdTRUE;
}
typedef struct {
@ -45,7 +36,7 @@ static void counter_task_fn(void *vp_config)
{
counter_config_t *config = (counter_config_t *)vp_config;
printf("counter_task running...\n");
while(1) {
while (1) {
xSemaphoreTake(config->trigger_sem, portMAX_DELAY);
config->counter++;
}
@ -59,9 +50,11 @@ static void counter_task_fn(void *vp_config)
TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[freertos]")
{
isr_count = 0;
isr_semaphore = xSemaphoreCreateBinary();
TaskHandle_t counter_task;
intr_handle_t isr_handle = NULL;
gptimer_handle_t gptimer = NULL;
intr_handle_t intr_handle = NULL;
isr_semaphore = xSemaphoreCreateBinary();
TEST_ASSERT_NOT_NULL(isr_semaphore);
counter_config_t count_config = {
.trigger_sem = isr_semaphore,
@ -71,25 +64,26 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
&count_config, UNITY_FREERTOS_PRIORITY + 1,
&counter_task, UNITY_FREERTOS_CPU);
/* Configure timer ISR */
const timer_config_t timer_config = {
.alarm_en = 1,
.auto_reload = 1,
.counter_dir = TIMER_COUNT_UP,
.divider = 2, //Range is 2 to 65536
.intr_type = TIMER_INTR_LEVEL,
.counter_en = TIMER_PAUSE,
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick=1us
};
/* Configure timer */
timer_init(TIMER_GROUP_0, TIMER_0, &timer_config);
timer_pause(TIMER_GROUP_0, TIMER_0);
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1000);
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_group0_isr, NULL, 0, &isr_handle);
timer_start(TIMER_GROUP_0, TIMER_0);
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 1000, // alarm period 1ms
.flags.auto_reload_on_alarm = true,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = on_timer_alarm_cb,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
TEST_ESP_OK(gptimer_get_intr_handle(gptimer, &intr_handle));
vTaskDelay(5);
vTaskDelay(pdMS_TO_TICKS(20));
// Check some counts have been triggered via the ISR
TEST_ASSERT(count_config.counter > 10);
@ -104,24 +98,22 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
// scheduler off on this CPU...
esp_rom_delay_us(20 * 1000);
//TEST_ASSERT_NOT_EQUAL(no_sched_isr, isr_count);
TEST_ASSERT_EQUAL(count_config.counter, no_sched_task);
// disable timer interrupts
timer_disable_intr(TIMER_GROUP_0, TIMER_0);
esp_intr_disable(intr_handle);
// When we resume scheduler, we expect the counter task
// will preempt and count at least one more item
esp_intr_noniram_enable();
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
esp_intr_enable(intr_handle);
xTaskResumeAll();
TEST_ASSERT_NOT_EQUAL(count_config.counter, no_sched_task);
}
esp_intr_free(isr_handle);
timer_disable_intr(TIMER_GROUP_0, TIMER_0);
TEST_ESP_OK(gptimer_stop(gptimer));
TEST_ESP_OK(gptimer_del_timer(gptimer));
vTaskDelete(counter_task);
vSemaphoreDelete(isr_semaphore);
}
@ -132,7 +124,7 @@ TEST_CASE("Scheduler disabled can handle a pending context switch on resume", "[
*/
TEST_CASE("Scheduler disabled can wake multiple tasks on resume", "[freertos]")
{
#define TASKS_PER_PROC 4
#define TASKS_PER_PROC 4
TaskHandle_t tasks[portNUM_PROCESSORS][TASKS_PER_PROC] = { 0 };
counter_config_t counters[portNUM_PROCESSORS][TASKS_PER_PROC] = { 0 };
@ -169,7 +161,7 @@ TEST_CASE("Scheduler disabled can wake multiple tasks on resume", "[freertos]")
for (int t = 0; t < TASKS_PER_PROC; t++) {
xSemaphoreGive(counters[p][t].trigger_sem);
}
}
}
esp_rom_delay_us(200); /* Let the other CPU do some things */
@ -207,7 +199,7 @@ static void suspend_scheduler_5ms_task_fn(void *ignore)
{
vTaskSuspendAll();
sched_suspended = true;
for (int i = 0; i <5; i++) {
for (int i = 0; i < 5; i++) {
esp_rom_delay_us(1000);
}
xTaskResumeAll();
@ -237,7 +229,7 @@ TEST_CASE("Scheduler disabled on CPU B, tasks on A can wake", "[freertos]")
/* counter task is now blocked on other CPU, waiting for wake_sem, and we expect
that this CPU's scheduler will be suspended for 5ms shortly... */
while(!sched_suspended) { }
while (!sched_suspended) { }
xSemaphoreGive(wake_sem);
esp_rom_delay_us(1000);
@ -247,7 +239,7 @@ TEST_CASE("Scheduler disabled on CPU B, tasks on A can wake", "[freertos]")
TEST_ASSERT(sched_suspended);
/* wait for the rest of the 5ms... */
while(sched_suspended) { }
while (sched_suspended) { }
esp_rom_delay_us(100);
TEST_ASSERT_EQUAL(1, count_config.counter); // when scheduler resumes, counter task should immediately count

Wyświetl plik

@ -9,22 +9,13 @@
#include "freertos/queue.h"
#include "unity.h"
#include "test_utils.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#ifndef CONFIG_FREERTOS_UNICORE
#include "esp_ipc.h"
#endif
#include "esp_freertos_hooks.h"
#include "esp_rom_sys.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define int_clr_timers int_clr
#define update update.update
#define int_st_timers int_st
#endif
/* Counter task counts a target variable forever */
static void task_count(void *vp_counter)
{
@ -116,33 +107,29 @@ TEST_CASE("Suspend the current running task", "[freertos]")
}
volatile bool timer_isr_fired;
static volatile bool timer_isr_fired;
static gptimer_handle_t gptimer = NULL;
/* Timer ISR clears interrupt, sets flag, then resumes the task supplied in the
* callback argument.
*/
void IRAM_ATTR timer_group0_isr(void *vp_arg)
bool on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
// Clear interrupt
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_isr_fired = true;
TaskHandle_t handle = vp_arg;
TaskHandle_t handle = user_ctx;
BaseType_t higherPriorityTaskWoken = pdFALSE;
gptimer_stop(timer);
timer_isr_fired = true;
higherPriorityTaskWoken = xTaskResumeFromISR(handle);
if (higherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
return higherPriorityTaskWoken == pdTRUE;
}
/* Task suspends itself, then sets parameter value to the current timer group counter and deletes itself */
static void task_suspend_self_with_timer(void *vp_resumed)
static IRAM_ATTR void task_suspend_self_with_timer(void *vp_resumed)
{
volatile uint64_t *resumed_counter = vp_resumed;
*resumed_counter = 0;
vTaskSuspend(NULL);
timer_get_counter_value(TIMER_GROUP_0, TIMER_0, vp_resumed);
gptimer_get_raw_count(gptimer, (uint64_t *)resumed_counter);
vTaskDelete(NULL);
}
@ -157,49 +144,40 @@ static void test_resume_task_from_isr(int target_core)
xTaskCreatePinnedToCore(task_suspend_self_with_timer, "suspend_self", 2048,
(void *)&resumed_counter, UNITY_FREERTOS_PRIORITY + 1,
&suspend_task, target_core);
// delay to make the task has resumed itself
vTaskDelay(1);
TEST_ASSERT_EQUAL(0, resumed_counter);
const unsigned APB_CYCLES_PER_TICK = TIMER_BASE_CLK / configTICK_RATE_HZ;
const unsigned TEST_TIMER_DIV = 2;
const unsigned TEST_TIMER_CYCLES_PER_TICK = APB_CYCLES_PER_TICK / TEST_TIMER_DIV;
const unsigned TEST_TIMER_CYCLES_PER_MS = TIMER_BASE_CLK / 1000 / TEST_TIMER_DIV;
const unsigned TEST_TIMER_ALARM = TEST_TIMER_CYCLES_PER_TICK / 2; // half an RTOS tick
/* Configure timer ISR */
timer_isr_handle_t isr_handle;
const timer_config_t config = {
.alarm_en = 1,
.auto_reload = 0,
.counter_dir = TIMER_COUNT_UP,
.divider = TEST_TIMER_DIV,
.intr_type = TIMER_INTR_LEVEL,
.counter_en = TIMER_PAUSE,
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick = 1us
};
/*Configure timer*/
ESP_ERROR_CHECK( timer_init(TIMER_GROUP_0, TIMER_0, &config) );
ESP_ERROR_CHECK( timer_pause(TIMER_GROUP_0, TIMER_0) );
ESP_ERROR_CHECK( timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0) );
ESP_ERROR_CHECK( timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TEST_TIMER_ALARM) );
ESP_ERROR_CHECK( timer_enable_intr(TIMER_GROUP_0, TIMER_0) );
ESP_ERROR_CHECK( timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_group0_isr, (void*)suspend_task, ESP_INTR_FLAG_IRAM, &isr_handle) );
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer));
timer_isr_fired = false;
vTaskDelay(1); // Make sure we're at the start of a new tick
ESP_ERROR_CHECK( timer_start(TIMER_GROUP_0, TIMER_0) );
vTaskDelay(1); // We expect timer group will fire half-way through this delay
gptimer_alarm_config_t alarm_config = {
.alarm_count = 1000000 / configTICK_RATE_HZ / 2,
.reload_count = 0,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = on_timer_alarm_cb,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, suspend_task));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
// wait the timer interrupt fires up
vTaskDelay(2);
TEST_ASSERT_TRUE(timer_isr_fired);
// check the task was resumed
TEST_ASSERT_NOT_EQUAL(0, resumed_counter);
// The task should have woken within 500us of the timer interrupt event (note: task may be a flash cache miss)
printf("alarm value %u task resumed at %u\n", TEST_TIMER_ALARM, (unsigned)resumed_counter);
TEST_ASSERT_UINT32_WITHIN(TEST_TIMER_CYCLES_PER_MS/2, TEST_TIMER_ALARM, (unsigned)resumed_counter);
printf("alarm value %llu task resumed at %u\n", alarm_config.alarm_count, (unsigned)resumed_counter);
TEST_ASSERT_UINT32_WITHIN(100, alarm_config.alarm_count, (unsigned)resumed_counter);
// clean up
timer_deinit(TIMER_GROUP_0, TIMER_0);
ESP_ERROR_CHECK( esp_intr_free(isr_handle) );
TEST_ESP_OK(gptimer_del_timer(gptimer));
}
TEST_CASE("Resume task from ISR (same core)", "[freertos]")
@ -216,7 +194,7 @@ TEST_CASE("Resume task from ISR (other core)", "[freertos]")
static volatile bool block;
static bool suspend_both_cpus;
static void IRAM_ATTR suspend_scheduler_while_block_set(void* arg)
static void IRAM_ATTR suspend_scheduler_while_block_set(void *arg)
{
vTaskSuspendAll();

Wyświetl plik

@ -7,7 +7,6 @@
#include <unity.h>
#include <esp_spi_flash.h>
#include <esp_attr.h>
#include "driver/timer.h"
#include "esp_intr_alloc.h"
#include "test_utils.h"
#include "ccomp_timer.h"
@ -117,88 +116,6 @@ TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_fla
vSemaphoreDelete(done);
}
typedef struct {
size_t buf_size;
uint8_t* buf;
size_t flash_addr;
size_t repeat_count;
SemaphoreHandle_t done;
} read_task_arg_t;
typedef struct {
size_t delay_time_us;
size_t repeat_count;
} block_task_arg_t;
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define int_clr_timers int_clr
#endif
static void IRAM_ATTR timer_isr(void* varg) {
block_task_arg_t* arg = (block_task_arg_t*) varg;
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
esp_rom_delay_us(arg->delay_time_us);
arg->repeat_count++;
}
static void read_task(void* varg) {
read_task_arg_t* arg = (read_task_arg_t*) varg;
for (size_t i = 0; i < arg->repeat_count; ++i) {
ESP_ERROR_CHECK( spi_flash_read(arg->flash_addr, arg->buf, arg->buf_size) );
}
xSemaphoreGive(arg->done);
vTaskDelay(1);
vTaskDelete(NULL);
}
TEST_CASE("spi flash functions can run along with IRAM interrupts", "[spi_flash][esp_flash]")
{
const size_t size = 128;
read_task_arg_t read_arg = {
.buf_size = size,
.buf = (uint8_t*) malloc(size),
.flash_addr = 0,
.repeat_count = 1000,
.done = xSemaphoreCreateBinary()
};
timer_config_t config = {
.alarm_en = true,
.counter_en = false,
.intr_type = TIMER_INTR_LEVEL,
.counter_dir = TIMER_COUNT_UP,
.auto_reload = true,
.divider = 80
};
block_task_arg_t block_arg = {
.repeat_count = 0,
.delay_time_us = 100
};
ESP_ERROR_CHECK( timer_init(TIMER_GROUP_0, TIMER_0, &config) );
timer_pause(TIMER_GROUP_0, TIMER_0);
ESP_ERROR_CHECK( timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 120) );
intr_handle_t handle;
ESP_ERROR_CHECK( timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer_isr, &block_arg, ESP_INTR_FLAG_IRAM, &handle) );
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
timer_start(TIMER_GROUP_0, TIMER_0);
xTaskCreatePinnedToCore(read_task, "r", 2048, &read_arg, 3, NULL, portNUM_PROCESSORS - 1);
xSemaphoreTake(read_arg.done, portMAX_DELAY);
timer_pause(TIMER_GROUP_0, TIMER_0);
timer_disable_intr(TIMER_GROUP_0, TIMER_0);
esp_intr_free(handle);
vSemaphoreDelete(read_arg.done);
free(read_arg.buf);
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
// TODO ESP32-S3 IDF-2021

Wyświetl plik

@ -1,26 +1,16 @@
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
//
// 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
#include "esp_vfs_eventfd.h"
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <sys/select.h>
#include "driver/timer.h"
#include "esp_vfs.h"
#include "freertos/FreeRTOS.h"
#include "unity.h"
#include "driver/gptimer.h"
#include "esp_vfs.h"
#include "esp_vfs_eventfd.h"
TEST_CASE("eventfd create and close", "[vfs][eventfd]")
{
@ -217,13 +207,14 @@ TEST_CASE("eventfd signal from task", "[vfs][eventfd]")
TEST_ESP_OK(esp_vfs_eventfd_unregister());
}
static void eventfd_select_test_isr(void *arg)
static bool eventfd_select_test_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
int fd = *((int *)arg);
gptimer_stop(timer);
int fd = *((int *)user_ctx);
uint64_t val = 1;
timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
int ret = write(fd, &val, sizeof(val));
assert(ret == sizeof(val));
return true;
}
TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
@ -234,22 +225,23 @@ TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
int fd = eventfd(0, EFD_SUPPORT_ISR);
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
timer_config_t timer_config = {
.divider = 16,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.auto_reload = false,
gptimer_handle_t gptimer = NULL;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000,
};
TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &timer_config));
TEST_ESP_OK(timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL));
TEST_ESP_OK(timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_BASE_CLK / 16));
TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0));
TEST_ESP_OK(timer_isr_register(TIMER_GROUP_0, TIMER_0, eventfd_select_test_isr,
&fd, ESP_INTR_FLAG_LOWMED, NULL));
TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0));
TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 200000,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = eventfd_select_test_isr,
};
TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, &fd));
TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
TEST_ESP_OK(gptimer_start(gptimer));
struct timeval wait_time;
fd_set read_fds, write_fds, error_fds;
@ -264,9 +256,9 @@ TEST_CASE("eventfd signal from ISR", "[vfs][eventfd]")
int ret = select(fd + 1, &read_fds, &write_fds, &error_fds, &wait_time);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT(FD_ISSET(fd, &read_fds));
timer_deinit(TIMER_GROUP_0, TIMER_0);
TEST_ASSERT_EQUAL(0, close(fd));
TEST_ESP_OK(esp_vfs_eventfd_unregister());
TEST_ESP_OK(gptimer_del_timer(gptimer));
}
static void close_task(void *arg)

Wyświetl plik

@ -57,6 +57,14 @@ examples_and_unit_tests:
- CC0-1.0
license_for_new_files: Unlicense OR CC0-1.0
freemodbus_component:
include:
- 'components/freemodbus/**'
allowed_licenses:
- Apache-2.0
- BSD-3-Clause
license_for_new_files: Apache-2.0
# files matching this section do not perform the check
# file patterns starting with ! are negated, meaning files matching them won't match the section.
ignore:

Wyświetl plik

@ -944,7 +944,6 @@ components/freertos/test/test_task_priorities.c
components/freertos/test/test_task_suspend_resume.c
components/freertos/test/test_tasks_snapshot.c
components/freertos/test/test_thread_local.c
components/freertos/test/test_timers.c
components/freertos/test/test_xtensa_loadstore_handler.c
components/hal/aes_hal.c
components/hal/cpu_hal.c
@ -2106,7 +2105,6 @@ components/vfs/include/esp_vfs_eventfd.h
components/vfs/include/esp_vfs_semihost.h
components/vfs/test/test_vfs_access.c
components/vfs/test/test_vfs_append.c
components/vfs/test/test_vfs_eventfd.c
components/vfs/test/test_vfs_fd.c
components/vfs/test/test_vfs_lwip.c
components/vfs/test/test_vfs_paths.c

Wyświetl plik

@ -1,41 +1,36 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "test_utils.h"
#include "esp_private/periph_ctrl.h"
#include "soc/periph_defs.h"
#include "hal/timer_hal.h"
#include "hal/timer_ll.h"
#include "unity_config.h"
#include "driver/gptimer.h"
#define TIMER_GROUP_ID (1)
#define TIMER_ID (0)
static timer_hal_context_t timer_hal;
static gptimer_handle_t ts_gptimer;
void ref_clock_init(void)
{
periph_module_enable(PERIPH_TIMG1_MODULE);
timer_hal_init(&timer_hal, TIMER_GROUP_ID, TIMER_ID);
timer_ll_set_clock_source(timer_hal.dev, TIMER_ID, GPTIMER_CLK_SRC_XTAL); // Select XTAL, so ref_clock is independent of the APL clock
timer_ll_enable_counter(timer_hal.dev, TIMER_ID, false); // stop timer from running
timer_ll_set_clock_prescale(timer_hal.dev, TIMER_ID, 40); // Resolution is configured to 1MHz
timer_ll_set_count_direction(timer_hal.dev, timer_hal.timer_id, GPTIMER_COUNT_UP); // increase mode
timer_hal_set_counter_value(&timer_hal, 0); // initial count value to zero
timer_ll_enable_intr(timer_hal.dev, TIMER_LL_EVENT_ALARM(TIMER_ID), false); // disable interrupt
timer_ll_enable_alarm(timer_hal.dev, TIMER_ID, false); // alarm event is not needed
timer_ll_enable_auto_reload(timer_hal.dev, TIMER_ID, false);
timer_ll_enable_counter(timer_hal.dev, TIMER_ID, true); // start counter
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_XTAL,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // Resolution is configured to 1MHz
};
TEST_ESP_OK(gptimer_new_timer(&timer_config, &ts_gptimer));
TEST_ESP_OK(gptimer_start(ts_gptimer));
}
void ref_clock_deinit(void)
{
timer_ll_enable_counter(timer_hal.dev, TIMER_ID, false); // stop timer from running
periph_module_disable(PERIPH_TIMG1_MODULE);
TEST_ESP_OK(gptimer_stop(ts_gptimer));
TEST_ESP_OK(gptimer_del_timer(ts_gptimer));
ts_gptimer = NULL;
}
uint64_t ref_clock_get(void)
{
return timer_ll_get_counter_value(timer_hal.dev, timer_hal.timer_id);
uint64_t ts;
gptimer_get_raw_count(ts_gptimer, &ts);
return ts;
}