@@ -74,6 +74,12 @@ TEST_CASE("CRs are removed from the stdin correctly", "[vfs_uart]")
74
74
uart_vfs_dev_port_set_tx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_CRLF );
75
75
76
76
flush_stdin_stdout ();
77
+
78
+ // A test case with no use of uart driver
79
+ // For non-uart-driver-involved uart vfs, all reads are non-blocking
80
+ // If no data at the moment, read() returns directly;
81
+ // If there is data available at the moment, read() also returns directly with the currently available size
82
+
77
83
const char * send_str = "1234567890\n\r123\r\n4\n" ;
78
84
/* with CONFIG_NEWLIB_STDOUT_ADDCR, the following will be sent on the wire.
79
85
* (last character of each part is marked with a hat)
@@ -133,30 +139,46 @@ struct read_task_arg_t {
133
139
134
140
struct write_task_arg_t {
135
141
const char * str ;
142
+ size_t str_len ;
136
143
SemaphoreHandle_t done ;
137
144
};
138
145
139
- static void read_task_fn (void * varg )
146
+ static void read_blocking_task_fn (void * varg )
140
147
{
141
148
struct read_task_arg_t * parg = (struct read_task_arg_t * ) varg ;
142
- parg -> out_buffer [ 0 ] = 0 ;
149
+ memset ( parg -> out_buffer , 0 , parg -> out_buffer_len ) ;
143
150
144
151
fgets (parg -> out_buffer , parg -> out_buffer_len , stdin );
145
152
xSemaphoreGive (parg -> done );
146
153
vTaskDelete (NULL );
147
154
}
148
155
156
+ static void read_non_blocking_task_fn (void * varg )
157
+ {
158
+ struct read_task_arg_t * parg = (struct read_task_arg_t * ) varg ;
159
+ memset (parg -> out_buffer , 0 , parg -> out_buffer_len );
160
+ char * ptr = parg -> out_buffer ;
161
+
162
+ while (fgets (ptr , parg -> out_buffer_len , stdin ) != NULL ) {
163
+ while (* ptr != 0 ) {
164
+ ptr ++ ;
165
+ }
166
+ }
167
+ xSemaphoreGive (parg -> done );
168
+ vTaskDelete (NULL );
169
+ }
170
+
149
171
static void write_task_fn (void * varg )
150
172
{
151
173
struct write_task_arg_t * parg = (struct write_task_arg_t * ) varg ;
152
- fwrite_str_loopback (parg -> str , strlen ( parg -> str ) );
174
+ fwrite_str_loopback (parg -> str , parg -> str_len );
153
175
xSemaphoreGive (parg -> done );
154
176
vTaskDelete (NULL );
155
177
}
156
178
157
- TEST_CASE ("can write to UART while another task is reading " , "[vfs_uart]" )
179
+ TEST_CASE ("read with uart driver (blocking) " , "[vfs_uart]" )
158
180
{
159
- char out_buffer [32 ];
181
+ char out_buffer [32 ] = {} ;
160
182
size_t out_buffer_len = sizeof (out_buffer );
161
183
162
184
struct read_task_arg_t read_arg = {
@@ -165,8 +187,12 @@ TEST_CASE("can write to UART while another task is reading", "[vfs_uart]")
165
187
.done = xSemaphoreCreateBinary ()
166
188
};
167
189
190
+ // Send a string with length less than the read requested length
191
+ const char in_buffer [] = "!(@*#&(!*@&#((SDasdkjhadsl\n" ;
192
+ size_t in_buffer_len = sizeof (in_buffer );
168
193
struct write_task_arg_t write_arg = {
169
- .str = "!(@*#&(!*@&#((SDasdkjhadsl\n" ,
194
+ .str = in_buffer ,
195
+ .str_len = in_buffer_len ,
170
196
.done = xSemaphoreCreateBinary ()
171
197
};
172
198
@@ -176,14 +202,18 @@ TEST_CASE("can write to UART while another task is reading", "[vfs_uart]")
176
202
256 , 0 , 0 , NULL , 0 ));
177
203
uart_vfs_dev_use_driver (CONFIG_ESP_CONSOLE_UART_NUM );
178
204
179
- xTaskCreate (& read_task_fn , "vfs_read" , 4096 , & read_arg , 5 , NULL );
180
- vTaskDelay (10 );
205
+ // Start the read task first, it will block until data incoming
206
+ xTaskCreate (& read_blocking_task_fn , "vfs_read" , 4096 , & read_arg , 5 , NULL );
207
+
208
+ int res = xSemaphoreTake (read_arg .done , 100 / portTICK_PERIOD_MS );
209
+ TEST_ASSERT_FALSE (res );
210
+
181
211
xTaskCreate (& write_task_fn , "vfs_write" , 4096 , & write_arg , 6 , NULL );
182
212
183
- int res = xSemaphoreTake (write_arg .done , 100 / portTICK_PERIOD_MS );
213
+ res = xSemaphoreTake (write_arg .done , 100 / portTICK_PERIOD_MS );
184
214
TEST_ASSERT (res );
185
215
186
- res = xSemaphoreTake (read_arg .done , 100 / portTICK_PERIOD_MS );
216
+ res = xSemaphoreTake (read_arg .done , 100 / portTICK_PERIOD_MS ); // read() returns with currently available size
187
217
TEST_ASSERT (res );
188
218
189
219
TEST_ASSERT_EQUAL (0 , strcmp (write_arg .str , read_arg .out_buffer ));
@@ -195,6 +225,69 @@ TEST_CASE("can write to UART while another task is reading", "[vfs_uart]")
195
225
vTaskDelay (2 ); // wait for tasks to exit
196
226
}
197
227
228
+ TEST_CASE ("read with uart driver (non-blocking)" , "[vfs_uart]" )
229
+ {
230
+ char out_buffer [32 ] = {};
231
+ size_t out_buffer_len = sizeof (out_buffer );
232
+
233
+ struct read_task_arg_t read_arg = {
234
+ .out_buffer = out_buffer ,
235
+ .out_buffer_len = out_buffer_len ,
236
+ .done = xSemaphoreCreateBinary ()
237
+ };
238
+
239
+ // Send a string with length less than the read requested length
240
+ const char in_buffer [] = "!(@*#&(!*@&#((SDasdkjhad\nce" ; // read should not early return on \n
241
+ size_t in_buffer_len = sizeof (in_buffer );
242
+ struct write_task_arg_t write_arg = {
243
+ .str = in_buffer ,
244
+ .str_len = in_buffer_len ,
245
+ .done = xSemaphoreCreateBinary ()
246
+ };
247
+
248
+ flush_stdin_stdout ();
249
+
250
+ ESP_ERROR_CHECK (uart_driver_install (CONFIG_ESP_CONSOLE_UART_NUM ,
251
+ 256 , 0 , 0 , NULL , 0 ));
252
+ uart_vfs_dev_use_driver (CONFIG_ESP_CONSOLE_UART_NUM );
253
+
254
+ uart_vfs_dev_port_set_rx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_LF );
255
+ uart_vfs_dev_port_set_tx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_LF );
256
+
257
+ int flags = fcntl (STDIN_FILENO , F_GETFL , 0 );
258
+ fcntl (STDIN_FILENO , F_SETFL , flags | O_NONBLOCK );
259
+
260
+ // If start the read task first, it will return immediately
261
+ xTaskCreate (& read_non_blocking_task_fn , "vfs_read" , 4096 , & read_arg , 5 , NULL );
262
+
263
+ int res = xSemaphoreTake (read_arg .done , 100 / portTICK_PERIOD_MS );
264
+ TEST_ASSERT (res );
265
+
266
+ xTaskCreate (& write_task_fn , "vfs_write" , 4096 , & write_arg , 6 , NULL );
267
+ vTaskDelay (10 );
268
+ xTaskCreate (& read_non_blocking_task_fn , "vfs_read" , 4096 , & read_arg , 5 , NULL );
269
+
270
+ res = xSemaphoreTake (write_arg .done , 100 / portTICK_PERIOD_MS );
271
+ TEST_ASSERT (res );
272
+
273
+ res = xSemaphoreTake (read_arg .done , 1000 / portTICK_PERIOD_MS ); // read() returns with currently available size
274
+ TEST_ASSERT (res );
275
+
276
+ // string compare
277
+ for (int i = 0 ; i < in_buffer_len ; i ++ ) {
278
+ TEST_ASSERT_EQUAL (in_buffer [i ], out_buffer [i ]);
279
+ }
280
+
281
+ uart_vfs_dev_use_nonblocking (CONFIG_ESP_CONSOLE_UART_NUM );
282
+ fcntl (STDIN_FILENO , F_SETFL , flags );
283
+ uart_vfs_dev_port_set_rx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_CRLF );
284
+ uart_vfs_dev_port_set_tx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_CRLF );
285
+ uart_driver_delete (CONFIG_ESP_CONSOLE_UART_NUM );
286
+ vSemaphoreDelete (read_arg .done );
287
+ vSemaphoreDelete (write_arg .done );
288
+ vTaskDelay (2 ); // wait for tasks to exit
289
+ }
290
+
198
291
TEST_CASE ("fcntl supported in UART VFS" , "[vfs_uart]" )
199
292
{
200
293
int flags = fcntl (STDIN_FILENO , F_GETFL , 0 );
0 commit comments