1 /* UART Echo Example
2
3 This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <stdio.h>
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/task.h"
12 #include "driver/uart.h"
13 #include "soc/uart_periph.h"
14 #include "esp_rom_gpio.h"
15 #include "driver/gpio.h"
16 #include "hal/gpio_hal.h"
17 #include "sdkconfig.h"
18 #include "esp_console.h"
19 #include "linenoise/linenoise.h"
20 #include <string.h>
21
22 #define DEFAULT_UART_CHANNEL (0)
23 #define CONSOLE_UART_CHANNEL (1 - DEFAULT_UART_CHANNEL)
24 #define DEFAULT_UART_RX_PIN (3)
25 #define DEFAULT_UART_TX_PIN (2)
26 #define CONSOLE_UART_RX_PIN (4)
27 #define CONSOLE_UART_TX_PIN (5)
28
29 #define UARTS_BAUD_RATE (115200)
30 #define TASK_STACK_SIZE (2048)
31 #define READ_BUF_SIZE (1024)
32
33 /* Message printed by the "consoletest" command.
34 * It will also be used by the default UART to check the reply of the second
35 * UART. As end of line characters are not standard here (\n, \r\n, \r...),
36 * let's not include it in this string. */
37 const char test_message[] = "This is an example string, if you can read this, the example is a success!";
38
39 /**
40 * @brief This function connects default UART TX to console UART RX and default
41 * UART RX to console UART TX. The purpose is to send commands to the console
42 * and get the reply directly by reading RX FIFO.
43 */
connect_uarts(void)44 static void connect_uarts(void)
45 {
46 esp_rom_gpio_connect_out_signal(DEFAULT_UART_RX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_TX_PIN_IDX), false, false);
47 esp_rom_gpio_connect_in_signal(DEFAULT_UART_RX_PIN, UART_PERIPH_SIGNAL(0, SOC_UART_RX_PIN_IDX), false);
48
49 esp_rom_gpio_connect_out_signal(DEFAULT_UART_TX_PIN, UART_PERIPH_SIGNAL(0, SOC_UART_TX_PIN_IDX), false, false);
50 esp_rom_gpio_connect_in_signal(DEFAULT_UART_TX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_RX_PIN_IDX), false);
51 }
52
53 /**
54 * @brief Disconnect default UART from the console UART, this is used once
55 * testing is finished, it will let us print messages on the UART without
56 * sending them back to the console UART. Else, we would get an infinite
57 * loop.
58 */
disconnect_uarts(void)59 static void disconnect_uarts(void)
60 {
61 esp_rom_gpio_connect_out_signal(CONSOLE_UART_TX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_TX_PIN_IDX), false, false);
62 esp_rom_gpio_connect_in_signal(CONSOLE_UART_RX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_RX_PIN_IDX), false);
63 }
64
65 /**
66 * @brief Configure and install the default UART, then, connect it to the
67 * console UART.
68 */
configure_uarts(void)69 static void configure_uarts(void)
70 {
71 /* Configure parameters of an UART driver,
72 * communication pins and install the driver */
73 uart_config_t uart_config = {
74 .baud_rate = UARTS_BAUD_RATE,
75 .data_bits = UART_DATA_8_BITS,
76 .parity = UART_PARITY_DISABLE,
77 .stop_bits = UART_STOP_BITS_1,
78 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
79 .source_clk = UART_SCLK_APB,
80 };
81
82 ESP_ERROR_CHECK(uart_driver_install(DEFAULT_UART_CHANNEL, READ_BUF_SIZE * 2, 0, 0, NULL, 0));
83 ESP_ERROR_CHECK(uart_param_config(DEFAULT_UART_CHANNEL, &uart_config));
84 ESP_ERROR_CHECK(uart_set_pin(DEFAULT_UART_CHANNEL, DEFAULT_UART_TX_PIN, DEFAULT_UART_RX_PIN,
85 UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
86
87
88 connect_uarts();
89 }
90
91 /**
92 * @brief Function called when command `consoletest` will be invoked.
93 * It will simply print `test_message` defined above.
94 */
console_test(int argc,char ** argv)95 static int console_test(int argc, char **argv) {
96 printf("%s\n", test_message);
97 return 0;
98 }
99
100 /**
101 * @brief Function executed in another task then main one (as the one main
102 * executes REPL console).
103 * It will send "consoletest" command to the console UART and then read back
104 * the response on RX.
105 * The response shall contain the test_message string.
106 */
send_commands(void * arg)107 static void send_commands(void* arg) {
108 static char data[READ_BUF_SIZE];
109 char command[] = "consoletest\n";
110 int len = 0;
111 void* substring = NULL;
112
113 /* Discard the first messages sent by the console. */
114 do {
115 len = uart_read_bytes(DEFAULT_UART_CHANNEL, data, READ_BUF_SIZE, 100 / portTICK_RATE_MS);
116 } while (len == 0);
117
118 if ( len == -1 ) {
119 goto end;
120 }
121 /* Send the command `consoletest` to the console UART. */
122 len = uart_write_bytes(DEFAULT_UART_CHANNEL, command, sizeof(command));
123 if ( len == -1 ) {
124 goto end;
125 }
126
127 /* Get the answer back from the console, give it some delay. */
128 do {
129 len = uart_read_bytes(DEFAULT_UART_CHANNEL, data, READ_BUF_SIZE - 1, 250 / portTICK_RATE_MS);
130 } while (len == 0);
131
132 if ( len == -1 ) {
133 goto end;
134 }
135
136 /**
137 * Check whether we can find test_message in the received message. Before
138 * that, we need to add a NULL character to terminate the string.
139 */
140 data[len] = 0;
141 substring = strcasestr(data, test_message);
142
143 end:
144 /* This is a must to not send anything to the console anymore! */
145 disconnect_uarts();
146 printf("Result: %s\n", substring == NULL ? "Failure" : "Success");
147 vTaskDelete(NULL);
148 }
149
app_main(void)150 void app_main(void)
151 {
152 esp_console_repl_t *repl = NULL;
153 esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
154 repl_config.prompt = "repl >";
155 const esp_console_cmd_t cmd = {
156 .command = "consoletest",
157 .help = "Test console by sending a message",
158 .func = &console_test,
159 };
160 esp_console_dev_uart_config_t uart_config = {
161 .channel = CONSOLE_UART_CHANNEL,
162 .baud_rate = UARTS_BAUD_RATE,
163 .tx_gpio_num = CONSOLE_UART_TX_PIN,
164 .rx_gpio_num = CONSOLE_UART_RX_PIN,
165 };
166 /**
167 * As we don't have a real serial terminal, (we just use default UART to
168 * send and receive commands, ) we won't handle any escape sequence, so the
169 * easiest thing to do is set the console to "dumb" mode. */
170 linenoiseSetDumbMode(1);
171
172 ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
173 configure_uarts();
174
175 ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
176
177 /* Create a task for sending and receiving commands to and from the second UART. */
178 xTaskCreate(send_commands, "send_commands_task", TASK_STACK_SIZE, NULL, 10, NULL);
179
180 ESP_ERROR_CHECK(esp_console_start_repl(repl));
181 }
182