@@ -107,10 +107,30 @@ static uint32_t sdio_rx_byte_count = 0;
107
107
// one-time trigger to start write thread
108
108
static bool sdio_start_write_thread = false;
109
109
110
- #if H_SDIO_HOST_RX_MODE == H_SDIO_HOST_STREAMING_MODE
111
- static uint32_t recv_buf_size = 0 ;
112
- static uint8_t * recv_buf = NULL ;
113
- #endif
110
+ /** structs to do double buffering
111
+ * sdio_read_task() writes Rx SDIO data to one buffer while
112
+ * sdio_data_to_rx_buf_task() transfers previously received data
113
+ * to the rx queue
114
+ */
115
+ typedef struct {
116
+ uint8_t * buf ;
117
+ uint32_t buf_size ;
118
+ } buf_info_t ;
119
+
120
+ typedef struct {
121
+ buf_info_t buffer [2 ];
122
+ int read_index ; // -1 means not in use
123
+ uint32_t read_data_len ;
124
+ int write_index ;
125
+ } double_buf_t ;
126
+
127
+ static double_buf_t double_buf ;
128
+
129
+ // sem to trigger sdio_data_to_rx_buf_task()
130
+ static semaphore_handle_t sem_double_buf_xfer_data ;
131
+
132
+ static void * sdio_rx_buf_thread ;
133
+ static void sdio_data_to_rx_buf_task (void const * pvParameters );
114
134
115
135
static esp_err_t sdio_generate_slave_intr (uint8_t intr_no );
116
136
@@ -568,10 +588,15 @@ static esp_err_t sdio_push_pkt_to_queue(uint8_t * rxbuff, uint16_t len, uint16_t
568
588
#if H_SDIO_HOST_RX_MODE != H_SDIO_HOST_STREAMING_MODE
569
589
// SDIO packet mode
570
590
// return a buffer big enough to contain the data
571
- static uint8_t * sdio_rx_get_buffer (uint32_t len )
591
+ static inline uint8_t * sdio_rx_get_buffer (uint32_t len )
572
592
{
573
- // return mempool allocated buffer
574
- return sdio_buffer_alloc (MEMSET_REQUIRED );
593
+ int index = double_buf .write_index ;
594
+ uint8_t * * buf = & double_buf .buffer [index ].buf ;
595
+
596
+ * buf = (uint8_t * )sdio_buffer_alloc (MEMSET_REQUIRED );
597
+ double_buf .buffer [index ].buf_size = len ;
598
+
599
+ return * buf ;
575
600
}
576
601
577
602
// this frees the buffer *before* it is queued
@@ -616,18 +641,21 @@ static uint8_t * sdio_rx_get_buffer(uint32_t len)
616
641
len = ((len + ESP_BLOCK_SIZE - 1 ) / ESP_BLOCK_SIZE ) * ESP_BLOCK_SIZE ;
617
642
#endif
618
643
619
- // (re)allocate a buffer big enough to contain the data stream
620
- if (len > recv_buf_size ) {
621
- if (recv_buf ) {
644
+ // (re)allocate a write buffer big enough to contain the data stream
645
+ int index = double_buf .write_index ;
646
+ uint8_t * * buf = & double_buf .buffer [index ].buf ;
647
+
648
+ if (len > double_buf .buffer [index ].buf_size ) {
649
+ if (* buf ) {
622
650
// free already allocated memory
623
- g_h .funcs -> _h_free (recv_buf );
651
+ g_h .funcs -> _h_free (* buf );
624
652
}
625
- recv_buf = (uint8_t * )MEM_ALLOC (len );
626
- assert (recv_buf );
627
- recv_buf_size = len ;
628
- ESP_LOGD (TAG , "recv_buf_size % ld" , recv_buf_size );
653
+ * buf = (uint8_t * )MEM_ALLOC (len );
654
+ assert (* buf );
655
+ double_buf . buffer [ index ]. buf_size = len ;
656
+ ESP_LOGD (TAG , "buf %d size: % ld" , index , double_buf . buffer [ index ]. buf_size );
629
657
}
630
- return recv_buf ;
658
+ return * buf ;
631
659
}
632
660
633
661
// this frees the buffer *before* it is queued
@@ -676,6 +704,31 @@ static esp_err_t sdio_push_data_to_queue(uint8_t * buf, uint32_t buf_len)
676
704
}
677
705
#endif
678
706
707
+ // double buffer task to transfer data from the current buffer to the queue
708
+ static void sdio_data_to_rx_buf_task (void const * pvParameters )
709
+ {
710
+ uint8_t * buf ;
711
+ uint32_t len ;
712
+
713
+ while (1 ) {
714
+ g_h .funcs -> _h_get_semaphore (sem_double_buf_xfer_data , HOSTED_BLOCK_MAX );
715
+
716
+ if (double_buf .read_index < 0 ) {
717
+ ESP_LOGE (TAG , "invalid double buf read_index" );
718
+ continue ;
719
+ }
720
+
721
+ buf = double_buf .buffer [double_buf .read_index ].buf ;
722
+ len = double_buf .read_data_len ;
723
+
724
+ if (sdio_push_data_to_queue (buf , len ))
725
+ ESP_LOGE (TAG , "Failed to push data to rx queue" );
726
+
727
+ // finished sending data: reset read_index
728
+ double_buf .read_index = -1 ;
729
+ }
730
+ }
731
+
679
732
static void sdio_read_task (void const * pvParameters )
680
733
{
681
734
esp_err_t res ;
@@ -843,11 +896,20 @@ static void sdio_read_task(void const* pvParameters)
843
896
sdio_rx_byte_count += len_from_slave ;
844
897
sdio_rx_byte_count = sdio_rx_byte_count % ESP_RX_BYTE_MAX ;
845
898
846
- if (ret )
899
+ if (unlikely ( ret ) )
847
900
continue ;
848
901
849
- if (sdio_push_data_to_queue (rxbuff , len_from_slave ))
850
- ESP_LOGE (TAG , "Failed to push data to rx queue" );
902
+ if (double_buf .read_index < 0 ) {
903
+ double_buf .read_index = double_buf .write_index ;
904
+ double_buf .read_data_len = len_from_slave ;
905
+ double_buf .write_index = (double_buf .write_index ) ? 0 : 1 ;
906
+ // trigger task to copy data to queue
907
+ g_h .funcs -> _h_post_semaphore (sem_double_buf_xfer_data );
908
+ } else {
909
+ // error: task to copy data to queue still running
910
+ ESP_LOGE (TAG , "task still writing Rx data to queue!" );
911
+ // don't send data to task, or update write_index
912
+ }
851
913
}
852
914
}
853
915
@@ -984,6 +1046,18 @@ void transport_init_internal(void)
984
1046
assert (sdio_handle );
985
1047
}
986
1048
1049
+ // initialise double buffering structs
1050
+ memset (& double_buf , 0 , sizeof (double_buf_t ));
1051
+ double_buf .read_index = -1 ; // indicates we are not reading anything
1052
+ double_buf .write_index = 0 ; // we will write into the first buffer
1053
+
1054
+ sem_double_buf_xfer_data = g_h .funcs -> _h_create_semaphore (1 );
1055
+ assert (sem_double_buf_xfer_data );
1056
+ g_h .funcs -> _h_get_semaphore (sem_double_buf_xfer_data , HOSTED_BLOCK_MAX );
1057
+
1058
+ sdio_rx_buf_thread = g_h .funcs -> _h_thread_create ("sdio_rx_buf" ,
1059
+ DFLT_TASK_PRIO , DFLT_TASK_STACK_SIZE , sdio_data_to_rx_buf_task , NULL );
1060
+
987
1061
sdio_read_thread = g_h .funcs -> _h_thread_create ("sdio_read" ,
988
1062
DFLT_TASK_PRIO , DFLT_TASK_STACK_SIZE , sdio_read_task , NULL );
989
1063
0 commit comments