mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
Merge branch 'bugfix/fix_driver_ut_pcnt' into 'master'
bugfix(pcnt): fix driver ut pcnt See merge request espressif/esp-idf!6891
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* this case is used for test PCNT
|
||||
* prepare job for test environment UT_T1_PCNT:
|
||||
* We use internal signals instead of external wiring, but please keep the following IO connections, or connect nothing to prevent the signal from being disturbed.
|
||||
* 1. prepare one ESP-WROOM-32 board and connect it to PC.
|
||||
* 2. connect GPIO18 with GPIO4
|
||||
* 2. connect GPIO21 with GPIO4
|
||||
* 3. GPIO5 connect to 3.3v
|
||||
* 4. GPIO19 connect to GND
|
||||
* 5. logic analyzer will help too if possible
|
||||
@@ -22,18 +23,18 @@
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "unity.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
|
||||
|
||||
#define PULSE_IO 18
|
||||
#define PULSE_IO 21
|
||||
#define PCNT_INPUT_IO 4
|
||||
#define PCNT_CTRL_FLOATING_IO 5
|
||||
#define PCNT_CTRL_VCC_IO 5
|
||||
#define PCNT_CTRL_GND_IO 19
|
||||
#define HIGHEST_LIMIT 10
|
||||
#define LOWEST_LIMIT 0
|
||||
#define MAX_THRESHOLD 5
|
||||
#define MIN_THRESHOLD 0
|
||||
#define PCNT_CTRL_HIGH_LEVEL 1
|
||||
#define PCNT_CTRL_LOW_LEVEL 0
|
||||
|
||||
static xQueueHandle pcnt_evt_queue;
|
||||
static xQueueHandle pcnt_evt_queue = NULL;
|
||||
|
||||
typedef struct {
|
||||
int zero_times;
|
||||
@@ -44,6 +45,15 @@ typedef struct {
|
||||
int filter_time;
|
||||
} event_times;
|
||||
|
||||
static void pcnt_test_io_config(int ctrl_level)
|
||||
{
|
||||
// Connect internal signals using IO matrix.
|
||||
gpio_set_direction(PULSE_IO, GPIO_MODE_INPUT_OUTPUT);
|
||||
gpio_matrix_out(PULSE_IO, LEDC_LS_SIG_OUT1_IDX, 0, 0); // LEDC_TIMER_1, LEDC_LOW_SPEED_MODE
|
||||
gpio_matrix_in(PULSE_IO, PCNT_SIG_CH0_IN0_IDX, 0); // PCNT_UNIT_0, PCNT_CHANNEL_0
|
||||
gpio_matrix_in(ctrl_level ? GPIO_FUNC_IN_HIGH: GPIO_FUNC_IN_LOW, PCNT_CTRL_CH0_IN0_IDX, 0); // PCNT_UNIT_0, PCNT_CHANNEL_0
|
||||
}
|
||||
|
||||
/* use LEDC to produce pulse for PCNT
|
||||
* the frequency of LEDC is 1000, so every second will get 1000 count values
|
||||
* the PCNT count the LEDC pulse
|
||||
@@ -51,7 +61,7 @@ typedef struct {
|
||||
static void produce_pulse(void)
|
||||
{
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.timer_num = LEDC_TIMER_1,
|
||||
.duty_resolution = LEDC_TIMER_10_BIT,
|
||||
.freq_hz = 1,
|
||||
@@ -60,7 +70,7 @@ static void produce_pulse(void)
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_1,
|
||||
.timer_sel = LEDC_TIMER_1,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
@@ -102,23 +112,23 @@ static void event_calculate(event_times* event)
|
||||
event->filter_time++;
|
||||
TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
|
||||
printf("Current counter value :%d\n", test_counter);
|
||||
if (status & PCNT_STATUS_THRES1_M) {
|
||||
if (status & PCNT_EVT_THRES_1) {
|
||||
printf("THRES1 EVT\n");
|
||||
event->h_threshold++;
|
||||
}
|
||||
if (status & PCNT_STATUS_THRES0_M) {
|
||||
if (status & PCNT_EVT_THRES_0) {
|
||||
printf("THRES0 EVT\n");
|
||||
event->l_threshold++;
|
||||
}
|
||||
if (status & PCNT_STATUS_L_LIM_M) {
|
||||
if (status & PCNT_EVT_L_LIM) {
|
||||
printf("L_LIM EVT\n");
|
||||
event->l_limit++;
|
||||
}
|
||||
if (status & PCNT_STATUS_H_LIM_M) {
|
||||
if (status & PCNT_EVT_H_LIM) {
|
||||
printf("H_LIM EVT\n");
|
||||
event->h_limit++;
|
||||
}
|
||||
if (status & PCNT_STATUS_ZERO_M) {
|
||||
if (status & PCNT_EVT_ZERO) {
|
||||
printf("ZERO EVT\n");
|
||||
event->zero_times++;
|
||||
}
|
||||
@@ -157,7 +167,7 @@ static void count_mode_test(gpio_num_t ctl_io)
|
||||
int16_t test_counter;
|
||||
//produce pulse, 100HZ
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.timer_num = LEDC_TIMER_1,
|
||||
.duty_resolution = LEDC_TIMER_10_BIT,
|
||||
.freq_hz = 100,
|
||||
@@ -166,7 +176,7 @@ static void count_mode_test(gpio_num_t ctl_io)
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_1,
|
||||
.timer_sel = LEDC_TIMER_1,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
@@ -189,10 +199,11 @@ static void count_mode_test(gpio_num_t ctl_io)
|
||||
.counter_l_lim = -101,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
pcnt_test_io_config((ctl_io == PCNT_CTRL_VCC_IO) ? PCNT_CTRL_HIGH_LEVEL : PCNT_CTRL_LOW_LEVEL);
|
||||
int16_t result1[8] = {100, -100, 0, -100, 100, 100, 0, 100};
|
||||
int16_t result2[8] = {100, -100, 0, 100, -100, -100, 100, 0};
|
||||
int16_t *result;
|
||||
if (gpio_get_level(pcnt_config.ctrl_gpio_num)) {
|
||||
if (ctl_io == PCNT_CTRL_VCC_IO) {
|
||||
result = result1;
|
||||
} else {
|
||||
result = result2;
|
||||
@@ -296,11 +307,11 @@ static void count_mode_test(gpio_num_t ctl_io)
|
||||
}
|
||||
|
||||
// test PCNT basic configuration
|
||||
TEST_CASE("PCNT test config", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
TEST_CASE("PCNT test config", "[pcnt]")
|
||||
{
|
||||
pcnt_config_t pcnt_config = {
|
||||
.pulse_gpio_num = PCNT_INPUT_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_VCC_IO,
|
||||
.channel = PCNT_CHANNEL_0,
|
||||
.unit = PCNT_UNIT_0,
|
||||
.pos_mode = PCNT_COUNT_INC,
|
||||
@@ -314,11 +325,11 @@ TEST_CASE("PCNT test config", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
pcnt_config_t temp_pcnt_config = pcnt_config;
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
|
||||
// test 8 units, from 0-7
|
||||
// test PCNT_UNIT_MAX units, from 0-(PCNT_UNIT_MAX-1)
|
||||
pcnt_config = temp_pcnt_config;
|
||||
pcnt_config.unit = PCNT_UNIT_MAX;
|
||||
TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
for (int i = 0; i < PCNT_UNIT_MAX; i++) {
|
||||
pcnt_config.unit = i;
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
}
|
||||
@@ -332,7 +343,7 @@ TEST_CASE("PCNT test config", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
|
||||
pcnt_config = temp_pcnt_config;
|
||||
pcnt_config.pulse_gpio_num = 41;
|
||||
pcnt_config.pulse_gpio_num = GPIO_NUM_MAX + 1;
|
||||
TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
|
||||
|
||||
// test pulse_gpio_num and ctrl_gpio_num is the same
|
||||
@@ -359,7 +370,7 @@ TEST_CASE("PCNT test config", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
* 2. resume counter
|
||||
* 3. clear counter
|
||||
* 4. check the counter value*/
|
||||
TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
TEST_CASE("PCNT basic function test", "[pcnt]")
|
||||
{
|
||||
int16_t test_counter;
|
||||
int16_t time = 0;
|
||||
@@ -368,7 +379,7 @@ TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
int temp_value = 0;
|
||||
pcnt_config_t pcnt_config = {
|
||||
.pulse_gpio_num = PCNT_INPUT_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_VCC_IO,
|
||||
.channel = PCNT_CHANNEL_0,
|
||||
.unit = PCNT_UNIT_0,
|
||||
.pos_mode = PCNT_COUNT_INC,
|
||||
@@ -382,6 +393,7 @@ TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
|
||||
// use LEDC to produce the pulse, then the PCNT to count it
|
||||
produce_pulse();
|
||||
pcnt_test_io_config(PCNT_CTRL_HIGH_LEVEL);
|
||||
|
||||
// initialize first, the initail value should be 0
|
||||
TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
|
||||
@@ -424,7 +436,7 @@ TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
|
||||
printf("RESUME: %d\n", test_counter);
|
||||
TEST_ASSERT_EQUAL_INT16(test_counter, (gpio_get_level(PCNT_CTRL_FLOATING_IO) > 0) ? (1) : -1);
|
||||
TEST_ASSERT_EQUAL_INT16(test_counter, 1);
|
||||
resume_count++;
|
||||
}
|
||||
time++;
|
||||
@@ -447,12 +459,11 @@ TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
* 4. PCNT_EVT_H_LIM
|
||||
* 5. PCNT_EVT_L_LIM
|
||||
* */
|
||||
// set it ignore: need to debug
|
||||
TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][test_env=UT_T1_PCNT][timeout=120][ignore]")
|
||||
TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][timeout=120]")
|
||||
{
|
||||
pcnt_config_t config = {
|
||||
.pulse_gpio_num = PCNT_INPUT_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
|
||||
.ctrl_gpio_num = PCNT_CTRL_VCC_IO,
|
||||
.channel = PCNT_CHANNEL_0,
|
||||
.unit = PCNT_UNIT_0,
|
||||
.pos_mode = PCNT_COUNT_INC,
|
||||
@@ -464,6 +475,7 @@ TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][test_env=UT_
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_config(&config));
|
||||
produce_pulse();
|
||||
pcnt_test_io_config(PCNT_CTRL_HIGH_LEVEL);
|
||||
|
||||
event_times event = {
|
||||
.zero_times = 0,
|
||||
@@ -485,16 +497,17 @@ TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][test_env=UT_
|
||||
TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM)); // when arrive to max limit trigger
|
||||
TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_L_LIM)); // when arrive to minimum limit trigger
|
||||
|
||||
// to initialize for PCNT
|
||||
// initialize first, the initail value should be 0
|
||||
TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
|
||||
|
||||
TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL));
|
||||
pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
||||
|
||||
pcnt_isr_handle_t pcnt_isr_service;
|
||||
TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, &pcnt_isr_service));
|
||||
TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
|
||||
|
||||
pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
||||
|
||||
// test event
|
||||
event_calculate(&event);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 2);
|
||||
@@ -537,15 +550,16 @@ TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][test_env=UT_
|
||||
TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 5);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 4);
|
||||
TEST_ASSERT(event.l_limit == 0);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.h_limit, 6);
|
||||
TEST_ASSERT_INT_WITHIN(3, event.h_limit, 6);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.zero_times, 4);
|
||||
TEST_ASSERT_INT_WITHIN(3, event.filter_time, 14);
|
||||
|
||||
pcnt_isr_service_uninstall();
|
||||
// Because this test uses its own ISR, we need to release it with `pcnt_isr_unregister` instead of `pcnt_isr_service_uninstall`
|
||||
TEST_ESP_OK(pcnt_isr_unregister(pcnt_isr_service));
|
||||
vQueueDelete(pcnt_evt_queue);
|
||||
}
|
||||
|
||||
// set it ignore: need to debug
|
||||
TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T1_PCNT][timeout=120][ignore]")
|
||||
TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][timeout=120]")
|
||||
{
|
||||
pcnt_config_t config = {
|
||||
.pulse_gpio_num = PCNT_INPUT_IO,
|
||||
@@ -559,9 +573,9 @@ TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T
|
||||
.counter_h_lim = 0,
|
||||
.counter_l_lim = -5,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(pcnt_unit_config(&config));
|
||||
produce_pulse();
|
||||
pcnt_test_io_config(PCNT_CTRL_LOW_LEVEL);
|
||||
|
||||
event_times event = {
|
||||
.zero_times = 0,
|
||||
@@ -587,12 +601,13 @@ TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T
|
||||
TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
|
||||
|
||||
TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL));
|
||||
pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
||||
|
||||
pcnt_isr_handle_t pcnt_isr_service;
|
||||
TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, &pcnt_isr_service));
|
||||
TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
|
||||
|
||||
pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
|
||||
|
||||
// test event
|
||||
event_calculate(&event);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 1);
|
||||
@@ -616,6 +631,7 @@ TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T
|
||||
|
||||
// enable the intr
|
||||
pcnt_unit_config(&config);
|
||||
pcnt_test_io_config(PCNT_CTRL_LOW_LEVEL);
|
||||
TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
|
||||
TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
|
||||
@@ -640,15 +656,15 @@ TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T
|
||||
TEST_ASSERT_INT_WITHIN(2, event.zero_times, 2);
|
||||
TEST_ASSERT_INT_WITHIN(2, event.filter_time, 8);
|
||||
|
||||
pcnt_isr_service_uninstall();
|
||||
// Because this test uses its own ISR, we need to release it with `pcnt_isr_unregister` instead of `pcnt_isr_service_uninstall`
|
||||
TEST_ESP_OK(pcnt_isr_unregister(pcnt_isr_service));
|
||||
vQueueDelete(pcnt_evt_queue);
|
||||
}
|
||||
|
||||
TEST_CASE("PCNT counting mode test", "[pcnt][test_env=UT_T1_PCNT]")
|
||||
TEST_CASE("PCNT counting mode test", "[pcnt]")
|
||||
{
|
||||
printf("PCNT mode test for positive count\n");
|
||||
count_mode_test(PCNT_CTRL_FLOATING_IO);
|
||||
count_mode_test(PCNT_CTRL_VCC_IO);
|
||||
printf("PCNT mode test for negative count\n");
|
||||
count_mode_test(PCNT_CTRL_GND_IO);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user