I’m developing source codes(with ZephyrOS) on my Adafruit feather nrf52840 board, I wanna use UART RX to capture data, currently I found a weird thing, which is, when the data length is <=10, the board can received the data correctly
every time(it recevied the data via UART from PC)and works fine. However, if the data length is >10, for example the data array has 18 bytes, then the board can received the data and works correctly at 1st and 2nd time, but at 3rd time, the uart_cb() will going into “UART_RX_DISABLED:” case for some reason, and then will never be called afterwards.
Could you kindly help me on this?
@AchimKraus
Here’re the source codes:
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/uart.h>
#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 500
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
/* The devicetree node identifier for the "led1" alias. */
#define LED1_NODE DT_ALIAS(led1)
#define UART_BUF_SIZE 40
#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led_blue = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];
uint8_t *uart_buf_next = uart_double_buffer[1];
uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active
/*
* Print a null-terminated string character by character to the UART interface
*/
void print_uart(char *buf, int len)
{
for (int i = 0; i < len; i++) {
uart_poll_out(uart_dev, buf[i]);
}
}
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
switch (evt->type)
{
case UART_TX_DONE:
break;
case UART_TX_ABORTED:
// do something
break;
case UART_RX_RDY:
printk("Received %i bytes \n", evt->data.rx.len);
printk("Offset = %i \n", evt->data.rx.offset);
if (currently_active_buffer == 0)
{
// read all characters one by one till new line is found
for (int i = 0 + evt->data.rx.offset; i < UART_BUF_SIZE; i++)
{
complete_message[complete_message_counter] = uart_double_buffer[0][i];
complete_message_counter++;
if (uart_double_buffer[0][i] == '\n')
{
complete_message_counter = 0;
print_uart(complete_message, sizeof(complete_message));
memset(&complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
break;
}
}
}
if (currently_active_buffer == 1)
{
// read all characters one by one till new line is found
for (int i = 0 + evt->data.rx.offset; i < UART_BUF_SIZE; i++)
{
complete_message[complete_message_counter] = uart_double_buffer[1][i];
complete_message_counter++;
if (uart_double_buffer[1][i] == '\n')
{
complete_message_counter = 0;
print_uart(complete_message, sizeof(complete_message));
memset(&complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
break;
}
}
}
break;
case UART_RX_BUF_REQUEST:
//printk("I'm requesting now");
uart_rx_buf_rsp(uart_dev, uart_buf_next, UART_BUF_SIZE);
currently_active_buffer = !currently_active_buffer;
break;
case UART_RX_BUF_RELEASED:
uart_buf_next = evt->data.rx_buf.buf;
break;
case UART_RX_DISABLED:
printk("it's in RX DISABLED case");
k_sem_give(&rx_disabled);
break;
case UART_RX_STOPPED:
// do something
break;
default:
printk("it's in default case");
break;
}
}
int main(void)
{
if (!device_is_ready(uart_dev)) {
printk("UART device not found!");
return 0;
}
int ret;
bool led_state = true;
if (!gpio_is_ready_dt(&led)) {
return 0;
}
if (!gpio_is_ready_dt(&led_blue)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
ret = gpio_pin_configure_dt(&led_blue, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
print_uart("Hello! I'm your echo bot.\r\n", 26);
int err;
err = uart_callback_set(uart_dev, uart_cb, NULL);
if (err)
{
return err;
}
uart_rx_enable(uart_dev, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
while (1) {
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
ret = gpio_pin_toggle_dt(&led_blue);
if (ret < 0) {
return 0;
}
//led_state = !led_state;
//printf("LED state: %s\n", led_state ? "ON" : "OFF");
//print_uart(single_inv_buf, sizeof(single_inv_buf));
/*Data Transmission End*/
k_msleep(SLEEP_TIME_MS);
}
return 0;
}