@@ -74,6 +74,12 @@ TEST_CASE("CRs are removed from the stdin correctly", "[vfs_uart]")
7474 uart_vfs_dev_port_set_tx_line_endings (CONFIG_ESP_CONSOLE_UART_NUM , ESP_LINE_ENDINGS_CRLF );
7575
7676 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+
7783 const char * send_str = "1234567890\n\r123\r\n4\n" ;
7884 /* with CONFIG_NEWLIB_STDOUT_ADDCR, the following will be sent on the wire.
7985 * (last character of each part is marked with a hat)
@@ -133,30 +139,46 @@ struct read_task_arg_t {
133139
134140struct write_task_arg_t {
135141 const char * str ;
142+ size_t str_len ;
136143 SemaphoreHandle_t done ;
137144};
138145
139- static void read_task_fn (void * varg )
146+ static void read_blocking_task_fn (void * varg )
140147{
141148 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 ) ;
143150
144151 fgets (parg -> out_buffer , parg -> out_buffer_len , stdin );
145152 xSemaphoreGive (parg -> done );
146153 vTaskDelete (NULL );
147154}
148155
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+
149171static void write_task_fn (void * varg )
150172{
151173 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 );
153175 xSemaphoreGive (parg -> done );
154176 vTaskDelete (NULL );
155177}
156178
157- TEST_CASE ("can write to UART while another task is reading " , "[vfs_uart]" )
179+ TEST_CASE ("read with uart driver (blocking) " , "[vfs_uart]" )
158180{
159- char out_buffer [32 ];
181+ char out_buffer [32 ] = {} ;
160182 size_t out_buffer_len = sizeof (out_buffer );
161183
162184 struct read_task_arg_t read_arg = {
@@ -165,8 +187,12 @@ TEST_CASE("can write to UART while another task is reading", "[vfs_uart]")
165187 .done = xSemaphoreCreateBinary ()
166188 };
167189
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 );
168193 struct write_task_arg_t write_arg = {
169- .str = "!(@*#&(!*@&#((SDasdkjhadsl\n" ,
194+ .str = in_buffer ,
195+ .str_len = in_buffer_len ,
170196 .done = xSemaphoreCreateBinary ()
171197 };
172198
@@ -176,14 +202,18 @@ TEST_CASE("can write to UART while another task is reading", "[vfs_uart]")
176202 256 , 0 , 0 , NULL , 0 ));
177203 uart_vfs_dev_use_driver (CONFIG_ESP_CONSOLE_UART_NUM );
178204
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+
181211 xTaskCreate (& write_task_fn , "vfs_write" , 4096 , & write_arg , 6 , NULL );
182212
183- int res = xSemaphoreTake (write_arg .done , 100 / portTICK_PERIOD_MS );
213+ res = xSemaphoreTake (write_arg .done , 100 / portTICK_PERIOD_MS );
184214 TEST_ASSERT (res );
185215
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
187217 TEST_ASSERT (res );
188218
189219 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]")
195225 vTaskDelay (2 ); // wait for tasks to exit
196226}
197227
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+
198291TEST_CASE ("fcntl supported in UART VFS" , "[vfs_uart]" )
199292{
200293 int flags = fcntl (STDIN_FILENO , F_GETFL , 0 );
0 commit comments