Skip to content

Commit 2edbc1b

Browse files
committed
Merge branch 'feat/improve_sdio' into 'feature/esp_as_mcu_host'
feat/improve_sdio Use double buffering to improve SDIO Rx See merge request app-frameworks/esp_hosted!490
2 parents a3058fd + 82ec2a5 commit 2edbc1b

File tree

1 file changed

+93
-19
lines changed

1 file changed

+93
-19
lines changed

host/drivers/transport/sdio/sdio_drv.c

Lines changed: 93 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,30 @@ static uint32_t sdio_rx_byte_count = 0;
107107
// one-time trigger to start write thread
108108
static bool sdio_start_write_thread = false;
109109

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);
114134

115135
static esp_err_t sdio_generate_slave_intr(uint8_t intr_no);
116136

@@ -568,10 +588,15 @@ static esp_err_t sdio_push_pkt_to_queue(uint8_t * rxbuff, uint16_t len, uint16_t
568588
#if H_SDIO_HOST_RX_MODE != H_SDIO_HOST_STREAMING_MODE
569589
// SDIO packet mode
570590
// 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)
572592
{
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;
575600
}
576601

577602
// this frees the buffer *before* it is queued
@@ -616,18 +641,21 @@ static uint8_t * sdio_rx_get_buffer(uint32_t len)
616641
len = ((len + ESP_BLOCK_SIZE - 1) / ESP_BLOCK_SIZE) * ESP_BLOCK_SIZE;
617642
#endif
618643

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) {
622650
// free already allocated memory
623-
g_h.funcs->_h_free(recv_buf);
651+
g_h.funcs->_h_free(*buf);
624652
}
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);
629657
}
630-
return recv_buf;
658+
return *buf;
631659
}
632660

633661
// 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)
676704
}
677705
#endif
678706

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+
679732
static void sdio_read_task(void const* pvParameters)
680733
{
681734
esp_err_t res;
@@ -843,11 +896,20 @@ static void sdio_read_task(void const* pvParameters)
843896
sdio_rx_byte_count += len_from_slave;
844897
sdio_rx_byte_count = sdio_rx_byte_count % ESP_RX_BYTE_MAX;
845898

846-
if (ret)
899+
if (unlikely(ret))
847900
continue;
848901

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+
}
851913
}
852914
}
853915

@@ -984,6 +1046,18 @@ void transport_init_internal(void)
9841046
assert(sdio_handle);
9851047
}
9861048

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+
9871061
sdio_read_thread = g_h.funcs->_h_thread_create("sdio_read",
9881062
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, sdio_read_task, NULL);
9891063

0 commit comments

Comments
 (0)