Skip to content

Commit 7c5b06d

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 e11a353 commit 7c5b06d

2 files changed

Lines changed: 34 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: 33 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,6 +58,7 @@ 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;
@@ -62,7 +68,7 @@ static void check_timing(uint32_t baudrate)
6268
zassert_equal(ret, 0, "uart_config_get: %d\n", ret);
6369

6470
test_uart_config.parity = UART_CFG_PARITY_EVEN;
65-
test_uart_config.stop_bits = UART_CFG_STOP_BITS_2;
71+
test_uart_config.stop_bits = UART_CFG_STOP_BITS_1;
6672
test_uart_config.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
6773
test_uart_config.baudrate = baudrate;
6874
ret = uart_configure(uart_dev, &test_uart_config);
@@ -75,37 +81,11 @@ static void check_timing(uint32_t baudrate)
7581
cycles_s_sys = (uint64_t)sys_clock_hw_cycles_per_sec();
7682
TC_PRINT("Cycles: %llu cycles\n", cycles_s_sys);
7783

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-
9884
double expected_bit_period_us = 1e6 / (double)baudrate;
9985
double number_of_bits = 8;
10086

10187
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-
}
88+
/* Stop bit is 1 so it is not counted. */
10989
if (test_uart_config.parity != UART_CFG_PARITY_NONE) {
11090
number_of_bits += 1;
11191
}
@@ -114,11 +94,6 @@ static void check_timing(uint32_t baudrate)
11494
TC_PRINT("[%d] Expected symbol time: %.2f us, expected bit time: %.2f us\n", baudrate,
11595
expected_symbol_period_us, expected_bit_period_us);
11696

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-
12297
start_index_count_zero = 0;
12398
bit_diviation_mean = 0;
12499
symbol_diviation_mean = 0;
@@ -136,26 +111,44 @@ static void check_timing(uint32_t baudrate)
136111
/*
137112
* Check gpio
138113
*/
114+
139115
key = irq_lock();
116+
cycle_start_time = k_cycle_get_32();
140117
for (uint32_t i = 0; i < PIN_STATE_SIZE; ++i) {
141-
pin_state[i] = gpio_pin_get_dt(&gpio_spec);
118+
pin_state[i] = nrf_gpio_port_in_read(gpio_port) & pin_mask ? 1 : 0;
142119
}
120+
cycle_stop_time = k_cycle_get_32();
143121
irq_unlock(key);
122+
uint32_t t_us = k_cyc_to_us_ceil32(cycle_stop_time - cycle_start_time);
123+
124+
gpio_read_time_us_mean = (double)t_us / PIN_STATE_SIZE;
125+
TC_PRINT("t: %d gpio read time = %.2f\n", t_us, gpio_read_time_us_mean);
126+
127+
if (expected_bit_period_us < gpio_read_time_us_mean) {
128+
TC_PRINT("[%d] Not supported - gpio measurement is too slow.\n", baudrate);
129+
ztest_test_skip();
130+
}
144131

145132
/*
146-
* Find start of start bit and end of stop bit
133+
* Find start of start bit and end of stop bit. For higher baudrates it is
134+
* possible that first byte is already being transferred. In search for
135+
* byte start and end, start from searching for idle state between byte 0 and 1.
147136
*/
148137
start_index = -1;
149138
stop_index = -1;
139+
idle_found = -1;
150140
for (uint32_t i = 0; i < PIN_STATE_SIZE; ++i) {
151141
if (-1 == start_index) {
152-
if (0 == pin_state[i]) {
142+
if (1 == pin_state[i]) {
143+
idle_found = 0;
144+
} else if ((idle_found == 0) && (0 == pin_state[i])) {
153145
start_index = i;
154146
}
155147
} else {
156148
if (-1 == stop_index) {
157149
if (1 == pin_state[i]) {
158150
stop_index = i;
151+
break;
159152
}
160153
} else {
161154
zassert_true(1 == pin_state[i], "Unexpected low at %d\n",

0 commit comments

Comments
 (0)