Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: on_target: 400k trace test on conn bridge #526

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified tests/on_target/artifacts/usb_uart_bridge_app.zip
Binary file not shown.
12 changes: 12 additions & 0 deletions tests/on_target/test_apps/usb_uart_bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(uart_echo_bot)

target_include_directories(app PRIVATE inc)

target_sources(app PRIVATE
src/main.c
)
4 changes: 4 additions & 0 deletions tests/on_target/test_apps/usb_uart_bridge/app.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Enable UART1 */
&uart1 {
status = "okay";
};
7 changes: 7 additions & 0 deletions tests/on_target/test_apps/usb_uart_bridge/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CONFIG_SERIAL=y
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_UART_ASYNC_API=y
CONFIG_WATCHDOG=y
CONFIG_LOG=n

278 changes: 278 additions & 0 deletions tests/on_target/test_apps/usb_uart_bridge/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/watchdog.h>

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* defines for watchdog */
#define WDT_MAX_WINDOW 10000U
#define WDT_FEED_WORKER_DELAY_MS 2500U

#define MSG_SIZE 5120
#define LINE_LEN 64
#define LINE_COUNT 64

#define RECEIVE_TIMEOUT 1000

/* queue to store up to 8 messages (aligned to 4-byte boundary) */
K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 8, 4);

static const struct device *uart0 = DEVICE_DT_GET(DT_NODELABEL(uart0));
static const struct device *uart1 = DEVICE_DT_GET(DT_NODELABEL(uart1));

struct wdt_data_storage {
const struct device *wdt_drv;
int wdt_channel_id;
struct k_work_delayable system_workqueue_work;
};

static struct wdt_data_storage wdt_data = {
.wdt_drv = DEVICE_DT_GET(DT_NODELABEL(wdt))
};



/* Define a semaphore for UART1 transmission synchronization */
K_SEM_DEFINE(uart1_tx_sem, 1, 1); // Initial count = 1, max count = 1

/* RX buffer for UART0 DMA */
static uint8_t rx_dma_buf[MSG_SIZE];

/* Buffer used in callback to process incoming lines */
static char rx_line_buf[MSG_SIZE];
static size_t rx_line_buf_pos = 0;

/* UART Print function using async API for UART0 */
static void print_uart0_async(const struct device *uart, const char *str)
{
size_t len = strlen(str);
if (len == 0) {
return;
}
uart_tx(uart, (const uint8_t *)str, len, SYS_FOREVER_MS);
}

/* UART Print function using async API for UART1 with semaphore */
static void print_uart1_async(const struct device *uart, const char *str)
{
size_t len = strlen(str);
if (len == 0) {
return;
}

/* Acquire the semaphore before initiating transmission */
if (k_sem_take(&uart1_tx_sem, K_FOREVER) == 0) {
int ret = uart_tx(uart, (const uint8_t *)str, len, SYS_FOREVER_MS);
if (ret < 0) {
/* Transmission failed, release the semaphore */
k_sem_give(&uart1_tx_sem);
}
/* If uart_tx is successful, the semaphore will be released in the callback */
}
}

/* UART0 callback to handle TX completion */
static void uart0_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
switch (evt->type) {
case UART_RX_RDY:
/* Data received. Copy it into rx_line_buf and look for line endings */
const uint8_t *data = &evt->data.rx.buf[evt->data.rx.offset];
size_t len = evt->data.rx.len;
for (size_t i = 0; i < len; i++) {
char c = (char)data[i];
if ((c == '\n' || c == '\r') && rx_line_buf_pos > 0) {
/* Terminate string */
rx_line_buf[rx_line_buf_pos] = '\0';
/* Put line into message queue (if full, dropped) */
k_msgq_put(&uart_msgq, rx_line_buf, K_NO_WAIT);
/* Reset buffer */
rx_line_buf_pos = 0;
} else if (rx_line_buf_pos < (sizeof(rx_line_buf) - 1)) {
rx_line_buf[rx_line_buf_pos++] = c;
}
/* else: drop characters beyond buffer size */
}
break;
case UART_RX_DISABLED:
uart_rx_enable(uart0, rx_dma_buf, sizeof(rx_dma_buf), RECEIVE_TIMEOUT);
break;
case UART_RX_STOPPED:
/* RX stopped due to an error. Restart RX. */
uart_rx_enable(dev, rx_dma_buf, sizeof(rx_dma_buf), RECEIVE_TIMEOUT);
break;
default:
break;
}
}

/* UART1 callback to handle TX completion */
static void uart1_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
switch (evt->type) {
case UART_TX_DONE:
case UART_TX_ABORTED:
/* Release the semaphore to allow the next transmission */
k_sem_give(&uart1_tx_sem);
break;
default:
break;
}
}


/*
* Generate a large predefined string to be checked by test
*/
static void generate_str(char *str, int line_len, int line_count)
{
int count = 0;
char c;
int t;

for (int i = 0; i < line_count; ++i) {
for (int j = i; j < i + line_len-1; ++j) {
t = j % line_len;
c = '!' + t;
if (c == '\"' || c == '\'' || c == '\\') {
c = 'a';
}
*(str+count) = c;
count++;
}
if (i < line_count-1) {
*(str+count) = 'A';
count++;
}
}
*(str+count) = '\0';
}

static void init_watchdog(void)
{
struct wdt_timeout_cfg wdt_config = {
/* Reset SoC when watchdog timer expires. */
.flags = WDT_FLAG_RESET_SOC,

/* Expire watchdog after max window */
.window.min = 0U,
.window.max = WDT_MAX_WINDOW,
};
wdt_data.wdt_channel_id = wdt_install_timeout(wdt_data.wdt_drv, &wdt_config);
wdt_setup(wdt_data.wdt_drv, WDT_OPT_PAUSE_HALTED_BY_DBG);
}

static void init_uart(void)
{
/* Set the UART0 callback */
uart_callback_set(uart0, uart0_cb, NULL);
/* Set the UART1 callback */
uart_callback_set(uart1, uart1_cb, NULL);

/* Enable asynchronous RX (required by async API) */
uart_rx_enable(uart0, rx_dma_buf, sizeof(rx_dma_buf), RECEIVE_TIMEOUT);

/* Enable UART1 asynchronous RX (required by async API), though we don't use RX here.
* Just provide a dummy buffer. */
static uint8_t dummy_rx_buf1[1];
uart_rx_enable(uart1, dummy_rx_buf1, sizeof(dummy_rx_buf1), SYS_FOREVER_MS);

/* Configure UART1 to 1000000 baud */
struct uart_config cfg1;
uart_config_get(uart1, &cfg1);
cfg1.baudrate = 1000000;
uart_configure(uart1, &cfg1);
}

/* Buffer to read from message queue */
static char buffer_to_read_msgq[MSG_SIZE];

/* Control String */
static char control_str[LINE_LEN*LINE_COUNT];

int main(void)
{
int err;
char hex_buf[5];

/* Ensure UART0 is ready */
if (!device_is_ready(uart0)) {
return 0;
}

/* Ensure UART1 is ready */
if (!device_is_ready(uart1)) {
return 0;
}

init_uart();
init_watchdog();



/* Generate a control string */
generate_str(control_str, LINE_LEN, LINE_COUNT);

while (1) {
err = k_msgq_get(&uart_msgq, buffer_to_read_msgq, K_MSEC(WDT_FEED_WORKER_DELAY_MS));
if (!err) {
wdt_feed(wdt_data.wdt_drv, wdt_data.wdt_channel_id);
if (strstr(buffer_to_read_msgq, control_str)) {
print_uart0_async(uart0, "Control string received from usb via bridge to nrf9160!\r\n");
}
/* CHECK_UART0_SMOKE */
else if (strstr(buffer_to_read_msgq, "CHECK_UART0_SMOKE")) {
print_uart0_async(uart0, "This message should be seen on UART0!\r\n");
}
/* CHECK_UART1_SMOKE */
else if (strstr(buffer_to_read_msgq, "CHECK_UART1_SMOKE")) {
print_uart1_async(uart1, "This message should be seen on UART1!\r\n");
}
else if (strstr(buffer_to_read_msgq, "CHECK_UART1_4k_TRACES")) {
print_uart0_async(uart0, "4k of data sent over UART1\r\n");
print_uart1_async(uart1, control_str);
}
else if (strstr(buffer_to_read_msgq, "CHECK_UART1_100k_TRACES")) {
print_uart0_async(uart0, "100k of data sent over UART1\r\n");
for (int i = 0; i < 25; ++i) {
print_uart1_async(uart1, control_str);
}
}
else if (strstr(buffer_to_read_msgq, "CHECK_UART1_400k_TRACES")) {
print_uart0_async(uart0, "400k of data sent over UART1\r\n");
for (int i = 0; i < 100; ++i) {
print_uart1_async(uart1, control_str);
}
}
else if (strstr(buffer_to_read_msgq, "CHECK_UART1_600k_TRACES")) {
print_uart0_async(uart0, "600k of data sent over UART1\r\n");
for (int i = 0; i < 150; ++i) {
print_uart1_async(uart1, control_str);
}
}
else {
print_uart0_async(uart0, "Unexpected message received:\r\n");
for (int i = 0; i < (int)strlen(buffer_to_read_msgq); ++i) {
snprintk(hex_buf, sizeof(hex_buf), "%02X, ", buffer_to_read_msgq[i]);
print_uart1_async(uart0, hex_buf);
}
print_uart0_async(uart0, "\r\n");
}
}
else if (err == -EAGAIN) {
wdt_feed(wdt_data.wdt_drv, wdt_data.wdt_channel_id);
print_uart0_async(uart0, "UART0 running at baudrate 115200\r\n");
print_uart1_async(uart1, "UART1 running at baudrate 1000000\r\n");
}
else {
print_uart0_async(uart0, "Error receiving message from queue\r\n");
return 0;
}
k_sleep(K_SECONDS(1));
}
return 0;
}
Loading
Loading