-
Notifications
You must be signed in to change notification settings - Fork 573
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
apps/examples: add uart_loopback_test
This is a test example where you can short-circuit the uart tx and rx boards to perform a loopback test. This test sends "1234567890abcdefghijklmnopqrstuvwxyz" and recive same string You can use CONIFG_UART_LOOPBACK_PORT to specify the port for the loopback test. [TEST RESULT] TASH>>uart_loopback start TASH>>######################### UART loopback test START ######################### UART RX THREAD START UART TX THREAD START SEND UART(1): 1234567890abcdefghijklmnopqrstuvwxyz RECEIVE(1): 1234567890abcdefghijklmnopqrstuvwxyz RESULT(1): PASSED SEND UART(2): 1234567890abcdefghijklmnopqrstuvwxyz RECEIVE(2): 1234567890abcdefghijklmnopqrstuvwxyz RESULT(2): PASSED SEND UART(3): 1234567890abcdefghijklmnopqrstuvwxyz RECEIVE(3): 1234567890abcdefghijklmnopqrstuvwxyz RESULT(3): PASSED
- Loading branch information
Showing
5 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# | ||
# For a description of the syntax of this configuration file, | ||
# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt | ||
# | ||
|
||
config EXAMPLES_UART_LOOPBACK | ||
bool "UART loopback test application" | ||
default n | ||
---help--- | ||
Enable UART loopback test application | ||
|
||
if EXAMPLES_UART_LOOPBACK | ||
|
||
config EXAMPLES_UART_LOOPBACK_PORT | ||
int "UART loopback tty port " | ||
default 2 | ||
---help--- | ||
The EXAMPLES_UART_LOOPBACK_PORT sets test UART ttyS* port | ||
The default port is ttyS2 | ||
|
||
endif #EXAMPLES_UART_LOOPBACK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
config ENTRY_UART_LOOPBACK | ||
bool "uart loop back example" | ||
depends on EXAMPLES_UART_LOOPBACK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
########################################################################### | ||
# | ||
# Copyright 2024 Samsung Electronics All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an | ||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
# either express or implied. See the License for the specific | ||
# language governing permissions and limitations under the License. | ||
# | ||
########################################################################### | ||
|
||
ifeq ($(CONFIG_EXAMPLES_UART_LOOPBACK),y) | ||
CONFIGURED_APPS += examples/uart_loopback | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
########################################################################### | ||
# | ||
# Copyright 2024 Samsung Electronics All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an | ||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
# either express or implied. See the License for the specific | ||
# language governing permissions and limitations under the License. | ||
# | ||
########################################################################### | ||
-include $(TOPDIR)/.config | ||
-include $(TOPDIR)/Make.defs | ||
include $(APPDIR)/Make.defs | ||
|
||
APPNAME = uart_loopback | ||
FUNCNAME = $(APPNAME)_main | ||
THREADEXEC = TASH_EXECMD_ASYNC | ||
PRIORITY = 100 | ||
STACKSIZE = 2048 | ||
|
||
ASRCS = | ||
CSRCS = | ||
MAINSRC = uart_loopback.c | ||
|
||
AOBJS = $(ASRCS:.S=$(OBJEXT)) | ||
COBJS = $(CSRCS:.c=$(OBJEXT)) | ||
MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) | ||
|
||
SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) | ||
OBJS = $(AOBJS) $(COBJS) | ||
|
||
ifneq ($(CONFIG_BUILD_KERNEL),y) | ||
OBJS += $(MAINOBJ) | ||
endif | ||
|
||
ifeq ($(CONFIG_WINDOWS_NATIVE),y) | ||
BIN = $(APPDIR)\libapps$(LIBEXT) | ||
else | ||
ifeq ($(WINTOOL),y) | ||
BIN = $(APPDIR)\\libapps$(LIBEXT) | ||
else | ||
BIN = $(APPDIR)/libapps$(LIBEXT) | ||
endif | ||
endif | ||
|
||
ifeq ($(WINTOOL),y) | ||
INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" | ||
else | ||
INSTALL_DIR = $(BIN_DIR) | ||
endif | ||
|
||
CONFIG_EXAMPLES_TEST_PROGNAME ?= uart_loopback(EXEEXT) | ||
PROGNAME = $(CONFIG_EXAMPLES_TEST_PROGNAME) | ||
|
||
ROOTDEPPATH = --dep-path . | ||
|
||
# Common build | ||
|
||
VPATH = | ||
|
||
all: .built | ||
.PHONY: clean depend distclean | ||
|
||
$(AOBJS): %$(OBJEXT): %.S | ||
$(call ASSEMBLE, $<, $@) | ||
|
||
$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c | ||
$(call COMPILE, $<, $@) | ||
|
||
.built: $(OBJS) | ||
$(call ARCHIVE, $(BIN), $(OBJS)) | ||
@touch .built | ||
|
||
ifeq ($(CONFIG_BUILD_KERNEL),y) | ||
$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) | ||
@echo "LD: $(PROGNAME)" | ||
$(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) | ||
$(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) | ||
|
||
install: $(BIN_DIR)$(DELIM)$(PROGNAME) | ||
|
||
else | ||
install: | ||
|
||
endif | ||
|
||
|
||
ifeq ($(CONFIG_BUILTIN_APPS)$(CONFIG_EXAMPLES_UART_LOOPBACK),yy) | ||
$(BUILTIN_REGISTRY)$(DELIM)$(FUNCNAME).bdat: $(DEPCONFIG) Makefile | ||
$(Q) $(call REGISTER,$(APPNAME),$(FUNCNAME),$(THREADEXEC),$(PRIORITY),$(STACKSIZE)) | ||
context: $(BUILTIN_REGISTRY)$(DELIM)$(FUNCNAME).bdat | ||
|
||
else | ||
context: | ||
|
||
endif | ||
|
||
.depend: Makefile $(SRCS) | ||
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep | ||
@touch $@ | ||
|
||
depend: .depend | ||
|
||
clean: | ||
$(call DELFILE, .built) | ||
$(call CLEAN) | ||
|
||
distclean: clean | ||
$(call DELFILE, Make.dep) | ||
$(call DELFILE, .depend) | ||
|
||
-include Make.dep | ||
.PHONY: preconfig | ||
preconfig: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
/**************************************************************************** | ||
* | ||
* Copyright 2024 Samsung Electronics All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
* either express or implied. See the License for the specific | ||
* language governing permissions and limitations under the License. | ||
* | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Included Files | ||
****************************************************************************/ | ||
#include <tinyara/config.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <fcntl.h> | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <pthread.h> | ||
#ifndef CONFIG_DISABLE_POLL | ||
#include <poll.h> | ||
#endif | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
/**************************************************************************** | ||
* Pre-processor Definitions | ||
****************************************************************************/ | ||
#ifndef CONFIG_EXAMPLES_UART_LOOPBACK_PORT | ||
#define CONFIG_EXAMPLES_UART_LOOPBACK_PORT 2 | ||
#endif | ||
|
||
#define UART_DEV_PATH "/dev/ttyS%d" | ||
|
||
#define UART_POLL_TIMEOUT_MS 10000 | ||
|
||
#define TEST_STR "1234567890abcdefghijklmnopqrstuvwxyz" | ||
#define TEST_STR_LEN 37 | ||
|
||
static int is_running; | ||
static pthread_t g_tx_tid; | ||
static pthread_t g_rx_tid; | ||
|
||
static int uart_tx_loop(void) | ||
{ | ||
printf("UART TX THREAD START\n"); | ||
int fd = 0; | ||
int tx_test_count = 0; | ||
char port[20] = {'\0'}; | ||
sprintf(port, UART_DEV_PATH, CONFIG_EXAMPLES_UART_LOOPBACK_PORT); | ||
fd = open(port, O_RDWR | O_SYNC, 0666); | ||
if (fd < 0) { | ||
printf("ERROR: Failed to open Tx UART(%d):\n", get_errno()); | ||
return -1; | ||
} | ||
|
||
while (is_running) { | ||
tx_test_count++; | ||
usleep(200*1000); | ||
|
||
char test_data[TEST_STR_LEN] = TEST_STR; | ||
write(fd, (void *)test_data, TEST_STR_LEN); | ||
printf("SEND UART(%d): %s\n", tx_test_count, TEST_STR, TEST_STR_LEN); | ||
} | ||
|
||
close(fd); | ||
return 0; | ||
} | ||
|
||
static int uart_rx_loop(void) | ||
{ | ||
int fd = 0; | ||
char port[20] = {'\0'}; | ||
ssize_t ret_size; | ||
int remain_size; | ||
char *read_ptr; | ||
int rx_test_count = 0; | ||
char read_buf[TEST_STR_LEN]; | ||
|
||
printf("UART RX THREAD START\n"); | ||
|
||
sprintf(port, UART_DEV_PATH, CONFIG_EXAMPLES_UART_LOOPBACK_PORT); | ||
fd = open(port, O_RDWR | O_SYNC, 0666); | ||
if (fd < 0) { | ||
printf("ERROR: Failed to open Rx UART(%d):\n", get_errno()); | ||
return -1; | ||
} | ||
|
||
while (is_running) { | ||
rx_test_count++; | ||
read_ptr = &read_buf; | ||
remain_size = TEST_STR_LEN; | ||
|
||
while (0 < remain_size) { | ||
|
||
#ifndef CONFIG_DISABLE_POLL | ||
struct pollfd fds[1]; | ||
fds[0].fd = fd; | ||
fds[0].events = POLLIN; | ||
if (poll(fds, 1, UART_POLL_TIMEOUT_MS) < 0) { | ||
printf("Fail to poll(%d):\n", get_errno()); | ||
close(fd); | ||
return -1; | ||
} | ||
if (!(fds[0].revents & POLLIN)) { | ||
printf("RESULT(%d): FAILED (Timeout)\n"); | ||
continue; | ||
} | ||
#endif | ||
ret_size = read(fd, (void *)read_ptr, remain_size); | ||
remain_size -= ret_size; | ||
read_ptr += ret_size; | ||
} | ||
printf("RECEIVE(%d): %s\n", rx_test_count, read_buf); | ||
if (strncmp(read_buf, TEST_STR, TEST_STR_LEN) == 0) { | ||
printf("RESULT(%d): PASSED\n", rx_test_count); | ||
} else { | ||
printf("RESULT(%d): FAILED (It does not match)\n", rx_test_count); | ||
} | ||
} | ||
|
||
close(fd); | ||
return 0; | ||
} | ||
|
||
static void help_func(void) | ||
{ | ||
printf("usage: uart_loopback start/stop \n\n"); | ||
printf("This test is to check if the same data is read as it was written through uart.\n"); | ||
printf("For this test, you need to short-circuit the UART TX PIN and the UART RX PIN.\n"); | ||
printf("This default uart port is /dev/ttyS2, you can change CONFIG_EXAMPLES_UART_LOOPBACK_PORT.\n\n"); | ||
printf(" start\t\t Start uart loopback test\n"); | ||
printf(" stop\t\t stop uart loopback test\n"); | ||
} | ||
|
||
/**************************************************************************** | ||
* Public functions | ||
****************************************************************************/ | ||
#ifdef CONFIG_BUILD_KERNEL | ||
int main(int argc, FAR char *argv[]) | ||
#else | ||
int uart_loopback_main(int argc, char **argv) | ||
#endif | ||
{ | ||
|
||
if (argc != 2 || strncmp(argv[1], "help", 5) == 0) { | ||
help_func(); | ||
return 0; | ||
} | ||
|
||
if (strncmp(argv[1], "start", 6) == 0) { | ||
|
||
if (is_running) { | ||
printf("uart_loopback is already running\n"); | ||
return 0; | ||
} | ||
|
||
printf("######################### UART loopback test START #########################\n"); | ||
|
||
is_running = 1; | ||
|
||
if (pthread_create(&g_rx_tid, NULL, (pthread_startroutine_t)uart_rx_loop, NULL) < 0) { | ||
printf("Failed to create rx pthread(%d):\n", get_errno()); | ||
return -1; | ||
} | ||
(void)pthread_setname_np(g_rx_tid, "uart_loopback_rx"); | ||
|
||
if (pthread_create(&g_tx_tid, NULL, (pthread_startroutine_t)uart_tx_loop, NULL) < 0) { | ||
printf("Failed to create tx pthread(%d):\n", get_errno()); | ||
pthread_cancel(g_rx_tid); | ||
return -1; | ||
} | ||
(void)pthread_setname_np(g_tx_tid, "uart_loopback_tx"); | ||
|
||
} else if (strncmp(argv[1], "stop", 5) == 0) { | ||
if (!is_running) { | ||
printf("uart_loopback was not running\n"); | ||
return 0; | ||
} | ||
|
||
is_running = 0; | ||
|
||
if (pthread_join(g_rx_tid, NULL) < 0) { | ||
printf("Fail to join rx thread(%d):\n", get_errno()); | ||
} | ||
if (pthread_join(g_rx_tid, NULL) < 0) { | ||
printf("Fail to join tx thread(%d):\n", get_errno()); | ||
} | ||
|
||
printf("######################### UART loopback test END ###########################\n"); | ||
|
||
} else { | ||
help_func(); | ||
} | ||
|
||
return 0; | ||
} |