This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

CONFIG_UART_ASYNC_API -> uart_tx() fails when call from K_THREAD

Hello,

i have a function wich just send "hello world" via uart0.

static otError SendUARTCommand(void) {
  volatile uint32_t ret;
  const uint8_t message[] = "Hello World! \n\r";
  dk_set_led_on(DONGLE_RED_MULTI_LED);
  ret = uart_tx(UART0Handle, &message, sizeof(message) - 1, SYS_FOREVER_MS);
}

It work when i call this function outside of a zephyr thread.

like this...

void main(void) {
  int ret;
  ret = dk_leds_init();

  UART0Handle = device_get_binding(UART_LABEL);

  if (!UART0Handle) {
    return;
  }

  const uint8_t message[] = "Hello World! \n\r";
  dk_set_led_on(DONGLE_RED_MULTI_LED);
  ret = uart_tx(UART0Handle, &message, sizeof(message) - 1, SYS_FOREVER_MS);

But when if define a zephyr thread (which is working as expected):

K_THREAD_DEFINE(main_thread, MY_STACK_SIZE,
    SenderThreadFunction, NULL, NULL, NULL,
    MY_PRIORITY, 0, 0);

and call it from this thread:

void SenderThreadFunction(void *p1, void *p2, void *p3) {

...

res = SendUARTCommand(void);

}

The output is corrupted

depending on how many characters i like to send the pattern looks different, but corrupted anyway.

i haven't found any advice how to use this function in threads. may be i have to take a mutex/semaphore, but i don't know which and where this could be provided.

Thanks

Sören

Parents Reply Children
  • Hi, Hakon! Thank you for the answer! It seems that I faced about the same problem, using uart_tx() function. After making a message variable as static the UART transmission started to work properly for me also. I had something like the code below. And UART (uart_tx()) sent corrupted data to me until I made a variable message as static.

    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/uart.h>
    
    #include <logging/log.h>
    #define LOG_MODULE_NAME main
    LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
    
    static const struct device *uart_dev;
    
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
        if (evt->type == UART_TX_DONE) {
            LOG_DBG("UART_TX_DONE: TX sent %d bytes", evt->data.tx.len);
        }
    }
    
    void main(void)
    {
        int err;
        static uint8_t message[] = "Hello World!\r\n";
        const struct uart_config uart_cfg = {
            .baudrate = 115200,
            .parity = UART_CFG_PARITY_NONE,
            .stop_bits = UART_CFG_STOP_BITS_1,
            .data_bits = UART_CFG_DATA_BITS_8,
            .flow_ctrl = UART_CFG_FLOW_CTRL_NONE
        };
    
        uart_dev = device_get_binding(DT_LABEL(DT_NODELABEL(uart0)));
    
        if (uart_dev == NULL) {
            LOG_ERR("Failed to get UART device");
        }
    
        if (uart_configure(uart_dev, &uart_cfg) != 0) {
            LOG_ERR("Failed to configure UART");
        }
    
        err = uart_callback_set(uart_dev, uart_cb, NULL);
        if (err < 0) {
            LOG_DBG("Cannot set UART callback (err %d)", err);
        }
    
        err = uart_tx(uart_dev, message, sizeof(message), SYS_FOREVER_MS);
        if (err < 0) {
            LOG_ERR("Cannot send data over UART (err %d)", err);
        } else {
            LOG_DBG("Sent data");
        }
    }



    So, do I have 4 options to define a buffer variable for uart_tx() function, which are listed below?

    1. make it static inside the function and not const (as it is implemented in this example https://github.com/nrfconnect/sdk-nrf/blob/v1.6.0/samples/edge_impulse/data_forwarder/src/main.c#L82)
    2. make it global and not const
    3. make it not static inside the function and not const, but wait until the end of transmission, using a semaphore, for example (as it is implemented in this example https://github.com/zephyrproject-rtos/zephyr/blob/zephyr-v2.6.0/tests/drivers/uart/uart_async_api/src/test_uart_async.c#L71)
    4. allocate a buffer variable on the heap and release it in a callback function (as it is implemented in this example https://github.com/nrfconnect/sdk-nrf/blob/v1.6.0/applications/serial_lte_modem/src/slm_at_host.c#L86)
  • RAlexeev said:
    So, do I have 4 options to define a buffer variable for uart_tx() function, which are listed below?

     Yes, all of these options are viable I believe.

Related