@@ -204,6 +204,42 @@ static size_t usj_drain_rx(struct UARTData *uart_data, uint8_t *out, size_t max_
204204}
205205#endif
206206
207+ static size_t uart_received_len (struct UARTData * uart_data )
208+ {
209+ #if SOC_USB_SERIAL_JTAG_SUPPORTED
210+ if (uart_data -> use_usj ) {
211+ return usj_rx_available (uart_data );
212+ }
213+ #endif
214+ size_t count = 0 ;
215+ uart_get_buffered_data_len (uart_data -> uart_num , & count );
216+ return count ;
217+ }
218+
219+ // Reads up to max_len received bytes without waiting, and returns how many it read.
220+ // The other scheduler may have taken some since they were counted: waiting for them
221+ // would block this one until the peer sends more, which may be never.
222+ static size_t uart_read_received (struct UARTData * uart_data , uint8_t * buf , size_t max_len )
223+ {
224+ #if SOC_USB_SERIAL_JTAG_SUPPORTED
225+ if (uart_data -> use_usj ) {
226+ return usj_drain_rx (uart_data , buf , max_len );
227+ }
228+ #endif
229+ int read = uart_read_bytes (uart_data -> uart_num , buf , max_len , 0 );
230+ return read > 0 ? (size_t ) read : 0 ;
231+ }
232+
233+ static uint8_t * alloc_read_buf (size_t count )
234+ {
235+ uint8_t * buf = malloc (count );
236+ if (IS_NULL_PTR (buf )) {
237+ fprintf (stderr , "Failed to allocate memory size %i: %s:%i.\n" , (int ) count , __FILE__ , __LINE__ );
238+ AVM_ABORT ();
239+ }
240+ return buf ;
241+ }
242+
207243EventListener * uart_interrupt_callback (GlobalContext * glb , EventListener * listener )
208244{
209245 struct UARTData * uart_data = GET_LIST_ENTRY (listener , struct UARTData , listener );
@@ -214,65 +250,28 @@ EventListener *uart_interrupt_callback(GlobalContext *glb, EventListener *listen
214250 case UART_DATA_BREAK :
215251 case UART_DATA :
216252 if (uart_data -> reader_process_pid != term_invalid_term ()) {
217- size_t count = event .size ;
218- uint8_t * usj_buf = NULL ;
219- #if SOC_USB_SERIAL_JTAG_SUPPORTED
220- if (!uart_data -> use_usj )
221- #endif
222- {
223- // A read that found data took the bytes of events still queued: an event
224- // may announce more than the buffer holds, even nothing. Reading what it
225- // announced would block the scheduler until that many bytes arrive.
226- size_t buffered = 0 ;
227- uart_get_buffered_data_len (uart_data -> uart_num , & buffered );
228- if (buffered < count ) {
229- count = buffered ;
230- }
231- if (count == 0 ) {
232- break ;
233- }
253+ // Not event.size: a read that found data took the bytes of events still
254+ // queued, so an event may announce more than the buffer holds, even nothing.
255+ size_t count = uart_received_len (uart_data );
256+ if (count == 0 ) {
257+ break ;
234258 }
235- #if SOC_USB_SERIAL_JTAG_SUPPORTED
236- if (uart_data -> use_usj ) {
237- count = usj_rx_available (uart_data );
238- if (count == 0 ) {
239- break ;
240- }
241- usj_buf = malloc (count );
242- if (IS_NULL_PTR (usj_buf )) {
243- fprintf (stderr , "Failed to allocate memory size %i: %s:%i.\n" , (int ) count , __FILE__ , __LINE__ );
244- AVM_ABORT ();
245- }
246- count = usj_drain_rx (uart_data , usj_buf , count );
247- if (count == 0 ) {
248- free (usj_buf );
249- break ;
250- }
259+ uint8_t * buf = alloc_read_buf (count );
260+ count = uart_read_received (uart_data , buf , count );
261+ if (count == 0 ) {
262+ free (buf );
263+ break ;
251264 }
252- #endif
253- int bin_size = term_binary_heap_size (count );
254265
255266 Heap heap ;
256- if (UNLIKELY (memory_init_heap (& heap , bin_size + TERM_BOXED_REFERENCE_SHORT_SIZE + TUPLE_SIZE (2 ) * 2 ) != MEMORY_GC_OK )) {
257- free (usj_buf );
267+ if (UNLIKELY (memory_init_heap (& heap , term_binary_heap_size ( count ) + TERM_BOXED_REFERENCE_SHORT_SIZE + TUPLE_SIZE (2 ) * 2 ) != MEMORY_GC_OK )) {
268+ free (buf );
258269 fprintf (stderr , "Failed to allocate memory: %s:%i.\n" , __FILE__ , __LINE__ );
259270 AVM_ABORT ();
260271 }
261272
262- term bin = term_create_uninitialized_binary (count , & heap , glb );
263- uint8_t * bin_buf = (uint8_t * ) term_binary_data (bin );
264- #if SOC_USB_SERIAL_JTAG_SUPPORTED
265- if (uart_data -> use_usj ) {
266- memcpy (bin_buf , usj_buf , count );
267- free (usj_buf );
268- }
269- #endif
270- #if SOC_USB_SERIAL_JTAG_SUPPORTED
271- if (!uart_data -> use_usj )
272- #endif
273- {
274- uart_read_bytes (uart_data -> uart_num , bin_buf , count , 0 );
275- }
273+ term bin = term_from_literal_binary (buf , count , & heap , glb );
274+ free (buf );
276275
277276 term ok_tuple = term_alloc_tuple (2 , & heap );
278277 term_put_tuple_element (ok_tuple , 0 , OK_ATOM );
@@ -604,68 +603,35 @@ static void uart_driver_do_read(Context *ctx, GenMessage gen_message)
604603 return ;
605604 }
606605
607- size_t count = 0 ;
608- #if SOC_USB_SERIAL_JTAG_SUPPORTED
609- if (uart_data -> use_usj ) {
610- count = usj_rx_available (uart_data );
611- }
612- #endif
613- #if SOC_USB_SERIAL_JTAG_SUPPORTED
614- if (!uart_data -> use_usj )
615- #endif
616- {
617- uart_get_buffered_data_len (uart_data -> uart_num , & count );
606+ size_t count = uart_received_len (uart_data );
607+ if (count == 0 ) {
608+ safe_update_reader_data (uart_data , pid , ref_ticks );
609+ return ;
618610 }
619611
620- if (count > 0 ) {
621- uint8_t * usj_buf = NULL ;
622- #if SOC_USB_SERIAL_JTAG_SUPPORTED
623- if (uart_data -> use_usj ) {
624- usj_buf = malloc (count );
625- if (IS_NULL_PTR (usj_buf )) {
626- fprintf (stderr , "Failed to allocate memory size %i: %s:%i.\n" , (int ) count , __FILE__ , __LINE__ );
627- AVM_ABORT ();
628- }
629- count = usj_drain_rx (uart_data , usj_buf , count );
630- if (count == 0 ) {
631- free (usj_buf );
632- safe_update_reader_data (uart_data , pid , ref_ticks );
633- return ;
634- }
635- }
636- #endif
637- int bin_size = term_binary_heap_size (count );
638- if (UNLIKELY (memory_ensure_free_with_roots (ctx , bin_size + TUPLE_SIZE (2 ) * 2 , 1 , & ref , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
639- free (usj_buf );
640- ESP_LOGE (TAG , "[uart_driver_do_read] Failed to allocate space for return value" );
641- globalcontext_send_message (glb , local_pid , OUT_OF_MEMORY_ATOM );
642- return ;
643- }
612+ // Before reading: on failure the bytes stay for the next read.
613+ if (UNLIKELY (memory_ensure_free_with_roots (ctx , term_binary_heap_size (count ) + TUPLE_SIZE (2 ) * 2 , 1 , & ref , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
614+ ESP_LOGE (TAG , "[uart_driver_do_read] Failed to allocate space for return value" );
615+ globalcontext_send_message (glb , local_pid , OUT_OF_MEMORY_ATOM );
616+ return ;
617+ }
644618
645- term bin = term_create_uninitialized_binary (count , & ctx -> heap , glb );
646- uint8_t * bin_buf = (uint8_t * ) term_binary_data (bin );
647- #if SOC_USB_SERIAL_JTAG_SUPPORTED
648- if (uart_data -> use_usj ) {
649- memcpy (bin_buf , usj_buf , count );
650- free (usj_buf );
651- }
652- #endif
653- #if SOC_USB_SERIAL_JTAG_SUPPORTED
654- if (!uart_data -> use_usj )
655- #endif
656- {
657- uart_read_bytes (uart_data -> uart_num , bin_buf , count , portMAX_DELAY );
658- }
619+ uint8_t * buf = alloc_read_buf (count );
620+ count = uart_read_received (uart_data , buf , count );
621+ if (count == 0 ) {
622+ free (buf );
623+ safe_update_reader_data (uart_data , pid , ref_ticks );
624+ return ;
625+ }
659626
660- term ok_tuple = term_alloc_tuple (2 , & ctx -> heap );
661- term_put_tuple_element (ok_tuple , 0 , OK_ATOM );
662- term_put_tuple_element (ok_tuple , 1 , bin );
627+ term bin = term_from_literal_binary (buf , count , & ctx -> heap , glb );
628+ free (buf );
663629
664- port_send_reply (ctx , pid , ref , ok_tuple );
630+ term ok_tuple = term_alloc_tuple (2 , & ctx -> heap );
631+ term_put_tuple_element (ok_tuple , 0 , OK_ATOM );
632+ term_put_tuple_element (ok_tuple , 1 , bin );
665633
666- } else {
667- safe_update_reader_data (uart_data , pid , ref_ticks );
668- }
634+ port_send_reply (ctx , pid , ref , ok_tuple );
669635}
670636
671637static void uart_driver_do_cancel_read (Context * ctx , GenMessage gen_message )
0 commit comments