Skip to content

Commit

Permalink
fix(eppp): Some optional fixes to SDIO
Browse files Browse the repository at this point in the history
  • Loading branch information
david-cermak committed Feb 28, 2024
1 parent 412bb26 commit 566a471
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 143 deletions.
15 changes: 10 additions & 5 deletions components/eppp_link/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
SLAVE micro HOST micro
\|/ +----------------+ +----------------+
| | | serial line | |
+---+ WiFi NAT PPPoS |======== UART / SPI =======| PPPoS client |
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
| (server)| | |
+----------------+ +----------------+
```
Expand All @@ -39,14 +39,19 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.

## Throughput

Tested with WiFi-NAPT example, no IRAM optimizations
Tested with WiFi-NAPT example

### UART @ 3Mbauds

* TCP - 2Mbits/s
* UDP - 2Mbits/s

### SPI @ 20MHz
### SPI @ 16MHz

* TCP - 6Mbits/s
* UDP - 10Mbits/s
* TCP - 5Mbits/s
* UDP - 8Mbits/s

### SDIO

* TCP - 9Mbits/s
* UDP - 11Mbits/s
14 changes: 11 additions & 3 deletions components/eppp_link/eppp_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
esp_err_t eppp_sdio_host_init(void);
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
esp_err_t eppp_sdio_slave_init(void);
void eppp_sdio_slave_deinit(void);
void eppp_sdio_host_deinit(void);
#else
static esp_err_t transmit(void *h, void *buffer, size_t len)
{
Expand Down Expand Up @@ -726,6 +728,13 @@ void eppp_deinit(esp_netif_t *netif)
}
#elif CONFIG_EPPP_LINK_DEVICE_UART
deinit_uart(esp_netif_get_io_driver(netif));
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (h->role == EPPP_CLIENT) {
eppp_sdio_host_deinit();
} else {
eppp_sdio_slave_deinit();
}
#endif
netif_deinit(netif);
}
Expand Down Expand Up @@ -754,11 +763,10 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
init_uart(esp_netif_get_io_driver(netif), config);
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
esp_err_t ret;
struct eppp_handle *h = esp_netif_get_io_driver(netif);
if (role == EPPP_SERVER) {
ret = eppp_sdio_slave_init();
} else {
ret = eppp_sdio_host_init();
ret = eppp_sdio_host_init(&config->sdio);
}

if (ret != ESP_OK) {
Expand Down
9 changes: 5 additions & 4 deletions components/eppp_link/eppp_sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
*/
#pragma once

#define MAX_PAYLOAD 1500
#define MAX_SDIO_PAYLOAD 1500
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_PAYLOAD)
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)


#define SLAVE_INTR 0
// Interrupts and registers
#define SLAVE_INTR 0
#define SLAVE_REG_REQ 0

// Requests from host to slave
#define REQ_RESET 1
#define REQ_INIT 2
171 changes: 72 additions & 99 deletions components/eppp_link/eppp_sdio_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,24 @@
#include "eppp_sdio.h"
#include "driver/sdmmc_host.h"
#include "sdmmc_cmd.h"
#include "esp_check.h"
#include "eppp_link.h"

#if CONFIG_SOC_SDMMC_HOST_SUPPORTED

// For blocking operations
#define TIMEOUT_MAX UINT32_MAX

// Short timeout for sending/receiving ESSL packets
#define PACKET_TIMEOUT_MS 50
// Used for padding unaligned packets, to simplify the logic and keep PPP protocol intact when padded
#define PPP_SOF 0x7E
static const char *TAG = "eppp_sdio_host";
static SemaphoreHandle_t s_essl_mutex = NULL;
static essl_handle_t s_essl = NULL;
static sdmmc_card_t *s_card = NULL;

static CACHE_ALIGNED_ATTR uint8_t send_buffer[SDIO_ALIGN(MAX_PAYLOAD)];
static DMA_ATTR uint8_t rcv_buffer[SDIO_ALIGN(MAX_PAYLOAD)];
static CACHE_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];

esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
{
Expand All @@ -36,133 +43,87 @@ esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
size_t send_len = SDIO_ALIGN(len);
if (send_len > len) {
// pad with SOF's
memset(&send_buffer[len], 0x7E, send_len - len);
memset(&send_buffer[len], PPP_SOF, send_len - len);
}
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, 50);
if (ret == ESP_ERR_TIMEOUT || ret == ESP_ERR_NOT_FOUND) {
ESP_LOGW(TAG, "slave not ready to receive packet %x", ret);
xSemaphoreGive(s_essl_mutex);
return ESP_ERR_NO_MEM;
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Slave not ready to receive packet %x", ret);
vTaskDelay(pdMS_TO_TICKS(1000));
ret = ESP_ERR_NO_MEM; // to inform the upper layers
}
// vTaskDelay(pdMS_TO_TICKS(50));
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
xSemaphoreGive(s_essl_mutex);
return ESP_OK;
return ret;
}

static esp_err_t request_slave_reset(void)
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG, "send reset to slave...");
esp_err_t ret = essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX);
if (ret != ESP_OK) {
goto fail;
}
ret = essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX);
if (ret != ESP_OK) {
goto fail;
}

vTaskDelay(pdMS_TO_TICKS(500));
ret = essl_wait_for_ready(s_essl, TIMEOUT_MAX);
if (ret != ESP_OK) {
goto fail;
}
ESP_GOTO_ON_ERROR(essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX), err, TAG, "write-reg failed");
ESP_GOTO_ON_ERROR(essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX), err, TAG, "send-intr failed");
vTaskDelay(pdMS_TO_TICKS(PACKET_TIMEOUT_MS));
ESP_GOTO_ON_ERROR(essl_wait_for_ready(s_essl, TIMEOUT_MAX), err, TAG, "wait-for-ready failed");
ESP_LOGI(TAG, "slave io ready");
return ESP_OK;
fail:
return ESP_FAIL;
err:
return ret;
}

esp_err_t eppp_sdio_host_init(void)
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
{
esp_err_t res;

sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
esp_err_t ret = ESP_OK;

// initialise SDMMC host
res = sdmmc_host_init();
if (res != ESP_OK) {
return ESP_FAIL;
}
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");

// configure SDIO interface and slot
slot_config.width = 4;
slot_config.clk = 18;
slot_config.cmd = 19;
slot_config.d0 = 49;
slot_config.d1 = 50;
slot_config.d2 = 16;
slot_config.d3 = 17;

res = sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config);
if (res != ESP_OK) {
ESP_LOGE(TAG, "init SDMMC Host slot %d failed", SDMMC_HOST_SLOT_1);
return ESP_FAIL;
}
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = eppp_config->width;
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.clk = eppp_config->clk;
slot_config.cmd = eppp_config->cmd;
slot_config.d0 = eppp_config->d0;
slot_config.d1 = eppp_config->d1;
slot_config.d2 = eppp_config->d2;
slot_config.d3 = eppp_config->d3;
#endif

ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config), err, TAG, "init sdmmc host slot failed");

sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_4BIT;
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;

sdmmc_card_t *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
return ESP_ERR_NO_MEM;
}

if (sdmmc_card_init(&config, card) != ESP_OK) {
ESP_LOGE(TAG, "sdmmc_card_init failed");
goto fail;
}
s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, err, TAG, "card allocation failed");
ESP_GOTO_ON_ERROR(sdmmc_card_init(&config, s_card), err, TAG, "sdmmc card init failed");

essl_sdio_config_t ser_config = {
.card = card,
.card = s_card,
.recv_buffer_size = SDIO_PAYLOAD,
};
res = essl_sdio_init_dev(&s_essl, &ser_config);
if (res != ESP_OK || s_essl == NULL) {
ESP_LOGE(TAG, "essl_sdio_init_dev failed %d", res);
goto fail;
}
res = essl_init(s_essl, TIMEOUT_MAX);
if (res != ESP_OK) {
ESP_LOGE(TAG, "essl_init failed %d", res);
goto fail;
}
ESP_GOTO_ON_FALSE(essl_sdio_init_dev(&s_essl, &ser_config) == ESP_OK && s_essl, ESP_FAIL, err, TAG, "essl_sdio_init_dev failed");
ESP_GOTO_ON_ERROR(essl_init(s_essl, TIMEOUT_MAX), err, TAG, "essl-init failed");
ESP_GOTO_ON_ERROR(request_slave_reset(), err, TAG, "failed to reset the slave");
ESP_GOTO_ON_FALSE((s_essl_mutex = xSemaphoreCreateMutex()), ESP_ERR_NO_MEM, err, TAG, "failed to create semaphore");
return ret;

if (request_slave_reset() != ESP_OK) {
ESP_LOGE(TAG, "failed to reset the slave");
goto fail;
}
s_essl_mutex = xSemaphoreCreateMutex();
if (s_essl_mutex == NULL) {
ESP_LOGE(TAG, "failed to create semaphore");
goto fail;
}
return ESP_OK;

fail:
err:
essl_sdio_deinit_dev(s_essl);
s_essl = NULL;
return ESP_FAIL;
return ret;
}

static esp_err_t get_intr(uint32_t *out_raw)
{
esp_err_t ret = ESP_OK;
ret = essl_wait_int(s_essl, TIMEOUT_MAX);
if (ret != ESP_OK) {
return ret;
}
ret = essl_get_intr(s_essl, out_raw, NULL, TIMEOUT_MAX);
if (ret != ESP_OK) {
return ret;
}
ret = essl_clear_intr(s_essl, *out_raw, TIMEOUT_MAX);
if (ret != ESP_OK) {
return ret;
}
ESP_GOTO_ON_ERROR(essl_wait_int(s_essl, TIMEOUT_MAX), err, TAG, "essl-wait-int failed");
ESP_GOTO_ON_ERROR(essl_get_intr(s_essl, out_raw, NULL, TIMEOUT_MAX), err, TAG, "essl-get-int failed");
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, TIMEOUT_MAX), err, TAG, "essl-clear-int failed");
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
return ESP_OK;
err:
return ret;
}

esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
Expand All @@ -173,16 +134,15 @@ esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
return ESP_OK;
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "failed to read interrupt register");
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
return ESP_FAIL;
}
const int wait_ms = 50;
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
esp_err_t ret;
do {
size_t size_read = MAX_PAYLOAD;
ret = essl_get_packet(s_essl, rcv_buffer, MAX_PAYLOAD, &size_read, wait_ms);
size_t size_read = SDIO_PAYLOAD;
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "interrupt but no data can be read");
break;
Expand All @@ -204,6 +164,15 @@ esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
return ESP_OK;
}

void eppp_sdio_host_deinit()
{
essl_sdio_deinit_dev(s_essl);
sdmmc_host_deinit();
free(s_card);
s_card = NULL;
s_essl = NULL;
}

#else // SDMMC_HOST NOT-SUPPORTED

esp_err_t eppp_sdio_host_tx(void *handle, void *buffer, size_t len)
Expand All @@ -216,6 +185,10 @@ esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
return ESP_ERR_NOT_SUPPORTED;
}

void eppp_sdio_host_deinit()
{
}

esp_err_t eppp_sdio_host_init()
{
return ESP_ERR_NOT_SUPPORTED;
Expand Down
Loading

0 comments on commit 566a471

Please sign in to comment.