Skip to content

Commit 18f677e

Browse files
committed
Implement the BufferedSerial class to replace UARTSerial
`BufferedSerial` is `UARTSerial` renamed to convey the original purpose of the class.
1 parent 2d3c402 commit 18f677e

File tree

4 files changed

+921
-0
lines changed

4 files changed

+921
-0
lines changed
+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Copyright (c) 2019 Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#if !DEVICE_SERIAL
18+
#error [NOT_SUPPORTED] serial communication not supported for this target
19+
#else
20+
21+
#include "mbed.h"
22+
#include "utest/utest.h"
23+
#include "unity/unity.h"
24+
#include "greentea-client/test_env.h"
25+
#include "platform/FileHandle.h"
26+
#include "drivers/BufferedSerial.h"
27+
28+
29+
using namespace utest::v1;
30+
31+
32+
/**
33+
* Macros for setting console flow control.
34+
*/
35+
#define CONSOLE_FLOWCONTROL_RTS 1
36+
#define CONSOLE_FLOWCONTROL_CTS 2
37+
#define CONSOLE_FLOWCONTROL_RTSCTS 3
38+
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
39+
#define mbed_console_concat(x) mbed_console_concat_(x)
40+
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
41+
42+
43+
#define MSG_KEY_ECHO_MESSAGE "echo_message"
44+
#define MSG_VALUE_HELLO_WORLD "Hello, world!"
45+
46+
#define EXPECTED_ECHOED_STRING "{{" MSG_KEY_ECHO_MESSAGE ";" MSG_VALUE_HELLO_WORLD "}}"
47+
// The target is expected to transmit Greentea messages with \n (or \r\n) or they are not detected by the host
48+
#define STRING_TO_SEND EXPECTED_ECHOED_STRING "\n"
49+
50+
51+
static BufferedSerial buffered_serial_obj(
52+
USBTX, USBRX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE
53+
);
54+
55+
56+
FileHandle *mbed::mbed_override_console(int fd)
57+
{
58+
return &buffered_serial_obj;
59+
}
60+
61+
static ssize_t buffered_serial_read(void *buffer, ssize_t length)
62+
{
63+
if (length == 0) {
64+
return 0;
65+
}
66+
67+
// Ignore the `\n` character previously sent to the host in the previous
68+
// key-value pair that may not have been removed from the FIFO.
69+
unsigned char *buf = static_cast<unsigned char *>(buffer);
70+
buffered_serial_obj.read(buf, 1);
71+
ssize_t i = (buf[0] == '{') ? 1 : 0;
72+
73+
// Get the message sent by the host
74+
for (; i < length; i++) {
75+
TEST_ASSERT_EQUAL_UINT(1, buffered_serial_obj.read(buf + i, 1));
76+
}
77+
78+
return length;
79+
}
80+
81+
82+
// Test that data sent using an UnbufferedSerial object is correctly sent.
83+
// The test case sends a Greentea key-value pair message from the target to the
84+
// host using an UnbufferedSerial object and expects the message
85+
// to be echoed back by the host. The host response is received via the Greentea
86+
// framework usual route using greentea_parse_kv(). Success is determined upon
87+
// reception of the echoed message which indicates that the message was received
88+
// by the host as it was sent by the target.
89+
static void test_serial_write()
90+
{
91+
char tx_msg[] = STRING_TO_SEND;
92+
93+
TEST_ASSERT_EQUAL_UINT(
94+
strlen(tx_msg) + 1,
95+
buffered_serial_obj.write(tx_msg, strlen(tx_msg) + 1)
96+
);
97+
98+
char rx_key[30] = {0};
99+
char rx_value[30] = {0};
100+
greentea_parse_kv(rx_key, rx_value, sizeof(rx_key), sizeof(rx_value));
101+
102+
TEST_ASSERT_EQUAL_STRING(MSG_KEY_ECHO_MESSAGE, rx_key);
103+
TEST_ASSERT_EQUAL_STRING(MSG_VALUE_HELLO_WORLD, rx_value);
104+
}
105+
106+
107+
// Test that data received using an UnbufferedSerial object is correctly received.
108+
// The test case sends a Greentea key-value pair message from the target to the
109+
// host via the Greentea framework usual route using greentea_send_kv().
110+
// It expects the message to be echoed back to the target. An UnbufferedSerial
111+
// object is used to handle the received message. Succes is determined upon
112+
// reception of a key-value pair matching the key-value pair sent by the target.
113+
static void test_serial_read()
114+
{
115+
greentea_send_kv(MSG_KEY_ECHO_MESSAGE, MSG_VALUE_HELLO_WORLD);
116+
117+
char rx_msg[sizeof(EXPECTED_ECHOED_STRING)] = {0};
118+
// Exclude the null terminator which is not read
119+
ssize_t expected_rx_msg_length = sizeof(EXPECTED_ECHOED_STRING) - 1;
120+
121+
buffered_serial_read(rx_msg, expected_rx_msg_length);
122+
123+
TEST_ASSERT_EQUAL_STRING(EXPECTED_ECHOED_STRING, rx_msg);
124+
}
125+
126+
127+
utest::v1::status_t greentea_setup(const size_t number_of_cases)
128+
{
129+
GREENTEA_SETUP(12, "serial_comms");
130+
131+
return greentea_test_setup_handler(number_of_cases);
132+
}
133+
134+
135+
utest::v1::status_t greentea_failure_handler(
136+
const Case *const source, const failure_t reason
137+
)
138+
{
139+
greentea_case_failure_abort_handler(source, reason);
140+
return STATUS_CONTINUE;
141+
}
142+
143+
144+
Case cases[] = {
145+
Case(
146+
"Bytes are correctly sent",
147+
test_serial_write, greentea_failure_handler
148+
),
149+
Case(
150+
"Bytes are correctly received",
151+
test_serial_read, greentea_failure_handler
152+
),
153+
};
154+
155+
156+
Specification specification(
157+
greentea_setup, cases, greentea_test_teardown_handler
158+
);
159+
160+
161+
int main()
162+
{
163+
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
164+
buffered_serial_obj.set_flow_control(
165+
SerialBase::RTS, STDIO_UART_RTS, NC
166+
);
167+
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
168+
buffered_serial_obj.set_flow_control(
169+
SerialBase::CTS, NC, STDIO_UART_CTS
170+
);
171+
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
172+
buffered_serial_obj.set_flow_control(
173+
SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS
174+
);
175+
#endif
176+
return !Harness::run(specification);
177+
}
178+
179+
#endif // !DEVICE_SERIAL

0 commit comments

Comments
 (0)