Skip to content

Commit

Permalink
Merge branch 'bugfix/sdio_esp_as_mcu_host' into 'feature/esp_as_mcu_h…
Browse files Browse the repository at this point in the history
…ost'

bugfix/sdio_esp_as_mcu_host

See merge request app-frameworks/esp_hosted!356
  • Loading branch information
mantriyogesh committed Nov 15, 2023
2 parents 89aee43 + 9165070 commit 7dc0055
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 81 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ else()
endif()

idf_component_register(SRCS ${COMPONENT_SRCS}
REQUIRES soc esp_event esp_netif esp_timer driver esp_wifi esp_wifi_remote
REQUIRES soc esp_event esp_netif esp_timer driver esp_wifi esp_wifi_remote sdmmc
EXCLUDE_SRCS ${EXCLUDE_COMPONENT_SRCS}
INCLUDE_DIRS ${COMPONENT_ADD_INCLUDEDIRS})

Expand Down
45 changes: 45 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,51 @@ ESP32S3_SDIO_CLK_FREQ_KHZ_RANGE_MAX := 80000
help
"Optimize SDIO CLK by increasing till host practically can support"

config ESP_SDIO_PIN_CMD
int "CMD GPIO number"
default 35 if IDF_TARGET_ESP32S3
range 15 15 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

config ESP_SDIO_PIN_CLK
int "CLK GPIO number"
default 36 if IDF_TARGET_ESP32S3
range 14 14 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

config ESP_SDIO_PIN_D0
int "D0 GPIO number"
default 37 if IDF_TARGET_ESP32S3
range 2 2 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

config ESP_SDIO_PIN_D1
int "D1 GPIO number"
default 38 if IDF_TARGET_ESP32S3
range 4 4 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

if ESP_SDIO_4_BIT_BUS
config ESP_SDIO_PIN_D2
int "D2 GPIO number"
default 33 if IDF_TARGET_ESP32S3
range 12 12 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

config ESP_SDIO_PIN_D3
int "D3 GPIO number"
default 34 if IDF_TARGET_ESP32S3
range 13 13 if IDF_TARGET_ESP32
help
"Value can only be configured for some targets. Displayed always for reference."

endif

config ESP_SDIO_TX_Q_SIZE
int "Host SDIO Tx queue size"
default 20
Expand Down
158 changes: 111 additions & 47 deletions host/drivers/transport/sdio/sdio_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,39 @@ static const char TAG[] = "H_SDIO_DRV";
// max number of times to try to write data to slave device
#define MAX_WRITE_RETRIES 2

// this locks the sdio transaction at the driver level, instead of at the HAL layer
#define USE_DRIVER_LOCK

#if defined(USE_DRIVER_LOCK)
#define ACQUIRE_LOCK false
#else
#define ACQUIRE_LOCK true
#endif

#if CONFIG_SLAVE_CHIPSET_ESP32
#define NEW_PACKET_INTR (1 << 23)
#elif CONFIG_SLAVE_CHIPSET_ESP32C6
#define NEW_PACKET_INTR (1 << 23)
#else
#error SDIO New Packet Intr Bit not defined for Hosted Slave
#endif

#if defined(USE_DRIVER_LOCK)
static void * sdio_bus_lock;

#define SDIO_DRV_LOCK() g_h.funcs->_h_lock_mutex(sdio_bus_lock, portMAX_DELAY);
#define SDIO_DRV_UNLOCK() g_h.funcs->_h_unlock_mutex(sdio_bus_lock);

#define REUSE_NW_MEMPOOL 1
#else
#define SDIO_DRV_LOCK()
#define SDIO_DRV_UNLOCK()
#endif

#if !REUSE_NW_MEMPOOL
/* Create mempool for cache mallocs */
static struct mempool * buf_mp_g;
#endif

/* TODO to move this in transport drv */
extern transport_channel_t *chan_arr[ESP_MAX_IF];

static void * sdio_handle = NULL;
static void * sdio_bus_lock;
Expand Down Expand Up @@ -79,40 +104,31 @@ static void (*sdio_drv_evt_handler_fp) (uint8_t) = NULL;

static inline void sdio_mempool_create()
{
#if !REUSE_NW_MEMPOOL
MEM_DUMP("sdio_mempool_create");
buf_mp_g = mempool_create(MAX_SDIO_BUFFER_SIZE);
#ifdef CONFIG_ESP_CACHE_MALLOC
assert(buf_mp_g);
#endif
#else

#endif
}

static inline void sdio_mempool_destroy()
{
#if !REUSE_NW_MEMPOOL
mempool_destroy(buf_mp_g);
#endif
}

static inline void *sdio_buffer_alloc(uint need_memset)
{
#if !REUSE_NW_MEMPOOL
return mempool_alloc(buf_mp_g, MAX_SDIO_BUFFER_SIZE, need_memset);
#else
return mempool_alloc(nw_mp_g, MAX_SDIO_BUFFER_SIZE, need_memset);
#endif
}

static inline void sdio_buffer_free(void *buf)
{
#if !REUSE_NW_MEMPOOL
mempool_free(buf_mp_g, buf);
#else
mempool_free(nw_mp_g, buf);
#endif
}

void transport_deinit_internal(void)
{
/* TODO */
}

static int sdio_generate_slave_intr(uint8_t intr_no)
Expand Down Expand Up @@ -266,8 +282,14 @@ static void sdio_write_task(void const* pvParameters)
if (!len)
continue;

sendbuf = sdio_buffer_alloc(MEMSET_REQUIRED);
free_func = sdio_buffer_free;
if (!buf_handle.payload_zcopy) {
sendbuf = sdio_buffer_alloc(MEMSET_REQUIRED);
assert(sendbuf);
free_func = sdio_buffer_free;
} else {
sendbuf = buf_handle.payload;
free_func = buf_handle.free_buf_handle;
}

if (!sendbuf) {
ESP_LOGE(TAG, "sdio buff malloc failed");
Expand All @@ -292,7 +314,8 @@ static void sdio_write_task(void const* pvParameters)
payload_header->seq_num = htole16(buf_handle.seq_num);
payload_header->flags = buf_handle.flag;

g_h.funcs->_h_memcpy(payload, buf_handle.payload, len);
if (!buf_handle.payload_zcopy)
g_h.funcs->_h_memcpy(payload, buf_handle.payload, len);

#if CONFIG_ESP_SDIO_CHECKSUM
payload_header->checksum = htole16(compute_checksum(sendbuf,
Expand All @@ -302,6 +325,8 @@ static void sdio_write_task(void const* pvParameters)
buf_needed = (len + sizeof(struct esp_payload_header) + ESP_RX_BUFFER_SIZE - 1)
/ ESP_RX_BUFFER_SIZE;

SDIO_DRV_LOCK();

ret = sdio_is_write_buffer_available(buf_needed);
if (ret != BUFFER_AVAILABLE) {
ESP_LOGE(TAG, "no SDIO write buffers on slave device");
Expand All @@ -317,7 +342,7 @@ static void sdio_write_task(void const* pvParameters)
len_to_send = data_left;

ret = g_h.funcs->_h_sdio_write_block(ESP_SLAVE_CMD53_END_ADDR - data_left,
pos, (len_to_send + 3) & (~3), ACQUIRE_LOCK);
pos, len_to_send, ACQUIRE_LOCK);
if (ret) {
ESP_LOGE(TAG, "%s: %d: Failed to send data: %d %ld %ld", __func__,
retries, ret, len_to_send, data_left);
Expand All @@ -340,8 +365,12 @@ static void sdio_write_task(void const* pvParameters)
sdio_tx_buf_count = sdio_tx_buf_count % ESP_TX_BUFFER_MAX;

done:
H_FREE_PTR_WITH_FUNC(buf_handle.free_buf_handle, buf_handle.priv_buffer_handle);
SDIO_DRV_UNLOCK();

if (len && !buf_handle.payload_zcopy) {
/* free allocated buffer, only if zerocopy is not requested */
H_FREE_PTR_WITH_FUNC(buf_handle.free_buf_handle, buf_handle.priv_buffer_handle);
}
H_FREE_PTR_WITH_FUNC(free_func, sendbuf);
}
}
Expand All @@ -364,6 +393,27 @@ static void sdio_read_task(void const* pvParameters)
uint8_t *pos;
uint32_t interrupts;

assert(sdio_handle);

// wait for transport to be in reset state
while (true) {
if (is_transport_in_reset()) {
ESP_LOGI(TAG, "transport has been reset");
break;
}
vTaskDelay(pdMS_TO_TICKS(100));
}

res = g_h.funcs->_h_sdio_card_init(sdio_handle);
if (res != ESP_OK) {
ESP_LOGE(TAG, "sdio card init failed");
return;
}
ESP_LOGI(TAG, "generate slave intr");

// inform the slave device that we are ready
sdio_generate_slave_intr(ESP_OPEN_DATA_PATH);

for (;;) {
// wait for sdio interrupt from slave
// call will block until there is an interrupt, timeout or error
Expand All @@ -374,13 +424,30 @@ static void sdio_read_task(void const* pvParameters)
continue;
}

SDIO_DRV_LOCK();

// clear slave interrupts
sdio_get_intr(&interrupts);
if (sdio_get_intr(&interrupts)) {
ESP_LOGE(TAG, "failed to read interrupt register");

SDIO_DRV_UNLOCK();
continue;
}
sdio_clear_intr(interrupts);

if (!(NEW_PACKET_INTR & interrupts)) {
// interrupt is not for a new packet
ESP_LOGD(TAG, "Slave intr is not for 'new packet'");

SDIO_DRV_UNLOCK();
continue;
}

ret = sdio_get_len_from_slave(&len_from_slave, ACQUIRE_LOCK);
if (ret || !len_from_slave) {
ESP_LOGD(TAG, "invalid ret or len_from_slave: %d %ld", ret, len_from_slave);

SDIO_DRV_UNLOCK();
continue;
}

Expand All @@ -396,19 +463,23 @@ static void sdio_read_task(void const* pvParameters)

ret = g_h.funcs->_h_sdio_read_block(
ESP_SLAVE_CMD53_END_ADDR - data_left,
pos, (len_to_read + 3) & (~3), ACQUIRE_LOCK);
pos, len_to_read, ACQUIRE_LOCK);
if (ret) {
ESP_LOGE(TAG, "%s: Failed to read data - %d %ld %ld",
__func__, ret, len_to_read, data_left);
HOSTED_FREE(rxbuff);
SDIO_DRV_UNLOCK();
continue;
}
data_left -= len_to_read;
pos += len_to_read;
sdio_rx_byte_count += len_to_read;
sdio_rx_byte_count = sdio_rx_byte_count % ESP_RX_BYTE_MAX;
} while (data_left);

SDIO_DRV_UNLOCK();

sdio_rx_byte_count += len_from_slave;
sdio_rx_byte_count = sdio_rx_byte_count % ESP_RX_BYTE_MAX;

/* create buffer rx handle, used for processing */
payload_header = (struct esp_payload_header *)rxbuff;

Expand Down Expand Up @@ -464,8 +535,6 @@ static void sdio_read_task(void const* pvParameters)
*/
static void sdio_process_rx_task(void const* pvParameters)
{
uint32_t netif_interface_type = 0;

interface_buffer_handle_t buf_handle_l = {0};
interface_buffer_handle_t *buf_handle = NULL;

Expand All @@ -479,8 +548,6 @@ static void sdio_process_rx_task(void const* pvParameters)
continue;
}
buf_handle = &buf_handle_l;
/* Translate Hosted interface type to netif interface type */
netif_interface_type = buf_handle->if_type - 1;

ESP_LOG_BUFFER_HEXDUMP(TAG, buf_handle->payload, buf_handle->payload_len, ESP_LOG_DEBUG);

Expand All @@ -489,16 +556,12 @@ static void sdio_process_rx_task(void const* pvParameters)
serial_rx_handler(buf_handle);
} else if((buf_handle->if_type == ESP_STA_IF) ||
(buf_handle->if_type == ESP_AP_IF)) {
if (g_rxcb[netif_interface_type]) {
if (buf_handle->payload_zcopy)
g_rxcb[netif_interface_type](buf_handle->payload,
buf_handle->payload_len, buf_handle->priv_buffer_handle);
else
g_rxcb[netif_interface_type](buf_handle->payload,
buf_handle->payload_len, NULL);
if (chan_arr[buf_handle->if_type] && chan_arr[buf_handle->if_type]->rx) {
chan_arr[buf_handle->if_type]->rx(chan_arr[buf_handle->if_type]->api_chan,
buf_handle->payload, NULL, buf_handle->payload_len);
}
} else if (buf_handle->if_type == ESP_PRIV_IF) {
process_priv_communication(buf_handle->payload, buf_handle->payload_len);
process_priv_communication(buf_handle);
/* priv transaction received */
ESP_LOGI(TAG, "Received INIT event");
sdio_start_write_thread = true;
Expand Down Expand Up @@ -532,7 +595,7 @@ static void sdio_process_rx_task(void const* pvParameters)
}
}

void transport_init(void(*transport_evt_handler_fp)(uint8_t))
void transport_init_internal(void(*transport_evt_handler_fp)(uint8_t))
{
/* register callback */
sdio_drv_evt_handler_fp = transport_evt_handler_fp;
Expand Down Expand Up @@ -569,32 +632,33 @@ void transport_init(void(*transport_evt_handler_fp)(uint8_t))
sdio_write_thread = g_h.funcs->_h_thread_create("sdio_write",
DFLT_TASK_PRIO, DFLT_TASK_STACK_SIZE, sdio_write_task, NULL);

// inform the slave device that we are ready
sdio_generate_slave_intr(ESP_OPEN_DATA_PATH);
#if defined(USE_DRIVER_LOCK)
// initialise mutex for bus locking
sdio_bus_lock = g_h.funcs->_h_create_mutex();
assert(sdio_bus_lock);
#endif
}

int esp_hosted_tx(uint8_t iface_type, uint8_t iface_num,
uint8_t * wbuffer, uint16_t wlen, uint8_t buff_zerocopy,
uint8_t * wbuffer, uint16_t wlen, uint8_t buff_zcopy,
void (*free_wbuf_fun)(void* ptr))
{
interface_buffer_handle_t buf_handle = {0};
void (*free_func)(void* ptr) = NULL;
uint8_t transport_up = is_transport_up();

if (free_wbuf_fun)
free_func = free_wbuf_fun;
else
free_func = g_h.funcs->_h_free;

if (!wbuffer || !wlen ||
(wlen > (MAX_PAYLOAD_SIZE - sizeof(struct esp_payload_header)))) {
(wlen > (MAX_PAYLOAD_SIZE - sizeof(struct esp_payload_header)))
|| !transport_up) {
ESP_LOGE(TAG, "tx fail: NULL buff, invalid len (%u) or len > max len (%u))",
wlen, MAX_PAYLOAD_SIZE - sizeof(struct esp_payload_header));
H_FREE_PTR_WITH_FUNC(free_func, wbuffer);
return ESP_FAIL;
}
#if CONFIG_H_LOWER_MEMCOPY
buf_handle.payload_zcopy = buff_zcopy;
#endif
buf_handle.if_type = iface_type;
buf_handle.if_num = iface_num;
buf_handle.payload_len = wlen;
Expand Down
5 changes: 5 additions & 0 deletions host/drivers/transport/transport_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ uint8_t is_transport_ready(void)
return !(TRANSPORT_INACTIVE == transport_state);
}

uint8_t is_transport_in_reset(void)
{
return TRANSPORT_RESET == transport_state;
}

static void reset_slave(void)
{
ESP_LOGI(TAG, "Reset slave using GPIO[%u]", H_GPIO_PIN_RESET_Pin);
Expand Down
Loading

0 comments on commit 7dc0055

Please sign in to comment.