mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-04 06:06:45 +02:00
Compare commits
14 Commits
console_cm
...
eppp-v0.2.
Author | SHA1 | Date | |
---|---|---|---|
68da69e4d8 | |||
c6e2eb2dac | |||
a9dd78ffad | |||
eb09e42638 | |||
adafeae5cf | |||
d7eaa77b89 | |||
402176c9e0 | |||
085dd79079 | |||
a05fbc7ed9 | |||
ba35d14e43 | |||
2b64e80acd | |||
ac9972aa48 | |||
1c5a149b14 | |||
8d0152f612 |
2
.github/workflows/pre_commit_check.yml
vendored
2
.github/workflows/pre_commit_check.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: v3.7
|
||||
python-version: v3.8
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
|
@ -48,7 +48,7 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/igrr/astyle_py.git
|
||||
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
|
||||
rev: v1.0.5
|
||||
hooks:
|
||||
- id: astyle_py
|
||||
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--exclude-list=ci/ignore_astyle.txt']
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(eppp): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py eppp_link
|
||||
tag_format: eppp-v$version
|
||||
version: 0.1.1
|
||||
version: 0.2.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
|
||||
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
|
||||
|
||||
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
@ -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"
|
||||
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)
|
||||
|
@ -21,6 +21,13 @@ menu "eppp_link"
|
||||
bool "SPI"
|
||||
help
|
||||
Use SPI.
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO
|
||||
bool "SDIO"
|
||||
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
|
||||
help
|
||||
Use SDIO.
|
||||
|
||||
endchoice
|
||||
|
||||
config EPPP_LINK_CONN_MAX_RETRY
|
||||
@ -34,8 +41,30 @@ menu "eppp_link"
|
||||
config EPPP_LINK_PACKET_QUEUE_SIZE
|
||||
int "Packet queue size"
|
||||
default 64
|
||||
depends on EPPP_LINK_DEVICE_SPI
|
||||
help
|
||||
Size of the Tx packet queue.
|
||||
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
|
||||
|
@ -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)| | |
|
||||
+----------------+ +----------------+
|
||||
```
|
||||
@ -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
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif_ppp.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_serial_slave_link/essl_sdio.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
#include "driver/spi_master.h"
|
||||
@ -86,7 +87,18 @@ struct eppp_handle {
|
||||
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)
|
||||
{
|
||||
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
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
|
||||
uart_write_bytes(handle->uart_port, buffer, len);
|
||||
#endif
|
||||
#endif // DEVICE UART or SPI
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 = {
|
||||
.handle = h,
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
||||
#else
|
||||
.transmit = transmit,
|
||||
#endif
|
||||
};
|
||||
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;
|
||||
}
|
||||
#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
|
||||
|
||||
@ -700,6 +731,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);
|
||||
}
|
||||
@ -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);
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Failed to initialize PPP netif");
|
||||
remove_handlers();
|
||||
return NULL;
|
||||
}
|
||||
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
|
||||
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
|
||||
return netif;
|
||||
}
|
||||
@ -754,6 +803,12 @@ esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_time
|
||||
return NULL;
|
||||
}
|
||||
#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) {
|
||||
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
|
||||
|
19
components/eppp_link/eppp_sdio.h
Normal file
19
components/eppp_link/eppp_sdio.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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)
|
||||
#define PPP_SOF 0x7E
|
||||
|
||||
// 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
|
200
components/eppp_link/eppp_sdio_host.c
Normal file
200
components/eppp_link/eppp_sdio_host.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
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 DRAM_DMA_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.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
|
||||
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_get_intr(s_essl, out_raw, NULL, 0), err, TAG, "essl-get-int failed");
|
||||
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, 0), 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 = essl_wait_int(s_essl, TIMEOUT_MAX);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
return ESP_OK;
|
||||
}
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
err = get_intr(&intr);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
|
||||
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(void)
|
||||
{
|
||||
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(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
174
components/eppp_link/eppp_sdio_slave.c
Normal file
174
components/eppp_link/eppp_sdio_slave.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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_SLAVE
|
||||
#define BUFFER_NUM 4
|
||||
#define BUFFER_SIZE SDIO_PAYLOAD
|
||||
static const char *TAG = "eppp_sdio_slave";
|
||||
static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
|
||||
static DMA_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], PPP_SOF, 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;
|
||||
}
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, length, ESP_LOG_VERBOSE);
|
||||
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 = BUFFER_SIZE,
|
||||
.event_cb = event_cb,
|
||||
};
|
||||
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(void)
|
||||
{
|
||||
}
|
||||
|
||||
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();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#else
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||
#else
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
#endif
|
||||
esp_netif_t *eppp_netif = eppp_connect(&config);
|
||||
if (eppp_netif == NULL) {
|
||||
|
@ -128,16 +128,21 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
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();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#else
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
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);
|
||||
if (eppp_netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to setup connection");
|
||||
|
@ -1,6 +1,6 @@
|
||||
version: 0.1.1
|
||||
version: 0.2.0
|
||||
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
|
||||
dependencies:
|
||||
idf:
|
||||
version: '>=5.2'
|
||||
idf: '>=5.2'
|
||||
espressif/esp_serial_slave_link: "^1.1.0"
|
||||
|
@ -28,7 +28,16 @@
|
||||
.rx_io = 26, \
|
||||
.queue_size = 16, \
|
||||
.rx_buffer_size = 1024, \
|
||||
}, \
|
||||
}, \
|
||||
.sdio = { \
|
||||
.width = 4, \
|
||||
.clk = 18, \
|
||||
.cmd = 19, \
|
||||
.d0 = 49, \
|
||||
.d1 = 50, \
|
||||
.d2 = 16, \
|
||||
.d3 = 17, \
|
||||
}, \
|
||||
. task = { \
|
||||
.run_task = true, \
|
||||
.stack_size = 4096, \
|
||||
@ -53,6 +62,7 @@ typedef enum eppp_type {
|
||||
typedef enum eppp_transport {
|
||||
EPPP_TRANSPORT_UART,
|
||||
EPPP_TRANSPORT_SPI,
|
||||
EPPP_TRANSPORT_SDIO,
|
||||
} eppp_transport_t;
|
||||
|
||||
|
||||
@ -81,6 +91,16 @@ typedef struct eppp_config_t {
|
||||
int rx_buffer_size;
|
||||
} 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 {
|
||||
bool run_task;
|
||||
int stack_size;
|
||||
|
@ -16,9 +16,9 @@ class.
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
|
@ -10,7 +10,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -36,6 +36,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -160,6 +160,9 @@ extern "C" void app_main(void)
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
@ -180,7 +183,7 @@ extern "C" void app_main(void)
|
||||
});
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
|
||||
#else
|
||||
#error USB modem not selected
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -11,9 +11,9 @@ See the README.md file in the upper level `pppos` directory for more information
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
|
@ -9,7 +9,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -29,6 +29,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -219,6 +219,10 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_BG96;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_EC20;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -52,6 +52,7 @@ typedef enum esp_modem_dce_device {
|
||||
ESP_MODEM_DCE_SIM7070,
|
||||
ESP_MODEM_DCE_SIM7000,
|
||||
ESP_MODEM_DCE_BG96,
|
||||
ESP_MODEM_DCE_EC20,
|
||||
ESP_MODEM_DCE_SIM800,
|
||||
ESP_MODEM_DCE_CUSTOM
|
||||
} esp_modem_dce_device_t;
|
||||
|
@ -59,6 +59,11 @@ WEAK void esp_wifi_internal_free_rx_buffer(void *buffer)
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
WEAK esp_err_t esp_wifi_internal_tx_by_ref(wifi_interface_t ifx, void *buffer, size_t len, void *netstack_buf)
|
||||
{
|
||||
return esp_wifi_internal_tx(ifx, buffer, (uint16_t)len);
|
||||
}
|
||||
|
||||
WEAK int esp_wifi_internal_tx(wifi_interface_t ifx, void *buffer, uint16_t len)
|
||||
{
|
||||
if (ifx == WIFI_IF_STA && s_tx_cb[0]) {
|
||||
|
@ -6,5 +6,5 @@ dependencies:
|
||||
version: '>=0.1'
|
||||
idf:
|
||||
version: '>=5.3'
|
||||
# espressif/esp_hosted:
|
||||
# version: '*'
|
||||
espressif/esp_hosted:
|
||||
version: '>=0.0.6'
|
||||
|
Reference in New Issue
Block a user