@@ -160,6 +160,8 @@ struct _pbdrv_legodev_pup_uart_dev_t {
160160 struct pt pt ;
161161 /** Protothread for receiving sensor data, running in parallel to the data send thread. */
162162 struct pt recv_pt ;
163+ /** Child protothread of the main protothread used for reading data */
164+ struct pt read_pt ;
163165 /** Child protothread of the main protothread used for writing data */
164166 struct pt write_pt ;
165167 /** Timer for sending keepalive messages and other delays. */
@@ -199,8 +201,6 @@ struct _pbdrv_legodev_pup_uart_dev_t {
199201 uint32_t err_count ;
200202 /** Number of bad reads when receiving DATA ludev->msgs. */
201203 uint32_t num_data_err ;
202- /** Time of most recently started transmission. */
203- uint32_t tx_start_time ;
204204 /** Flag that indicates that good DATA ludev->msg has been received since last watchdog timeout. */
205205 bool data_rec ;
206206 /** Return value for synchronization thread. */
@@ -229,8 +229,6 @@ static pbdrv_legodev_pup_uart_dev_t ludevs[PBDRV_CONFIG_LEGODEV_PUP_UART_NUM_DEV
229229static uint8_t data_read_bufs [PBDRV_CONFIG_LEGODEV_PUP_UART_NUM_DEV ][PBDRV_LEGODEV_MAX_DATA_SIZE ] __attribute__((aligned (4 )));
230230static pbdrv_legodev_pup_uart_data_set_t data_set_bufs [PBDRV_CONFIG_LEGODEV_PUP_UART_NUM_DEV ];
231231
232- #define PBIO_PT_WAIT_READY (pt , expr ) PT_WAIT_UNTIL((pt), (expr) != PBIO_ERROR_AGAIN)
233-
234232pbdrv_legodev_pup_uart_dev_t * pbdrv_legodev_pup_uart_configure (uint8_t device_index , uint8_t uart_driver_index , pbio_dcmotor_t * dcmotor ) {
235233 pbdrv_legodev_pup_uart_dev_t * ludev = & ludevs [device_index ];
236234 ludev -> dcmotor = dcmotor ;
@@ -694,16 +692,6 @@ static void pbdrv_legodev_pup_uart_reset(pbdrv_legodev_pup_uart_dev_t *ludev) {
694692 }
695693}
696694
697- static PT_THREAD (pbdrv_legodev_pup_uart_send_prepared_msg (pbdrv_legodev_pup_uart_dev_t * ludev , pbio_error_t * err )) {
698- PT_BEGIN (& ludev -> write_pt );
699- ludev -> tx_start_time = pbdrv_clock_get_ms ();
700- PBIO_PT_WAIT_READY (& ludev -> write_pt , * err = pbdrv_uart_write_begin (ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT ));
701- if (* err == PBIO_SUCCESS ) {
702- PBIO_PT_WAIT_READY (& ludev -> write_pt , * err = pbdrv_uart_write_end (ludev -> uart ));
703- }
704- PT_END (& ludev -> write_pt );
705- }
706-
707695/**
708696 * The synchronization thread for the LEGO UART device.
709697 *
@@ -734,7 +722,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
734722
735723 pbdrv_uart_flush (ludev -> uart );
736724
737- PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_legodev_pup_uart_send_prepared_msg ( ludev , & ludev -> err ));
725+ PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_uart_write ( & ludev -> write_pt , ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT , & ludev -> err ));
738726 if (ludev -> err != PBIO_SUCCESS ) {
739727 DBG_ERR (ludev -> last_err = "Speed tx failed" );
740728 PT_EXIT (& ludev -> pt );
@@ -743,13 +731,8 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
743731 pbdrv_uart_flush (ludev -> uart );
744732
745733 // read one byte to check for ACK
746- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg , 1 , 10 ));
747- if (ludev -> err != PBIO_SUCCESS ) {
748- DBG_ERR (ludev -> last_err = "UART Rx error during baud" );
749- PT_EXIT (& ludev -> pt );
750- }
734+ PT_SPAWN (& ludev -> pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg , 1 , 10 , & ludev -> err ));
751735
752- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_end (ludev -> uart ));
753736 if ((ludev -> err == PBIO_SUCCESS && ludev -> rx_msg [0 ] != LUMP_SYS_ACK ) || ludev -> err == PBIO_ERROR_TIMEDOUT ) {
754737 // if we did not get ACK within 100ms, then switch to slow baud rate for sync
755738 pbdrv_uart_set_baud_rate (ludev -> uart , EV3_UART_SPEED_MIN );
@@ -758,18 +741,14 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
758741 DBG_ERR (ludev -> last_err = "UART Rx error during baud" );
759742 PT_EXIT (& ludev -> pt );
760743 }
761-
762744sync :
763745
764746 // To get in sync with the data stream from the sensor, we look for a valid TYPE command.
765747 for (;;) {
766-
767- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT ));
768- if (ludev -> err != PBIO_SUCCESS ) {
769- DBG_ERR (ludev -> last_err = "UART Rx error during sync" );
770- PT_EXIT (& ludev -> pt );
771- }
772- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_end (ludev -> uart ));
748+ // If there are multiple bytes waiting to be read, this drains them one
749+ // by one without requiring additional polls. This means we won't need
750+ // exact timing to get in sync.
751+ PT_SPAWN (& ludev -> pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
773752 if (ludev -> err == PBIO_ERROR_TIMEDOUT ) {
774753 continue ;
775754 }
@@ -784,13 +763,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
784763 }
785764
786765 // then read the rest of the message
787-
788- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg + 1 , 2 , EV3_UART_IO_TIMEOUT ));
789- if (ludev -> err != PBIO_SUCCESS ) {
790- DBG_ERR (ludev -> last_err = "UART Rx error while reading type" );
791- PT_EXIT (& ludev -> pt );
792- }
793- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_end (ludev -> uart ));
766+ PT_SPAWN (& ludev -> pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg + 1 , 2 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
794767 if (ludev -> err != PBIO_SUCCESS ) {
795768 DBG_ERR (ludev -> last_err = "UART Rx error while reading type" );
796769 PT_EXIT (& ludev -> pt );
@@ -825,12 +798,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
825798
826799 while (ludev -> status == PBDRV_LEGODEV_PUP_UART_STATUS_INFO ) {
827800 // read the message header
828- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT ));
829- if (ludev -> err != PBIO_SUCCESS ) {
830- DBG_ERR (ludev -> last_err = "UART Rx begin error during info header" );
831- PT_EXIT (& ludev -> pt );
832- }
833- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_end (ludev -> uart ));
801+ PT_SPAWN (& ludev -> pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
834802 if (ludev -> err != PBIO_SUCCESS ) {
835803 DBG_ERR (ludev -> last_err = "UART Rx end error during info header" );
836804 PT_EXIT (& ludev -> pt );
@@ -845,12 +813,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
845813
846814 // read the rest of the message
847815 if (ludev -> rx_msg_size > 1 ) {
848- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg + 1 , ludev -> rx_msg_size - 1 , EV3_UART_IO_TIMEOUT ));
849- if (ludev -> err != PBIO_SUCCESS ) {
850- DBG_ERR (ludev -> last_err = "UART Rx begin error during info" );
851- PT_EXIT (& ludev -> pt );
852- }
853- PBIO_PT_WAIT_READY (& ludev -> pt , ludev -> err = pbdrv_uart_read_end (ludev -> uart ));
816+ PT_SPAWN (& ludev -> pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg + 1 , ludev -> rx_msg_size - 1 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
854817 if (ludev -> err != PBIO_SUCCESS ) {
855818 DBG_ERR (ludev -> last_err = "UART Rx end error during info" );
856819 PT_EXIT (& ludev -> pt );
@@ -871,7 +834,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_synchronize_thread(pbdrv_legodev_pup_uar
871834 // reply with ACK
872835 ludev -> tx_msg [0 ] = LUMP_SYS_ACK ;
873836 ludev -> tx_msg_size = 1 ;
874- PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_legodev_pup_uart_send_prepared_msg ( ludev , & ludev -> err ));
837+ PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_uart_write ( & ludev -> write_pt , ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT , & ludev -> err ));
875838 if (ludev -> err != PBIO_SUCCESS ) {
876839 DBG_ERR (ludev -> last_err = "UART Tx error during ack." );
877840 PT_EXIT (& ludev -> pt );
@@ -942,7 +905,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_send_thread(pbdrv_legodev_pup_uart_dev_t
942905 ludev -> data_rec = false;
943906 ludev -> tx_msg [0 ] = LUMP_SYS_NACK ;
944907 ludev -> tx_msg_size = 1 ;
945- PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_legodev_pup_uart_send_prepared_msg ( ludev , & ludev -> err ));
908+ PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_uart_write ( & ludev -> write_pt , ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT , & ludev -> err ));
946909 if (ludev -> err != PBIO_SUCCESS ) {
947910 DBG_ERR (ludev -> last_err = "Error during keepalive." );
948911 PT_EXIT (& ludev -> pt );
@@ -959,7 +922,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_send_thread(pbdrv_legodev_pup_uart_dev_t
959922 if (ludev -> mode_switch .requested ) {
960923 ludev -> mode_switch .requested = false;
961924 ev3_uart_prepare_tx_msg (ludev , LUMP_MSG_TYPE_CMD , LUMP_CMD_SELECT , & ludev -> mode_switch .desired_mode , 1 );
962- PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_legodev_pup_uart_send_prepared_msg ( ludev , & ludev -> err ));
925+ PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_uart_write ( & ludev -> write_pt , ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT , & ludev -> err ));
963926 if (ludev -> err != PBIO_SUCCESS ) {
964927 DBG_ERR (ludev -> last_err = "Setting requested mode failed." );
965928 PT_EXIT (& ludev -> pt );
@@ -973,7 +936,7 @@ static PT_THREAD(pbdrv_legodev_pup_uart_send_thread(pbdrv_legodev_pup_uart_dev_t
973936 ev3_uart_prepare_tx_msg (ludev , LUMP_MSG_TYPE_DATA , ludev -> data_set -> desired_mode , ludev -> data_set -> bin_data , ludev -> data_set -> size );
974937 ludev -> data_set -> size = 0 ;
975938 ludev -> data_set -> time = pbdrv_clock_get_ms ();
976- PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_legodev_pup_uart_send_prepared_msg ( ludev , & ludev -> err ));
939+ PT_SPAWN (& ludev -> pt , & ludev -> write_pt , pbdrv_uart_write ( & ludev -> write_pt , ludev -> uart , ludev -> tx_msg , ludev -> tx_msg_size , EV3_UART_IO_TIMEOUT , & ludev -> err ));
977940 if (ludev -> err != PBIO_SUCCESS ) {
978941 DBG_ERR (ludev -> last_err = "Setting requested data failed." );
979942 PT_EXIT (& ludev -> pt );
@@ -1004,19 +967,11 @@ static PT_THREAD(pbdrv_legodev_pup_uart_receive_data_thread(pbdrv_legodev_pup_ua
1004967 // loose data. For now, the retry after bad message size helps get back into
1005968 // sync with the data stream.
1006969
1007- pbio_error_t err ;
1008-
1009970 PT_BEGIN (& ludev -> recv_pt );
1010971
1011972 while (true) {
1012- PBIO_PT_WAIT_READY (& ludev -> recv_pt ,
1013- err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT ));
1014- if (err != PBIO_SUCCESS ) {
1015- DBG_ERR (ludev -> last_err = "UART Rx data header begin error" );
1016- break ;
1017- }
1018- PBIO_PT_WAIT_READY (& ludev -> recv_pt , err = pbdrv_uart_read_end (ludev -> uart ));
1019- if (err != PBIO_SUCCESS ) {
973+ PT_SPAWN (& ludev -> recv_pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg , 1 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
974+ if (ludev -> err != PBIO_SUCCESS ) {
1020975 DBG_ERR (ludev -> last_err = "UART Rx data header end error" );
1021976 break ;
1022977 }
@@ -1035,14 +990,8 @@ static PT_THREAD(pbdrv_legodev_pup_uart_receive_data_thread(pbdrv_legodev_pup_ua
1035990 continue ;
1036991 }
1037992
1038- PBIO_PT_WAIT_READY (& ludev -> recv_pt ,
1039- err = pbdrv_uart_read_begin (ludev -> uart , ludev -> rx_msg + 1 , ludev -> rx_msg_size - 1 , EV3_UART_IO_TIMEOUT ));
1040- if (err != PBIO_SUCCESS ) {
1041- DBG_ERR (ludev -> last_err = "UART Rx data begin error" );
1042- break ;
1043- }
1044- PBIO_PT_WAIT_READY (& ludev -> recv_pt , err = pbdrv_uart_read_end (ludev -> uart ));
1045- if (err != PBIO_SUCCESS ) {
993+ PT_SPAWN (& ludev -> recv_pt , & ludev -> read_pt , pbdrv_uart_read (& ludev -> read_pt , ludev -> uart , ludev -> rx_msg + 1 , ludev -> rx_msg_size - 1 , EV3_UART_IO_TIMEOUT , & ludev -> err ));
994+ if (ludev -> err != PBIO_SUCCESS ) {
1046995 DBG_ERR (ludev -> last_err = "UART Rx data end error" );
1047996 break ;
1048997 }
0 commit comments