Skip to content

Commit a24ca61

Browse files
committed
tests: drivers: uart: baudrate_test: Improve accuracy measurement
Test was reporting high deviation 17-25% which seemed high. Such measurement inaccuracy was due to 3 reasons: - using gpio Zephyr API for reading pin state which is twice longer than using GPIO HAL - assumption that stop bits are also 0 and should be included in the measurement. UART stop bits are 1 so they should not be included - starting UART transfer and then starting the measurement. For high baudrates beginning of the byte was not included in the measurement as first gpio read was already 0. All issues have been fixed: - Reduced number of bits in the frame (biggest gain). - Using GPIO HAL for reading the input - sampling frequency is doubled. - Transferring 2 bytes and measuring the second byte which improved accuracy for higher baudrates. Additionally, reduced number of repeats from 10 to 3 to shorten the test. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
1 parent 398b0ea commit a24ca61

2 files changed

Lines changed: 40 additions & 41 deletions

File tree

tests/drivers/uart/uart_baudrate_test/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ source "Kconfig.zephyr"
88

99
config TEST_ALLOWED_DEVIATION
1010
int "Allowed deviation (%) for UART timing checks"
11-
default 25
11+
default 5
1212
range 0 100
1313
help
1414
Maximum allowed deviation (%) from the programmed values for the test to be

tests/drivers/uart/uart_baudrate_test/src/main.c

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@
1010
#include <zephyr/kernel.h>
1111
#include <zephyr/ztest.h>
1212
#include <zephyr/drivers/gpio.h>
13+
#include <hal/nrf_gpio.h>
1314
#include <stdlib.h>
1415
#include <math.h>
1516

17+
18+
static NRF_GPIO_Type *gpio_port =
19+
((NRF_GPIO_Type *)DT_REG_ADDR(DT_GPIO_CTLR(DT_PATH(zephyr_user), gpios)));
20+
static uint32_t pin_mask = BIT(DT_GPIO_PIN(DT_PATH(zephyr_user), gpios));
1621
static const struct gpio_dt_spec gpio_spec =
1722
GPIO_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), gpios, 0);
1823
static const struct device *const uart_dev = DEVICE_DT_GET(DT_NODELABEL(dut));
1924

20-
static const uint8_t tx_buf[1] = {0x00};
25+
static const uint8_t tx_buf[] = {0x00, 0x00};
2126

22-
#define PIN_STATE_SIZE 16384
23-
static int pin_state[PIN_STATE_SIZE] = {};
27+
#define PIN_STATE_SIZE 32768
28+
static uint8_t pin_state[PIN_STATE_SIZE] = {};
2429

25-
#define REPEAT_NUMBER 10
30+
#define REPEAT_NUMBER 3
2631

2732
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
2833
static void uart_fifo_callback(const struct device *dev, void *user_data)
@@ -53,16 +58,18 @@ static void check_timing(uint32_t baudrate)
5358
double gpio_read_time_us_mean;
5459
int32_t start_index;
5560
int32_t stop_index;
61+
int32_t idle_found;
5662
int32_t start_index_count_zero;
5763
double bit_diviation_mean;
5864
double symbol_diviation_mean;
65+
bool once = true;
5966
int key;
6067

6168
ret = uart_config_get(uart_dev, &test_uart_config);
6269
zassert_equal(ret, 0, "uart_config_get: %d\n", ret);
6370

6471
test_uart_config.parity = UART_CFG_PARITY_EVEN;
65-
test_uart_config.stop_bits = UART_CFG_STOP_BITS_2;
72+
test_uart_config.stop_bits = UART_CFG_STOP_BITS_1;
6673
test_uart_config.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
6774
test_uart_config.baudrate = baudrate;
6875
ret = uart_configure(uart_dev, &test_uart_config);
@@ -75,37 +82,11 @@ static void check_timing(uint32_t baudrate)
7582
cycles_s_sys = (uint64_t)sys_clock_hw_cycles_per_sec();
7683
TC_PRINT("Cycles: %llu cycles\n", cycles_s_sys);
7784

78-
/*
79-
* Measure time needed to read gpios
80-
*/
81-
gpio_read_time_us_mean = 0;
82-
key = irq_lock();
83-
for (uint32_t t = 0; t < REPEAT_NUMBER; ++t) {
84-
cycle_start_time = k_cycle_get_32();
85-
for (uint32_t i = 0; i < PIN_STATE_SIZE; ++i) {
86-
pin_state[i] = gpio_pin_get_dt(&gpio_spec);
87-
}
88-
cycle_stop_time = k_cycle_get_32();
89-
double gpio_read_time_us =
90-
((cycle_stop_time - cycle_start_time) / (double)PIN_STATE_SIZE) *
91-
(1e6 / cycles_s_sys);
92-
gpio_read_time_us_mean += gpio_read_time_us;
93-
}
94-
irq_unlock(key);
95-
gpio_read_time_us_mean /= (double)REPEAT_NUMBER;
96-
TC_PRINT("GPIO get takes: %.2f us\n", gpio_read_time_us_mean);
97-
9885
double expected_bit_period_us = 1e6 / (double)baudrate;
9986
double number_of_bits = 8;
10087

10188
number_of_bits += 1;
102-
if (test_uart_config.stop_bits == UART_CFG_STOP_BITS_1) {
103-
number_of_bits += 1;
104-
} else if (test_uart_config.stop_bits == UART_CFG_STOP_BITS_2) {
105-
number_of_bits += 2;
106-
} else {
107-
zassert_true(false, "Unsupported stop_bits: %d", test_uart_config.stop_bits);
108-
}
89+
/* Stop bit is 1 so it is not counted. */
10990
if (test_uart_config.parity != UART_CFG_PARITY_NONE) {
11091
number_of_bits += 1;
11192
}
@@ -114,11 +95,6 @@ static void check_timing(uint32_t baudrate)
11495
TC_PRINT("[%d] Expected symbol time: %.2f us, expected bit time: %.2f us\n", baudrate,
11596
expected_symbol_period_us, expected_bit_period_us);
11697

117-
if (expected_bit_period_us < gpio_read_time_us_mean) {
118-
TC_PRINT("[%d] Not supported - gpio measurement is too slow.\n", baudrate);
119-
ztest_test_skip();
120-
}
121-
12298
start_index_count_zero = 0;
12399
bit_diviation_mean = 0;
124100
symbol_diviation_mean = 0;
@@ -136,26 +112,49 @@ static void check_timing(uint32_t baudrate)
136112
/*
137113
* Check gpio
138114
*/
115+
139116
key = irq_lock();
117+
cycle_start_time = k_cycle_get_32();
140118
for (uint32_t i = 0; i < PIN_STATE_SIZE; ++i) {
141-
pin_state[i] = gpio_pin_get_dt(&gpio_spec);
119+
pin_state[i] = nrf_gpio_port_in_read(gpio_port) & pin_mask ? 1 : 0;
142120
}
121+
cycle_stop_time = k_cycle_get_32();
143122
irq_unlock(key);
144123

124+
if (once) {
125+
/* Calculate only for the first iteration. */
126+
uint32_t t_us = k_cyc_to_us_ceil32(cycle_stop_time - cycle_start_time);
127+
128+
gpio_read_time_us_mean = (double)t_us / PIN_STATE_SIZE;
129+
once = false;
130+
TC_PRINT("GPIO get takes: %.2f us\n", gpio_read_time_us_mean);
131+
}
132+
133+
if (expected_bit_period_us < gpio_read_time_us_mean) {
134+
TC_PRINT("[%d] Not supported - gpio measurement is too slow.\n", baudrate);
135+
ztest_test_skip();
136+
}
137+
145138
/*
146-
* Find start of start bit and end of stop bit
139+
* Find start of start bit and end of stop bit. For higher baudrates it is
140+
* possible that first byte is already being transferred. In search for
141+
* byte start and end, start from searching for idle state between byte 0 and 1.
147142
*/
148143
start_index = -1;
149144
stop_index = -1;
145+
idle_found = -1;
150146
for (uint32_t i = 0; i < PIN_STATE_SIZE; ++i) {
151147
if (-1 == start_index) {
152-
if (0 == pin_state[i]) {
148+
if (1 == pin_state[i]) {
149+
idle_found = 0;
150+
} else if ((idle_found == 0) && (0 == pin_state[i])) {
153151
start_index = i;
154152
}
155153
} else {
156154
if (-1 == stop_index) {
157155
if (1 == pin_state[i]) {
158156
stop_index = i;
157+
break;
159158
}
160159
} else {
161160
zassert_true(1 == pin_state[i], "Unexpected low at %d\n",

0 commit comments

Comments
 (0)