mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-06-25 17:31:33 +02:00
feat(eppp): Add support for SDIO transport
This commit is contained in:
@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "eppp_link.c"
|
idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)
|
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)
|
||||||
|
@ -21,6 +21,13 @@ menu "eppp_link"
|
|||||||
bool "SPI"
|
bool "SPI"
|
||||||
help
|
help
|
||||||
Use SPI.
|
Use SPI.
|
||||||
|
|
||||||
|
config EPPP_LINK_DEVICE_SDIO
|
||||||
|
bool "SDIO"
|
||||||
|
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
|
||||||
|
help
|
||||||
|
Use SDIO.
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config EPPP_LINK_CONN_MAX_RETRY
|
config EPPP_LINK_CONN_MAX_RETRY
|
||||||
@ -34,8 +41,30 @@ menu "eppp_link"
|
|||||||
config EPPP_LINK_PACKET_QUEUE_SIZE
|
config EPPP_LINK_PACKET_QUEUE_SIZE
|
||||||
int "Packet queue size"
|
int "Packet queue size"
|
||||||
default 64
|
default 64
|
||||||
|
depends on EPPP_LINK_DEVICE_SPI
|
||||||
help
|
help
|
||||||
Size of the Tx packet queue.
|
Size of the Tx packet queue.
|
||||||
You can decrease the number for slower bit rates.
|
You can decrease the number for slower bit rates.
|
||||||
|
|
||||||
|
choice EPPP_LINK_SDIO_ROLE
|
||||||
|
prompt "Choose SDIO host or slave"
|
||||||
|
depends on EPPP_LINK_DEVICE_SDIO
|
||||||
|
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
|
||||||
|
help
|
||||||
|
Select which either SDIO host or slave
|
||||||
|
|
||||||
|
config EPPP_LINK_DEVICE_SDIO_HOST
|
||||||
|
bool "Host"
|
||||||
|
depends on SOC_SDMMC_HOST_SUPPORTED
|
||||||
|
help
|
||||||
|
Use SDIO host.
|
||||||
|
|
||||||
|
config EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||||
|
bool "SLAVE"
|
||||||
|
depends on SOC_SDIO_SLAVE_SUPPORTED
|
||||||
|
help
|
||||||
|
Use SDIO slave.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -14,7 +14,7 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
|||||||
SLAVE micro HOST micro
|
SLAVE micro HOST micro
|
||||||
\|/ +----------------+ +----------------+
|
\|/ +----------------+ +----------------+
|
||||||
| | | serial line | |
|
| | | serial line | |
|
||||||
+---+ WiFi NAT PPPoS |======== UART / SPI =======| PPPoS client |
|
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
|
||||||
| (server)| | |
|
| (server)| | |
|
||||||
+----------------+ +----------------+
|
+----------------+ +----------------+
|
||||||
```
|
```
|
||||||
@ -39,14 +39,19 @@ brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
|||||||
|
|
||||||
## Throughput
|
## Throughput
|
||||||
|
|
||||||
Tested with WiFi-NAPT example, no IRAM optimizations
|
Tested with WiFi-NAPT example
|
||||||
|
|
||||||
### UART @ 3Mbauds
|
### UART @ 3Mbauds
|
||||||
|
|
||||||
* TCP - 2Mbits/s
|
* TCP - 2Mbits/s
|
||||||
* UDP - 2Mbits/s
|
* UDP - 2Mbits/s
|
||||||
|
|
||||||
### SPI @ 20MHz
|
### SPI @ 16MHz
|
||||||
|
|
||||||
* TCP - 6Mbits/s
|
* TCP - 5Mbits/s
|
||||||
* UDP - 10Mbits/s
|
* UDP - 8Mbits/s
|
||||||
|
|
||||||
|
### SDIO
|
||||||
|
|
||||||
|
* TCP - 9Mbits/s
|
||||||
|
* UDP - 11Mbits/s
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_netif_ppp.h"
|
#include "esp_netif_ppp.h"
|
||||||
#include "eppp_link.h"
|
#include "eppp_link.h"
|
||||||
|
#include "esp_serial_slave_link/essl_sdio.h"
|
||||||
|
|
||||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||||
#include "driver/spi_master.h"
|
#include "driver/spi_master.h"
|
||||||
@ -86,7 +87,18 @@ struct eppp_handle {
|
|||||||
bool netif_stop;
|
bool netif_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
|
||||||
|
|
||||||
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
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(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)
|
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||||
{
|
{
|
||||||
struct eppp_handle *handle = h;
|
struct eppp_handle *handle = h;
|
||||||
@ -125,9 +137,10 @@ static esp_err_t transmit(void *h, void *buffer, size_t len)
|
|||||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
|
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
|
||||||
uart_write_bytes(handle->uart_port, buffer, len);
|
uart_write_bytes(handle->uart_port, buffer, len);
|
||||||
#endif
|
#endif // DEVICE UART or SPI
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void netif_deinit(esp_netif_t *netif)
|
static void netif_deinit(esp_netif_t *netif)
|
||||||
{
|
{
|
||||||
@ -209,7 +222,11 @@ static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
|
|||||||
|
|
||||||
esp_netif_driver_ifconfig_t driver_cfg = {
|
esp_netif_driver_ifconfig_t driver_cfg = {
|
||||||
.handle = h,
|
.handle = h,
|
||||||
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
||||||
|
#else
|
||||||
.transmit = transmit,
|
.transmit = transmit,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
|
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
|
||||||
|
|
||||||
@ -657,6 +674,20 @@ esp_err_t eppp_perform(esp_netif_t *netif)
|
|||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
|
||||||
|
esp_err_t eppp_perform(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||||
|
if (h->stop) {
|
||||||
|
return ESP_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
if (h->role == EPPP_SERVER) {
|
||||||
|
return eppp_sdio_slave_rx(netif);
|
||||||
|
} else {
|
||||||
|
return eppp_sdio_host_rx(netif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
||||||
|
|
||||||
@ -700,6 +731,13 @@ void eppp_deinit(esp_netif_t *netif)
|
|||||||
}
|
}
|
||||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||||
deinit_uart(esp_netif_get_io_driver(netif));
|
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
|
#endif
|
||||||
netif_deinit(netif);
|
netif_deinit(netif);
|
||||||
}
|
}
|
||||||
@ -714,7 +752,6 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
|
|||||||
esp_netif_t *netif = netif_init(role, config);
|
esp_netif_t *netif = netif_init(role, config);
|
||||||
if (!netif) {
|
if (!netif) {
|
||||||
ESP_LOGE(TAG, "Failed to initialize PPP netif");
|
ESP_LOGE(TAG, "Failed to initialize PPP netif");
|
||||||
remove_handlers();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
esp_netif_ppp_config_t netif_params;
|
esp_netif_ppp_config_t netif_params;
|
||||||
@ -732,6 +769,18 @@ esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
|
|||||||
}
|
}
|
||||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||||
init_uart(esp_netif_get_io_driver(netif), config);
|
init_uart(esp_netif_get_io_driver(netif), config);
|
||||||
|
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
esp_err_t ret;
|
||||||
|
if (role == EPPP_SERVER) {
|
||||||
|
ret = eppp_sdio_slave_init();
|
||||||
|
} else {
|
||||||
|
ret = eppp_sdio_host_init(&config->sdio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return netif;
|
return netif;
|
||||||
}
|
}
|
||||||
@ -754,6 +803,12 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
if (config->transport != EPPP_TRANSPORT_SDIO) {
|
||||||
|
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (config->task.run_task == false) {
|
if (config->task.run_task == false) {
|
||||||
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
|
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
|
||||||
|
18
components/eppp_link/eppp_sdio.h
Normal file
18
components/eppp_link/eppp_sdio.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define MAX_SDIO_PAYLOAD 1500
|
||||||
|
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||||
|
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
|
||||||
|
|
||||||
|
// 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
|
195
components/eppp_link/eppp_sdio_host.c
Normal file
195
components/eppp_link/eppp_sdio_host.c
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "driver/sdio_slave.h"
|
||||||
|
#include "esp_serial_slave_link/essl_sdio.h"
|
||||||
|
#include "eppp_sdio.h"
|
||||||
|
#include "driver/sdmmc_host.h"
|
||||||
|
#include "sdmmc_cmd.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "eppp_link.h"
|
||||||
|
|
||||||
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
|
||||||
|
|
||||||
|
// 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_PAYLOAD];
|
||||||
|
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||||
|
{
|
||||||
|
if (s_essl == NULL || s_essl_mutex == NULL) {
|
||||||
|
// silently skip the Tx if the SDIO not fully initialized
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(send_buffer, buffer, len);
|
||||||
|
size_t send_len = SDIO_ALIGN(len);
|
||||||
|
if (send_len > len) {
|
||||||
|
// pad with SOF's
|
||||||
|
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, 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
|
||||||
|
}
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
|
||||||
|
xSemaphoreGive(s_essl_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t request_slave_reset(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
ESP_LOGI(TAG, "send reset to slave...");
|
||||||
|
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");
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");
|
||||||
|
|
||||||
|
// configure SDIO interface and slot
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 = s_card,
|
||||||
|
.recv_buffer_size = SDIO_PAYLOAD,
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
|
||||||
|
err:
|
||||||
|
essl_sdio_deinit_dev(s_essl);
|
||||||
|
s_essl = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t get_intr(uint32_t *out_raw)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
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);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
uint32_t intr;
|
||||||
|
esp_err_t err = get_intr(&intr);
|
||||||
|
if (err == ESP_ERR_TIMEOUT) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
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 = 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;
|
||||||
|
} else if (ret == ESP_OK) {
|
||||||
|
ESP_LOGD(TAG, "receive data, size: %d", size_read);
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
|
||||||
|
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "rx packet error: %08X", ret);
|
||||||
|
if (request_slave_reset() != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to request slave reset %x", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (ret == ESP_ERR_NOT_FINISHED);
|
||||||
|
xSemaphoreGive(s_essl_mutex);
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
175
components/eppp_link/eppp_sdio_slave.c
Normal file
175
components/eppp_link/eppp_sdio_slave.c
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "driver/sdio_slave.h"
|
||||||
|
#include "eppp_sdio.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
|
||||||
|
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAV
|
||||||
|
#define BUFFER_NUM 4
|
||||||
|
|
||||||
|
static const char *TAG = "eppp_sdio_slave";
|
||||||
|
static WORD_ALIGNED_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][SDIO_PAYLOAD];
|
||||||
|
static WORD_ALIGNED_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
|
||||||
|
static int s_slave_request = 0;
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||||
|
{
|
||||||
|
if (s_slave_request != REQ_INIT) {
|
||||||
|
// silently skip the Tx if the SDIO not fully initialized
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
memcpy(sdio_slave_tx_buffer, buffer, len);
|
||||||
|
size_t send_len = SDIO_ALIGN(len);
|
||||||
|
if (send_len > len) {
|
||||||
|
// pad with SOF's if the size is not 4 bytes aligned
|
||||||
|
memset(&sdio_slave_tx_buffer[len], 0x7E, send_len - len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
|
||||||
|
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "sdio slave transmit error, ret : 0x%x", ret);
|
||||||
|
// to inform the upper layers
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t slave_reset(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
ESP_LOGI(TAG, "SDIO slave reset");
|
||||||
|
sdio_slave_stop();
|
||||||
|
ESP_GOTO_ON_ERROR(sdio_slave_reset(), err, TAG, "slave reset failed");
|
||||||
|
ESP_GOTO_ON_ERROR(sdio_slave_start(), err, TAG, "slave start failed");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sdio_slave_buf_handle_t handle;
|
||||||
|
ret = sdio_slave_send_get_finished(&handle, 0);
|
||||||
|
if (ret == ESP_ERR_TIMEOUT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_GOTO_ON_ERROR(ret, err, TAG, "slave-get-finished failed");
|
||||||
|
ESP_GOTO_ON_ERROR(sdio_slave_recv_load_buf(handle), err, TAG, "slave-load-buf failed");
|
||||||
|
}
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
if (s_slave_request == REQ_RESET) {
|
||||||
|
ESP_LOGD(TAG, "request: %x", s_slave_request);
|
||||||
|
slave_reset();
|
||||||
|
s_slave_request = REQ_INIT;
|
||||||
|
}
|
||||||
|
sdio_slave_buf_handle_t handle;
|
||||||
|
size_t length;
|
||||||
|
uint8_t *ptr;
|
||||||
|
esp_err_t ret = sdio_slave_recv_packet(&handle, pdMS_TO_TICKS(1000));
|
||||||
|
if (ret == ESP_ERR_TIMEOUT) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||||
|
again:
|
||||||
|
ptr = sdio_slave_recv_get_buf(handle, &length);
|
||||||
|
esp_netif_receive(netif, ptr, length, NULL);
|
||||||
|
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to recycle packet buffer");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
if (ret == ESP_ERR_NOT_FINISHED) {
|
||||||
|
ret = sdio_slave_recv_packet(&handle, 0);
|
||||||
|
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
ESP_LOGE(TAG, "Error when receiving packet %d", ret);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void event_cb(uint8_t pos)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGI(TAG, "SDIO event: %d", pos);
|
||||||
|
if (pos == SLAVE_INTR) {
|
||||||
|
s_slave_request = sdio_slave_read_reg(SLAVE_REG_REQ);
|
||||||
|
sdio_slave_write_reg(SLAVE_REG_REQ, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_slave_init(void)
|
||||||
|
{
|
||||||
|
sdio_slave_config_t config = {
|
||||||
|
.sending_mode = SDIO_SLAVE_SEND_PACKET,
|
||||||
|
.send_queue_size = BUFFER_NUM,
|
||||||
|
.recv_buffer_size = SDIO_PAYLOAD,
|
||||||
|
.event_cb = event_cb,
|
||||||
|
.flags = SDIO_SLAVE_FLAG_HIGH_SPEED,
|
||||||
|
.timing = SDIO_SLAVE_TIMING_NSEND_PSAMPLE,
|
||||||
|
};
|
||||||
|
esp_err_t ret = sdio_slave_initialize(&config);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < BUFFER_NUM; i++) {
|
||||||
|
sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(sdio_slave_rx_buffer[i]);
|
||||||
|
if (handle == NULL) {
|
||||||
|
sdio_slave_deinit();
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
ret = sdio_slave_recv_load_buf(handle);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
sdio_slave_deinit();
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET); // only need one interrupt to notify of a new packet
|
||||||
|
|
||||||
|
ret = sdio_slave_start();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
sdio_slave_deinit();
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eppp_sdio_slave_deinit(void)
|
||||||
|
{
|
||||||
|
sdio_slave_stop();
|
||||||
|
sdio_slave_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // SOC_SDIO_SLAVE NOT-SUPPORTED
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||||
|
{
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||||
|
{
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eppp_sdio_slave_deinit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t eppp_sdio_slave_init(void)
|
||||||
|
{
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
@ -104,11 +104,13 @@ void app_main(void)
|
|||||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||||
config.transport = EPPP_TRANSPORT_SPI;
|
config.transport = EPPP_TRANSPORT_SPI;
|
||||||
#else
|
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||||
config.transport = EPPP_TRANSPORT_UART;
|
config.transport = EPPP_TRANSPORT_UART;
|
||||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||||
|
#else
|
||||||
|
config.transport = EPPP_TRANSPORT_SDIO;
|
||||||
#endif
|
#endif
|
||||||
esp_netif_t *eppp_netif = eppp_connect(&config);
|
esp_netif_t *eppp_netif = eppp_connect(&config);
|
||||||
if (eppp_netif == NULL) {
|
if (eppp_netif == NULL) {
|
||||||
|
@ -128,16 +128,21 @@ void app_main(void)
|
|||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
|
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
|
||||||
|
// ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
// ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||||
config.transport = EPPP_TRANSPORT_SPI;
|
config.transport = EPPP_TRANSPORT_SPI;
|
||||||
#else
|
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||||
config.transport = EPPP_TRANSPORT_UART;
|
config.transport = EPPP_TRANSPORT_UART;
|
||||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||||
#endif
|
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||||
|
config.transport = EPPP_TRANSPORT_SDIO;
|
||||||
|
#endif // transport device
|
||||||
|
|
||||||
esp_netif_t *eppp_netif = eppp_listen(&config);
|
esp_netif_t *eppp_netif = eppp_listen(&config);
|
||||||
if (eppp_netif == NULL) {
|
if (eppp_netif == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to setup connection");
|
ESP_LOGE(TAG, "Failed to setup connection");
|
||||||
|
@ -2,5 +2,5 @@ version: 0.1.1
|
|||||||
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
|
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
|
||||||
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
|
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
|
||||||
dependencies:
|
dependencies:
|
||||||
idf:
|
idf: '>=5.2'
|
||||||
version: '>=5.2'
|
espressif/esp_serial_slave_link: "^1.1.0"
|
||||||
|
@ -28,7 +28,16 @@
|
|||||||
.rx_io = 26, \
|
.rx_io = 26, \
|
||||||
.queue_size = 16, \
|
.queue_size = 16, \
|
||||||
.rx_buffer_size = 1024, \
|
.rx_buffer_size = 1024, \
|
||||||
}, \
|
}, \
|
||||||
|
.sdio = { \
|
||||||
|
.width = 4, \
|
||||||
|
.clk = 18, \
|
||||||
|
.cmd = 19, \
|
||||||
|
.d0 = 49, \
|
||||||
|
.d1 = 50, \
|
||||||
|
.d2 = 16, \
|
||||||
|
.d3 = 17, \
|
||||||
|
}, \
|
||||||
. task = { \
|
. task = { \
|
||||||
.run_task = true, \
|
.run_task = true, \
|
||||||
.stack_size = 4096, \
|
.stack_size = 4096, \
|
||||||
@ -53,6 +62,7 @@ typedef enum eppp_type {
|
|||||||
typedef enum eppp_transport {
|
typedef enum eppp_transport {
|
||||||
EPPP_TRANSPORT_UART,
|
EPPP_TRANSPORT_UART,
|
||||||
EPPP_TRANSPORT_SPI,
|
EPPP_TRANSPORT_SPI,
|
||||||
|
EPPP_TRANSPORT_SDIO,
|
||||||
} eppp_transport_t;
|
} eppp_transport_t;
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +91,16 @@ typedef struct eppp_config_t {
|
|||||||
int rx_buffer_size;
|
int rx_buffer_size;
|
||||||
} uart;
|
} uart;
|
||||||
|
|
||||||
|
struct eppp_config_sdio_s {
|
||||||
|
int width;
|
||||||
|
int clk;
|
||||||
|
int cmd;
|
||||||
|
int d0;
|
||||||
|
int d1;
|
||||||
|
int d2;
|
||||||
|
int d3;
|
||||||
|
} sdio;
|
||||||
|
|
||||||
struct eppp_config_task_s {
|
struct eppp_config_task_s {
|
||||||
bool run_task;
|
bool run_task;
|
||||||
int stack_size;
|
int stack_size;
|
||||||
|
Reference in New Issue
Block a user