From 061885ad2384c9027e2d421835183ba060683e04 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 21 May 2020 17:55:56 +1200 Subject: [PATCH 01/16] esp-netif: Added esp_netif slip support, slip_modem component and example Merges https://github.com/espressif/esp-idf/pull/4985 * Original commit: espressif/esp-idf@266be00254c6e8dcbda75005092260161c03ee95 --- .../slip/components/slip_modem/CMakeLists.txt | 8 + .../slip_modem/include/slip_modem.h | 55 ++++ .../slip_modem/library/slip_modem.c | 303 ++++++++++++++++++ .../protocols/slip/slip_udp/CMakeLists.txt | 12 + examples/protocols/slip/slip_udp/Makefile | 9 + examples/protocols/slip/slip_udp/README.md | 57 ++++ .../slip/slip_udp/main/CMakeLists.txt | 7 + .../slip/slip_udp/main/Kconfig.projbuild | 32 ++ .../protocols/slip/slip_udp/main/component.mk | 4 + .../slip/slip_udp/main/slip_client_main.c | 229 +++++++++++++ .../slip/slip_udp/sdkconfig.defaults | 3 + 11 files changed, 719 insertions(+) create mode 100644 examples/protocols/slip/components/slip_modem/CMakeLists.txt create mode 100644 examples/protocols/slip/components/slip_modem/include/slip_modem.h create mode 100644 examples/protocols/slip/components/slip_modem/library/slip_modem.c create mode 100644 examples/protocols/slip/slip_udp/CMakeLists.txt create mode 100644 examples/protocols/slip/slip_udp/Makefile create mode 100644 examples/protocols/slip/slip_udp/README.md create mode 100644 examples/protocols/slip/slip_udp/main/CMakeLists.txt create mode 100644 examples/protocols/slip/slip_udp/main/Kconfig.projbuild create mode 100644 examples/protocols/slip/slip_udp/main/component.mk create mode 100644 examples/protocols/slip/slip_udp/main/slip_client_main.c create mode 100644 examples/protocols/slip/slip_udp/sdkconfig.defaults diff --git a/examples/protocols/slip/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/components/slip_modem/CMakeLists.txt new file mode 100644 index 000000000..4a596ca72 --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/CMakeLists.txt @@ -0,0 +1,8 @@ +# SLIP Modem Component + +idf_component_register( + SRCS "library/slip_modem.c" + INCLUDE_DIRS "include" + REQUIRES lwip esp_netif +) + diff --git a/examples/protocols/slip/components/slip_modem/include/slip_modem.h b/examples/protocols/slip/components/slip_modem/include/slip_modem.h new file mode 100644 index 000000000..e0e04da4a --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/include/slip_modem.h @@ -0,0 +1,55 @@ + +#pragma once + +#include +#include + +#include "esp_netif.h" +#include "esp_netif_slip.h" + +#include "driver/uart.h" + +// Forward declare modem object +typedef struct esp_slip_modem esp_slip_modem_t; + +// Filter callbacks for handling application specific slip messages +typedef bool slip_rx_filter_cb_t(void *ctx, uint8_t *data, uint32_t len); + + +/** @brief Configuration structure for SLIP modem interface + * + */ +typedef struct { + uart_port_t uart_dev; /* UART device for reading and writing SLIP information, this must be initialised externally */ + + int uart_tx_pin; /* UART TX pin number */ + int uart_rx_pin; /* UART TX pin number */ + + uint32_t uart_baud; /* UART baud rate */ + + uint32_t rx_buffer_len; /* Length of buffer for RX messages */ + + slip_rx_filter_cb_t *rx_filter; /* Filter for parsing out non-SLIP messages from incoming SLIP stream */ + void *rx_filter_ctx; /* Context to be passed to SLIP filter function */ + +} esp_slip_modem_config_t; + + +/** @brief Create a slip modem + * + * @param[in] slip configured esp netif + * @param[in] configuration for the slip modem + * + * @returns + * - slip modem driver glue object + */ +void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config); + +/** @brief Destroy a slip modem + * + * @param[in] slip modem object for destruction + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem); diff --git a/examples/protocols/slip/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/components/slip_modem/library/slip_modem.c new file mode 100644 index 000000000..d7b6b4fba --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/library/slip_modem.c @@ -0,0 +1,303 @@ + + +#include "slip_modem.h" + + +#include "esp_netif.h" +#include "esp_netif_slip.h" +#include "esp_event.h" +#include "esp_log.h" + + +#include "lwip/opt.h" +#include "lwip/sio.h" +#include "lwip/ip.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + +#include "esp_netif_slip.h" + + +#define SLIP_RX_TASK_PRIORITY 10 +#define SLIP_RX_TASK_STACK_SIZE (4 * 1024) + + +static const char *TAG = "esp-slip_modem"; + + +// UART container object +typedef struct { + // UART device number for SIO use + uart_port_t uart_dev; + + // UART baud rate for configuration + uint32_t uart_baud; + + // UART TX pin for configuration + int uart_tx_pin; + + // UART RX pin for configuration + int uart_rx_pin; + + // QueueHandle for uart driver + QueueHandle_t uart_queue; + + // TaskHandle for receive task + TaskHandle_t uart_rx_task; +} esp_slip_uart_t; + + +// Modem object, implements glue logic for slip_driver and esp_netif +struct esp_slip_modem { + // ESP base netif driver + esp_netif_driver_base_t base; + + // LWIP slip context + lwip_slip_ctx_t *slip_driver; + + // Uart for use with slip + esp_slip_uart_t uart; + + // Buffer for incoming messages + uint8_t *buffer; + uint32_t buffer_len; + + // Filter callbacks for application-specific slip message handling + slip_rx_filter_cb_t *rx_filter; + void *rx_filter_ctx; + + // Running flag + bool running; +}; + + +// Forward function definitions +static void esp_slip_modem_uart_rx_task(void *arg); +static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args); + + +// TODO: netif internal functions required for driver operation +esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx); +esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx); + +void esp_netif_lwip_slip_output(lwip_slip_ctx_t *slip_ctx, void *buffer, size_t len); +void esp_netif_lwip_slip_input(void *ctx, void *buffer, size_t len, void *eb); + + +// Create a new slip netif +void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config) +{ + ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); + + // Fetch lwip slip ctx object + // TODO: is the the best / a reasonable approach? + lwip_slip_ctx_t *slip_ctx = esp_netif_lwip_slip_get_ctx(slip_netif); + + ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif); + + esp_slip_modem_t *slip_modem = calloc(1, sizeof(esp_slip_modem_t)); + if (!slip_modem) { + ESP_LOGE(TAG, "create netif glue failed"); + return NULL; + } + + // Attach driver and post_attach callbacks + slip_modem->slip_driver = slip_ctx; + slip_modem->base.post_attach = esp_slip_modem_post_attach; + + // Attach config + slip_modem->buffer_len = modem_config->rx_buffer_len; + + slip_modem->rx_filter = modem_config->rx_filter; + slip_modem->rx_filter_ctx = modem_config->rx_filter_ctx; + + slip_modem->uart.uart_dev = modem_config->uart_dev; + slip_modem->uart.uart_baud = modem_config->uart_baud; + slip_modem->uart.uart_rx_pin = modem_config->uart_rx_pin; + slip_modem->uart.uart_tx_pin = modem_config->uart_tx_pin; + + // Return new modem, with a cast to the first item + return &slip_modem->base; +} + +// Internal handler called on driver start +static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) +{ + ESP_LOGD(TAG, "%s: Starting SLIP modem (modem %p)", __func__, slip_modem); + + // Allocate RX buffer if one does not exist + if (slip_modem->buffer == NULL) { + slip_modem->buffer = malloc(slip_modem->buffer_len); + } + if (slip_modem->buffer == NULL) { + ESP_LOGE(TAG, "error allocating rx buffer"); + return ESP_ERR_NO_MEM; + } + + // Then, initialise UART + + // Build configuration + uart_config_t uart_config = { + .baud_rate = slip_modem->uart.uart_baud, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + }; + + // Initialise uart + ESP_ERROR_CHECK(uart_param_config(slip_modem->uart.uart_dev, &uart_config)); + + // Set UART pins + ESP_ERROR_CHECK(uart_set_pin(slip_modem->uart.uart_dev, slip_modem->uart.uart_tx_pin, slip_modem->uart.uart_rx_pin, 0, 0)); + + // Install UART driver + ESP_ERROR_CHECK(uart_driver_install(slip_modem->uart.uart_dev, slip_modem->buffer_len, slip_modem->buffer_len, 10, &slip_modem->uart.uart_queue, 0)); + + // Start slip RX task + slip_modem->running = true; + xTaskCreate(esp_slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task); + + // Finally, initialise slip network interface + esp_netif_start_slip(slip_modem->slip_driver); + + return ESP_OK; +} + + +esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) +{ + // Stop slip driver + esp_netif_stop_slip(slip_modem->slip_driver); + + // Stop uart rx task + vTaskDelete(slip_modem->uart.uart_rx_task); + + // Delete driver + uart_driver_delete(slip_modem->uart.uart_dev); + + // Free slip interface + free(slip_modem); + + return ESP_OK; +} + +// Modem transmit for glue logic +esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) +{ + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *) slip_driver; + + esp_netif_lwip_slip_output(slip_ctx, buffer, len); + + return ESP_OK; +} + +// Modem receive for glue logic +void esp_slip_modem_receive(esp_netif_t *esp_netif, void *buffer, size_t len) +{ + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + + esp_netif_receive(esp_netif, buffer, len, NULL); +} + +// Post-attach handler for netif +static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) +{ + esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) args; + + ESP_LOGD(TAG, "%s (netif: %p args: %p)", __func__, esp_netif, args); + + const esp_netif_driver_ifconfig_t driver_ifconfig = { + .driver_free_rx_buffer = NULL, + .transmit = esp_slip_modem_transmit, + .handle = slip_modem->slip_driver, + }; + + slip_modem->base.netif = esp_netif; + ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); + + esp_slip_driver_start(slip_modem); + + return ESP_OK; +} + +esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) +{ + esp_err_t ret; + + if (esp_netif == NULL) { + ESP_LOGE(TAG, "esp-netif handle can't be null"); + return ESP_ERR_INVALID_ARG; + } + + ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + +fail: + esp_eth_clear_default_handlers(esp_netif); + return ret; + + return ESP_OK; +} + +esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) +{ + if (!esp_netif) { + ESP_LOGE(TAG, "esp-netif handle can't be null"); + return ESP_ERR_INVALID_ARG; + } + esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start); + esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop); + + return ESP_OK; +} + + + +static void esp_slip_modem_uart_rx_task(void *arg) +{ + esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg; + + ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p slip_ctx %p filter: %p)", slip_modem, slip_modem->slip_driver, slip_modem->rx_filter); + ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len); + + + while (slip_modem->running == true) { + // Read data from the UART + int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_RATE_MS); + + if (len > 0) { + + // Log slip RX data + ESP_LOGD(TAG, "rx %d bytes", len); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, slip_modem->buffer, len, ESP_LOG_DEBUG); + + // Ensure null termination + slip_modem->buffer[len] = '\0'; + + // Filter if provided + if ((slip_modem->rx_filter != NULL) && slip_modem->rx_filter(slip_modem->rx_filter_ctx, slip_modem->buffer, len)) { + continue; + } + + // Pass received bytes in to slip interface + esp_netif_lwip_slip_input(slip_modem->slip_driver, slip_modem->buffer, len, NULL); + } + + // Yeild to allow other tasks to progress + vTaskDelay(1 * portTICK_PERIOD_MS); + } +} + diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt new file mode 100644 index 000000000..b9d68c60f --- /dev/null +++ b/examples/protocols/slip/slip_udp/CMakeLists.txt @@ -0,0 +1,12 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS + ../components/slip_modem/ +) + + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(slip_client) + diff --git a/examples/protocols/slip/slip_udp/Makefile b/examples/protocols/slip/slip_udp/Makefile new file mode 100644 index 000000000..453c971b3 --- /dev/null +++ b/examples/protocols/slip/slip_udp/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := slip_client + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md new file mode 100644 index 000000000..334d2d467 --- /dev/null +++ b/examples/protocols/slip/slip_udp/README.md @@ -0,0 +1,57 @@ +# SLIP device client + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## Overview + +This provides SLIP support for connection to Contiki gateway devices, allowing the ESP32 to be used to bridge between low-power networks and IP (Wifi / Ethernet). + +## How to use example + +### Hardware Required + +To run this example, you need an ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC). +For test purpose, you also need a SLIP capable gateway device, such as anything running [Contiki](https://github.com/contiki-os/contiki) gateway firmware. +You can also try other modules as long as they implement the SLIP protocol. + +#### Pin Assignment + +**Note:** The following pin assignments are used by default which can be changed in menuconfig. + +| ESP32 | Gateway | +| ------ | -------------- | +| GPIO4 | RX | +| GPIO36 | TX | +| GND | GND | +| 3v3 | VCC | + +### Configure the project + +Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu. + +- Choose the RX and TX pins + +For use in external projects `SLIP support` must be enabled under the `components/lwip` menu. + + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build and flash the project.. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + + + +## Troubleshooting + +1. Invalid slip packets + +Many slip devices use additional messages for things like ipv6 prefix configuration (or sending log messages over the SLIP serial port). This is supported in the driver through the use of an `rx_filter` function that is called on receipt of all packets and can be used to filter packets prior to passing them to the stack. + +2. No packets received + +The first layer to check is the serial port, you can enable debugging of the SLIP component by setting the global log level to `DEBUG`, or changing the slip component log levbel with `esp_log_level_set("esp-netif_lwip-slip", ESP_LOG_DEBUG);` + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/protocols/slip/slip_udp/main/CMakeLists.txt b/examples/protocols/slip/slip_udp/main/CMakeLists.txt new file mode 100644 index 000000000..903e70d27 --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/CMakeLists.txt @@ -0,0 +1,7 @@ +# Slip client example + +idf_component_register( + SRCS "slip_client_main.c" + INCLUDE_DIRS "." + REQUIRES esp_netif slip_modem +) diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild new file mode 100644 index 000000000..1709058d0 --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild @@ -0,0 +1,32 @@ +menu "Example Configuration" + + menu "UART Configuration" + config EXAMPLE_UART_TX_PIN + int "TXD Pin Number" + default 4 + range 0 36 + help + Pin number of UART TX. + + config EXAMPLE_UART_RX_PIN + int "RXD Pin Number" + default 36 + range 0 36 + help + Pin number of UART RX. + + config EXAMPLE_UART_BAUD + int "UART baud rate" + default 115200 + help + Baud rate for UART communication + + config EXAMPLE_UDP_PORT + int "Port for UDP echo server" + default 5678 + help + Port for UDP echo server in example + + endmenu + +endmenu diff --git a/examples/protocols/slip/slip_udp/main/component.mk b/examples/protocols/slip/slip_udp/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c new file mode 100644 index 000000000..682e363eb --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -0,0 +1,229 @@ +/* SLIP Client Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + + +#include "esp_system.h" +#include "esp_log.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_netif_slip.h" + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "slip_modem.h" + +static const char *TAG = "SLIP_EXAMPLE"; + +#define STACK_SIZE (10 * 1024) +#define PRIORITY 10 + +TaskHandle_t udp_rx_tx_handle; + +static void udp_rx_tx_task(void *arg) +{ + char addr_str[128]; + uint8_t rx_buff[1024]; + + int sock = *(int *)arg; + + struct sockaddr_in6 source_addr; + socklen_t socklen = sizeof(source_addr); + + + ESP_LOGI(TAG, "Starting node manager UDP task"); + + while (1) { + // Receive data + int len = recvfrom(sock, rx_buff, sizeof(rx_buff) - 1, 0, (struct sockaddr *)&source_addr, &socklen); + if (len < 0) { + ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); + break; + } + + // Parse out address to string + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + + // Force null termination of received data and print + rx_buff[len] = 0; + ESP_LOGI(TAG, "Received '%s' from '%s'", rx_buff, addr_str); + + // Send data back + int err = sendto(sock, rx_buff, len, 0, (struct sockaddr *)&source_addr, socklen); + if (err < 0) { + ESP_LOGE(TAG, "sendto failed: errno %d", errno); + break; + } + } + + vTaskDelete(NULL); +} + +esp_err_t udp_rx_tx_init() +{ + // Setup bind address + struct sockaddr_in6 dest_addr; + bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(CONFIG_EXAMPLE_UDP_PORT); + + // Create socket + int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + if (sock < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + return -1; + } + + // Disable IPv4 and reuse address + int opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); + + // Bind socket + int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + if (err < 0) { + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + return -2; + } + ESP_LOGI(TAG, "Socket bound, port %d", CONFIG_EXAMPLE_UDP_PORT); + + + // Start UDP rx thread + xTaskCreate(udp_rx_tx_task, "udp_rx_tx", STACK_SIZE, &sock, PRIORITY, &udp_rx_tx_handle); + + return ESP_OK; +} + +// Write a prefix to the contiki slip device +static void slip_set_prefix(esp_netif_t *slip_netif) +{ + uint8_t buff[10] = {0}; + + // Fetch the slip interface IP + const ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); + + ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, + lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); + + // Build slip set message + buff[0] = '!'; + buff[1] = 'P'; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 4; j++) { + buff[2 + i * 4 + j] = addr->addr[i] >> (j * 8); + } + } + + // Write raw data out the slip interface + esp_netif_lwip_slip_raw_output(slip_netif, buff, 2 + 8); +} + +// slip_rx_filter filters incomming commands from the slip interface +// this implementation is designed for use with contiki slip devices +bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) +{ + + esp_netif_t *slip_netif = (esp_netif_t *)ctx; + + if (data[1] == '?') { + switch (data[2]) { + case 'P': + ESP_LOGI(TAG, "Prefix request"); + slip_set_prefix(slip_netif); + + return true; + + default: + ESP_LOGI(TAG, "Unhandled request '%c'", data[2]); + break; + } + + return true; + + } else if (data[1] == '!') { + switch (data[2]) { + default: + ESP_LOGI(TAG, "Unhandled command '%c'", data[2]); + break; + } + } + + return false; +} + +// Initialise the SLIP interface +esp_netif_t *slip_if_init() +{ + ESP_LOGI(TAG, "Initialising SLIP interface"); + + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_SLIP(); + esp_netif_t *slip_netif = esp_netif_new(&cfg); + + esp_netif_slip_config_t slip_config = { + .uart_dev = UART_NUM_2, + }; + + IP6_ADDR(&slip_config.addr, + lwip_htonl(0xfd000000), + lwip_htonl(0x00000000), + lwip_htonl(0x00000000), + lwip_htonl(0x000000001) + ); + + esp_netif_slip_set_params(slip_netif, &slip_config); + + ESP_LOGI(TAG, "Initialising SLIP modem"); + + esp_slip_modem_config_t modem_cfg = { + .uart_dev = UART_NUM_2, + + .uart_tx_pin = CONFIG_EXAMPLE_UART_TX_PIN, + .uart_rx_pin = CONFIG_EXAMPLE_UART_RX_PIN, + .uart_baud = CONFIG_EXAMPLE_UART_BAUD, + + .rx_buffer_len = 1024, + + .rx_filter = slip_rx_filter, + .rx_filter_ctx = slip_netif, + }; + + void *slip_modem = esp_slip_modem_create(slip_netif, &modem_cfg); + ESP_ERROR_CHECK(esp_netif_attach(slip_netif, slip_modem)); + + ESP_LOGI(TAG, "SLIP init complete"); + + return slip_netif; +} + +void app_main(void) +{ + // Setup networking + tcpip_adapter_init(); + + esp_log_level_set("*", ESP_LOG_DEBUG); + + // Create event loop + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Setup slip interface + slip_if_init(); + + // Setup UDP loopback service + udp_rx_tx_init(); + + // Run + while (1) { + vTaskDelay(portTICK_PERIOD_MS * 10); + } +} diff --git a/examples/protocols/slip/slip_udp/sdkconfig.defaults b/examples/protocols/slip/slip_udp/sdkconfig.defaults new file mode 100644 index 000000000..9f3d373fa --- /dev/null +++ b/examples/protocols/slip/slip_udp/sdkconfig.defaults @@ -0,0 +1,3 @@ +# Override some defaults to enable SLIP +CONFIG_LWIP_SLIP_SUPPORT=y + From 3bf488eb860d8fee4fa43f27eb5ac284d1c4dc50 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 12 Jun 2020 16:43:34 +0200 Subject: [PATCH 02/16] esp-netif: SLIP interface refactor to isolate interface from drivers * Original commit: espressif/esp-idf@1a41545c3eb7c3b9ed6e64cd3800743236e469cb --- .../protocols/slip/slip_udp/CMakeLists.txt | 6 -- examples/protocols/slip/slip_udp/README.md | 32 ++++++- .../components/slip_modem/CMakeLists.txt | 2 +- .../components/slip_modem/component.mk | 3 + .../slip_modem/include/slip_modem.h | 13 +++ .../slip_modem/library/slip_modem.c | 87 ++++++------------- .../slip/slip_udp/main/Kconfig.projbuild | 18 ++-- .../slip/slip_udp/main/slip_client_main.c | 78 ++++++++++------- 8 files changed, 134 insertions(+), 105 deletions(-) rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/CMakeLists.txt (79%) create mode 100644 examples/protocols/slip/slip_udp/components/slip_modem/component.mk rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/include/slip_modem.h (71%) rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/library/slip_modem.c (80%) diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt index b9d68c60f..5d7fdd6ce 100644 --- a/examples/protocols/slip/slip_udp/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/CMakeLists.txt @@ -2,11 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS - ../components/slip_modem/ -) - - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(slip_client) - diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md index 334d2d467..d7869ff97 100644 --- a/examples/protocols/slip/slip_udp/README.md +++ b/examples/protocols/slip/slip_udp/README.md @@ -4,7 +4,7 @@ ## Overview -This provides SLIP support for connection to Contiki gateway devices, allowing the ESP32 to be used to bridge between low-power networks and IP (Wifi / Ethernet). +This provides SLIP support for connection to Contiki gateway devices, allowing the ESP platform board to be used to bridge between low-power networks and IP (Wifi / Ethernet). ## How to use example @@ -12,7 +12,33 @@ This provides SLIP support for connection to Contiki gateway devices, allowing t To run this example, you need an ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC). For test purpose, you also need a SLIP capable gateway device, such as anything running [Contiki](https://github.com/contiki-os/contiki) gateway firmware. -You can also try other modules as long as they implement the SLIP protocol. +You can also try other modules as long as they implement the SLIP protocol (e.g. linux device with slip module loaded) + +#### Setup a test SLIP device + +It is possible to configure any device with linux and a serial interface +(e.g. raspberry PI or a PC with USB to serial bridge) to enable SLIP interface. + +To test this example with such device, please follow these steps: + +- Configure IPv4 mode in the example configuration menu + +- Setup SLIP interface +``` +slattach -v -L -s 115200 -p slip /dev/ttyAMA0 +``` +where the `/dev/ttyAMA0` is the device's serial port + +- Configure IP addresses +``` +ifconfig sl0 10.0.0.1 dstaddr 10.0.0.2 +``` +where the `10.0.0.2` is IPv4 address of the ESP platform board + +- Send and receive back UDP packets, as the example implements UDP echo server +``` +nc -u 10.0.0.2 5678 +``` #### Pin Assignment @@ -30,7 +56,7 @@ You can also try other modules as long as they implement the SLIP protocol. Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu. - Choose the RX and TX pins - +- Choose port number and IP protocol for socket udp server For use in external projects `SLIP support` must be enabled under the `components/lwip` menu. diff --git a/examples/protocols/slip/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt similarity index 79% rename from examples/protocols/slip/components/slip_modem/CMakeLists.txt rename to examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index 4a596ca72..7739fdfbc 100644 --- a/examples/protocols/slip/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -3,6 +3,6 @@ idf_component_register( SRCS "library/slip_modem.c" INCLUDE_DIRS "include" - REQUIRES lwip esp_netif + REQUIRES esp_netif ) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/component.mk b/examples/protocols/slip/slip_udp/components/slip_modem/component.mk new file mode 100644 index 000000000..b9a426049 --- /dev/null +++ b/examples/protocols/slip/slip_udp/components/slip_modem/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := include + +COMPONENT_SRCDIRS := library diff --git a/examples/protocols/slip/components/slip_modem/include/slip_modem.h b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h similarity index 71% rename from examples/protocols/slip/components/slip_modem/include/slip_modem.h rename to examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h index e0e04da4a..2cbd4be51 100644 --- a/examples/protocols/slip/components/slip_modem/include/slip_modem.h +++ b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h @@ -1,3 +1,16 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once diff --git a/examples/protocols/slip/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c similarity index 80% rename from examples/protocols/slip/components/slip_modem/library/slip_modem.c rename to examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index d7b6b4fba..0583dc238 100644 --- a/examples/protocols/slip/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -1,28 +1,27 @@ - +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "slip_modem.h" - #include "esp_netif.h" #include "esp_netif_slip.h" #include "esp_event.h" #include "esp_log.h" - -#include "lwip/opt.h" -#include "lwip/sio.h" -#include "lwip/ip.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - -#include "esp_netif_slip.h" - - #define SLIP_RX_TASK_PRIORITY 10 #define SLIP_RX_TASK_STACK_SIZE (4 * 1024) - static const char *TAG = "esp-slip_modem"; @@ -53,9 +52,6 @@ struct esp_slip_modem { // ESP base netif driver esp_netif_driver_base_t base; - // LWIP slip context - lwip_slip_ctx_t *slip_driver; - // Uart for use with slip esp_slip_uart_t uart; @@ -72,28 +68,15 @@ struct esp_slip_modem { }; -// Forward function definitions +// Forward function declaration static void esp_slip_modem_uart_rx_task(void *arg); static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args); - -// TODO: netif internal functions required for driver operation -esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx); -esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx); - -void esp_netif_lwip_slip_output(lwip_slip_ctx_t *slip_ctx, void *buffer, size_t len); -void esp_netif_lwip_slip_input(void *ctx, void *buffer, size_t len, void *eb); - - // Create a new slip netif void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config) { ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); - // Fetch lwip slip ctx object - // TODO: is the the best / a reasonable approach? - lwip_slip_ctx_t *slip_ctx = esp_netif_lwip_slip_get_ctx(slip_netif); - ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif); esp_slip_modem_t *slip_modem = calloc(1, sizeof(esp_slip_modem_t)); @@ -103,7 +86,6 @@ void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *mo } // Attach driver and post_attach callbacks - slip_modem->slip_driver = slip_ctx; slip_modem->base.post_attach = esp_slip_modem_post_attach; // Attach config @@ -135,8 +117,6 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) return ESP_ERR_NO_MEM; } - // Then, initialise UART - // Build configuration uart_config_t uart_config = { .baud_rate = slip_modem->uart.uart_baud, @@ -160,7 +140,7 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) xTaskCreate(esp_slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task); // Finally, initialise slip network interface - esp_netif_start_slip(slip_modem->slip_driver); + esp_netif_action_start(slip_modem->base.netif, 0, 0, 0); return ESP_OK; } @@ -169,7 +149,7 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) { // Stop slip driver - esp_netif_stop_slip(slip_modem->slip_driver); + esp_netif_action_stop(slip_modem->base.netif, 0, 0, 0); // Stop uart rx task vTaskDelete(slip_modem->uart.uart_rx_task); @@ -184,27 +164,21 @@ esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) } // Modem transmit for glue logic -esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) +static esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) { ESP_LOGD(TAG, "%s", __func__); ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) slip_driver; - lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *) slip_driver; - - esp_netif_lwip_slip_output(slip_ctx, buffer, len); - + int32_t res = uart_write_bytes(slip_modem->uart.uart_dev, (char *)buffer, len); + if (res < 0) { + // Handle errors + ESP_LOGE(TAG, "%s: uart_write_bytes error %i", __func__, res); + return ESP_FAIL; + } return ESP_OK; } -// Modem receive for glue logic -void esp_slip_modem_receive(esp_netif_t *esp_netif, void *buffer, size_t len) -{ - ESP_LOGD(TAG, "%s", __func__); - ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); - - esp_netif_receive(esp_netif, buffer, len, NULL); -} - // Post-attach handler for netif static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) { @@ -215,7 +189,7 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) const esp_netif_driver_ifconfig_t driver_ifconfig = { .driver_free_rx_buffer = NULL, .transmit = esp_slip_modem_transmit, - .handle = slip_modem->slip_driver, + .handle = slip_modem, }; slip_modem->base.netif = esp_netif; @@ -226,8 +200,7 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) -{ +esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) { esp_err_t ret; if (esp_netif == NULL) { @@ -248,8 +221,6 @@ esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) fail: esp_eth_clear_default_handlers(esp_netif); return ret; - - return ESP_OK; } esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) @@ -265,15 +236,13 @@ esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) } - static void esp_slip_modem_uart_rx_task(void *arg) { esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg; - ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p slip_ctx %p filter: %p)", slip_modem, slip_modem->slip_driver, slip_modem->rx_filter); + ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p filter: %p)", slip_modem, slip_modem->rx_filter); ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len); - while (slip_modem->running == true) { // Read data from the UART int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_RATE_MS); @@ -293,7 +262,7 @@ static void esp_slip_modem_uart_rx_task(void *arg) } // Pass received bytes in to slip interface - esp_netif_lwip_slip_input(slip_modem->slip_driver, slip_modem->buffer, len, NULL); + esp_netif_receive(slip_modem->base.netif, slip_modem->buffer, len, NULL); } // Yeild to allow other tasks to progress diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild index 1709058d0..e23abfa08 100644 --- a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild +++ b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild @@ -21,12 +21,18 @@ menu "Example Configuration" help Baud rate for UART communication - config EXAMPLE_UDP_PORT - int "Port for UDP echo server" - default 5678 - help - Port for UDP echo server in example - endmenu + config EXAMPLE_UDP_PORT + int "Port for UDP echo server" + default 5678 + help + Port for UDP echo server in example + + config EXAMPLE_IPV4 + bool "Test with IPv4 address" + default n + help + Test interface using IPv4 + endmenu diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c index 682e363eb..2fdab8800 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -9,8 +9,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" #include "esp_log.h" @@ -19,8 +17,6 @@ #include "esp_netif_slip.h" #include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" #include "slip_modem.h" @@ -29,14 +25,12 @@ static const char *TAG = "SLIP_EXAMPLE"; #define STACK_SIZE (10 * 1024) #define PRIORITY 10 -TaskHandle_t udp_rx_tx_handle; - static void udp_rx_tx_task(void *arg) { char addr_str[128]; uint8_t rx_buff[1024]; - int sock = *(int *)arg; + int sock = (int)arg; struct sockaddr_in6 source_addr; socklen_t socklen = sizeof(source_addr); @@ -53,7 +47,11 @@ static void udp_rx_tx_task(void *arg) } // Parse out address to string - inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + if (source_addr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.sin6_family == PF_INET6) { + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } // Force null termination of received data and print rx_buff[len] = 0; @@ -70,37 +68,51 @@ static void udp_rx_tx_task(void *arg) vTaskDelete(NULL); } -esp_err_t udp_rx_tx_init() +esp_err_t udp_rx_tx_init(void) { // Setup bind address struct sockaddr_in6 dest_addr; +#if CONFIG_EXAMPLE_IPV4 + sa_family_t family = AF_INET; + int ip_protocol = IPPROTO_IP; + struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr; + dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr_ip4->sin_family = AF_INET; + dest_addr_ip4->sin_port = htons(CONFIG_EXAMPLE_UDP_PORT); + ip_protocol = IPPROTO_IP; +#else + sa_family_t family = AF_INET6; + int ip_protocol = IPPROTO_IPV6; bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); - dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_family = family; dest_addr.sin6_port = htons(CONFIG_EXAMPLE_UDP_PORT); +#endif // Create socket - int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + int sock = socket(family, SOCK_DGRAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); - return -1; + return ESP_FAIL; } // Disable IPv4 and reuse address int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#if !CONFIG_EXAMPLE_IPV4 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); +#endif // Bind socket int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); - return -2; + return ESP_FAIL; } ESP_LOGI(TAG, "Socket bound, port %d", CONFIG_EXAMPLE_UDP_PORT); // Start UDP rx thread - xTaskCreate(udp_rx_tx_task, "udp_rx_tx", STACK_SIZE, &sock, PRIORITY, &udp_rx_tx_handle); + xTaskCreate(udp_rx_tx_task, "udp_rx_tx", STACK_SIZE, (void *)sock, PRIORITY, NULL); return ESP_OK; } @@ -111,7 +123,7 @@ static void slip_set_prefix(esp_netif_t *slip_netif) uint8_t buff[10] = {0}; // Fetch the slip interface IP - const ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); + const esp_ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); @@ -129,7 +141,7 @@ static void slip_set_prefix(esp_netif_t *slip_netif) esp_netif_lwip_slip_raw_output(slip_netif, buff, 2 + 8); } -// slip_rx_filter filters incomming commands from the slip interface +// slip_rx_filter filters incoming commands from the slip interface // this implementation is designed for use with contiki slip devices bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) { @@ -162,23 +174,34 @@ bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) return false; } +#if CONFIG_EXAMPLE_IPV4 +static const esp_netif_ip_info_t s_slip_ip4 = { + .ip = { .addr = ESP_IP4TOADDR( 10, 0, 0, 2) }, +}; +#endif + // Initialise the SLIP interface -esp_netif_t *slip_if_init() +esp_netif_t *slip_if_init(void) { ESP_LOGI(TAG, "Initialising SLIP interface"); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_SLIP(); + esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_SLIP() +#if CONFIG_EXAMPLE_IPV4 + base_cfg.ip_info = &s_slip_ip4; +#endif + esp_netif_config_t cfg = { .base = &base_cfg, + .driver = NULL, + .stack = ESP_NETIF_NETSTACK_DEFAULT_SLIP }; + esp_netif_t *slip_netif = esp_netif_new(&cfg); - esp_netif_slip_config_t slip_config = { - .uart_dev = UART_NUM_2, - }; + esp_netif_slip_config_t slip_config; - IP6_ADDR(&slip_config.addr, + IP6_ADDR(&slip_config.ip6_addr, lwip_htonl(0xfd000000), lwip_htonl(0x00000000), lwip_htonl(0x00000000), - lwip_htonl(0x000000001) + lwip_htonl(0x00000001) ); esp_netif_slip_set_params(slip_netif, &slip_config); @@ -186,7 +209,7 @@ esp_netif_t *slip_if_init() ESP_LOGI(TAG, "Initialising SLIP modem"); esp_slip_modem_config_t modem_cfg = { - .uart_dev = UART_NUM_2, + .uart_dev = UART_NUM_1, .uart_tx_pin = CONFIG_EXAMPLE_UART_TX_PIN, .uart_rx_pin = CONFIG_EXAMPLE_UART_RX_PIN, @@ -209,7 +232,7 @@ esp_netif_t *slip_if_init() void app_main(void) { // Setup networking - tcpip_adapter_init(); + esp_netif_init(); esp_log_level_set("*", ESP_LOG_DEBUG); @@ -221,9 +244,4 @@ void app_main(void) // Setup UDP loopback service udp_rx_tx_init(); - - // Run - while (1) { - vTaskDelay(portTICK_PERIOD_MS * 10); - } } From 36d0d32b35c615e70a4f8481365f060a6bf3b679 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 16 Jun 2020 15:22:40 +0200 Subject: [PATCH 03/16] esp-netif: removing SLIP related events as the slip-modem set state synchronously * Original commit: espressif/esp-idf@bb9a7356acfce03515a4c0bb117d0ec5b9ea4c69 --- .../slip_modem/library/slip_modem.c | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index 0583dc238..2982774d8 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -200,42 +200,6 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) { - esp_err_t ret; - - if (esp_netif == NULL) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } - - ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - -fail: - esp_eth_clear_default_handlers(esp_netif); - return ret; -} - -esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) -{ - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } - esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start); - esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop); - - return ESP_OK; -} - - static void esp_slip_modem_uart_rx_task(void *arg) { esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg; From f1d1d79daf7448b6d37a0782b20ee98df8f10f0d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 21 Aug 2020 08:20:15 +0200 Subject: [PATCH 04/16] esp-netif: Fix SLIP interface to start with correct IPv6 addr Merges https://github.com/espressif/esp-idf/pull/4985 * Original commit: espressif/esp-idf@5dae28069f5c0995a08997008bd954e3efb6bdfd --- examples/protocols/slip/slip_udp/main/slip_client_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c index 2fdab8800..be169a63a 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -198,7 +198,7 @@ esp_netif_t *slip_if_init(void) esp_netif_slip_config_t slip_config; IP6_ADDR(&slip_config.ip6_addr, - lwip_htonl(0xfd000000), + lwip_htonl(0xfd0000), lwip_htonl(0x00000000), lwip_htonl(0x00000000), lwip_htonl(0x00000001) From 0fc1fc6b23fa7898dae6b057f8a449eb13660c3a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 10 Nov 2020 18:40:01 +1100 Subject: [PATCH 05/16] Whitespace: Automated whitespace fixes (large commit) Apply the pre-commit hook whitespace fixes to all files in the repo. (Line endings, blank lines at end of file, trailing whitespace) * Original commit: espressif/esp-idf@66fb5a29bbdc2482d67c52e6f66b303378c9b789 --- examples/protocols/slip/slip_udp/Makefile | 1 - .../protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt | 1 - .../slip/slip_udp/components/slip_modem/library/slip_modem.c | 1 - examples/protocols/slip/slip_udp/sdkconfig.defaults | 1 - 4 files changed, 4 deletions(-) diff --git a/examples/protocols/slip/slip_udp/Makefile b/examples/protocols/slip/slip_udp/Makefile index 453c971b3..866b3d6ae 100644 --- a/examples/protocols/slip/slip_udp/Makefile +++ b/examples/protocols/slip/slip_udp/Makefile @@ -6,4 +6,3 @@ PROJECT_NAME := slip_client include $(IDF_PATH)/make/project.mk - diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index 7739fdfbc..e3fc55fbf 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -5,4 +5,3 @@ idf_component_register( INCLUDE_DIRS "include" REQUIRES esp_netif ) - diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index 2982774d8..c6ad54162 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -233,4 +233,3 @@ static void esp_slip_modem_uart_rx_task(void *arg) vTaskDelay(1 * portTICK_PERIOD_MS); } } - diff --git a/examples/protocols/slip/slip_udp/sdkconfig.defaults b/examples/protocols/slip/slip_udp/sdkconfig.defaults index 9f3d373fa..a0f094bcd 100644 --- a/examples/protocols/slip/slip_udp/sdkconfig.defaults +++ b/examples/protocols/slip/slip_udp/sdkconfig.defaults @@ -1,3 +1,2 @@ # Override some defaults to enable SLIP CONFIG_LWIP_SLIP_SUPPORT=y - From ffa13e4b902e15014df3fee9077be65302c22ff6 Mon Sep 17 00:00:00 2001 From: Xue Yun Fei Date: Thu, 12 Nov 2020 19:41:16 +0800 Subject: [PATCH 06/16] bugfix for ipv6_address_value_issue Closes https://github.com/espressif/esp-idf/issues/5663 * Original commit: espressif/esp-idf@74236f0b295c060e9e95368ce16dac13e8e56247 --- examples/protocols/slip/slip_udp/main/slip_client_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c index be169a63a..8bb131f98 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -32,7 +32,7 @@ static void udp_rx_tx_task(void *arg) int sock = (int)arg; - struct sockaddr_in6 source_addr; + struct sockaddr_storage source_addr; socklen_t socklen = sizeof(source_addr); @@ -47,10 +47,10 @@ static void udp_rx_tx_task(void *arg) } // Parse out address to string - if (source_addr.sin6_family == PF_INET) { + if (source_addr.ss_family == PF_INET) { inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } else if (source_addr.sin6_family == PF_INET6) { - inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.ss_family == PF_INET6) { + inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1); } // Force null termination of received data and print From 0ad6cad8b215597c433a68b8c38b4225ec4d1533 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 5 Nov 2021 15:38:25 +0100 Subject: [PATCH 07/16] Build & config: Remove leftover files from the unsupported "make" build system * Original commit: espressif/esp-idf@766aa5708443099f3f033b739cda0e1de101cca6 --- examples/protocols/slip/slip_udp/Makefile | 8 -------- .../slip/slip_udp/components/slip_modem/component.mk | 3 --- examples/protocols/slip/slip_udp/main/component.mk | 4 ---- 3 files changed, 15 deletions(-) delete mode 100644 examples/protocols/slip/slip_udp/Makefile delete mode 100644 examples/protocols/slip/slip_udp/components/slip_modem/component.mk delete mode 100644 examples/protocols/slip/slip_udp/main/component.mk diff --git a/examples/protocols/slip/slip_udp/Makefile b/examples/protocols/slip/slip_udp/Makefile deleted file mode 100644 index 866b3d6ae..000000000 --- a/examples/protocols/slip/slip_udp/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := slip_client - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/component.mk b/examples/protocols/slip/slip_udp/components/slip_modem/component.mk deleted file mode 100644 index b9a426049..000000000 --- a/examples/protocols/slip/slip_udp/components/slip_modem/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := include - -COMPONENT_SRCDIRS := library diff --git a/examples/protocols/slip/slip_udp/main/component.mk b/examples/protocols/slip/slip_udp/main/component.mk deleted file mode 100644 index a98f634ea..000000000 --- a/examples/protocols/slip/slip_udp/main/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) From e66b19c414c25012735b16c8eff5294f7a17dae9 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 8 Feb 2022 17:39:38 +0800 Subject: [PATCH 08/16] freertos: Remove legacy data types This commit removes the usage of all legacy FreeRTOS data types that are exposed via configENABLE_BACKWARD_COMPATIBILITY. Legacy types can still be used by enabling CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY. * Original commit: espressif/esp-idf@57fd78f5baf93a368a82cf4b2e00ca17ffc09115 --- .../slip_modem/library/slip_modem.c | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index c6ad54162..816ffdded 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "slip_modem.h" @@ -209,7 +201,7 @@ static void esp_slip_modem_uart_rx_task(void *arg) while (slip_modem->running == true) { // Read data from the UART - int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_RATE_MS); + int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_PERIOD_MS); if (len > 0) { From 06dd536d520ebab24547f6902a92f32539ef6f82 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 28 Jan 2022 19:47:04 +0800 Subject: [PATCH 09/16] G0: target component (components/esp32*) doesn't depend on driver anymore * Original commit: espressif/esp-idf@2571aaf3c998f128787554cd5db2933126cc555f --- .../slip/slip_udp/components/slip_modem/CMakeLists.txt | 2 +- examples/protocols/slip/slip_udp/main/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index e3fc55fbf..f35a62ba3 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( SRCS "library/slip_modem.c" INCLUDE_DIRS "include" - REQUIRES esp_netif + REQUIRES esp_netif driver ) diff --git a/examples/protocols/slip/slip_udp/main/CMakeLists.txt b/examples/protocols/slip/slip_udp/main/CMakeLists.txt index 903e70d27..cecffd821 100644 --- a/examples/protocols/slip/slip_udp/main/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/main/CMakeLists.txt @@ -3,5 +3,5 @@ idf_component_register( SRCS "slip_client_main.c" INCLUDE_DIRS "." - REQUIRES esp_netif slip_modem + REQUIRES esp_netif slip_modem driver ) From 582f5b5ff64f981092d7db466fc4c693231bd0aa Mon Sep 17 00:00:00 2001 From: Djordje Nedic Date: Fri, 27 May 2022 10:10:51 +0200 Subject: [PATCH 10/16] tools: Increase the minimal supported CMake version to 3.16 This updates the minimal supported version of CMake to 3.16, which in turn enables us to use more CMake features and have a cleaner build system. This is the version that provides most new features and also the one we use in our latest docker image for CI. * Original commit: espressif/esp-idf@facab8c5a78323dceb0a418ecaaaa4319b102793 --- examples/protocols/slip/slip_udp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt index 5d7fdd6ce..0a8c2f9cc 100644 --- a/examples/protocols/slip/slip_udp/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(slip_client) From c8d0a13f0ea21a8427bc96bd9201d6d12d6e4a7f Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Fri, 20 May 2022 17:50:08 +0800 Subject: [PATCH 11/16] ci: partially enable example build for esp32c2 * Original commit: espressif/esp-idf@f7be540222e204f682dfe27bb23f0f622f5a93e7 --- examples/protocols/slip/slip_udp/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md index d7869ff97..67d21736f 100644 --- a/examples/protocols/slip/slip_udp/README.md +++ b/examples/protocols/slip/slip_udp/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + # SLIP device client (See the README.md file in the upper level 'examples' directory for more information about examples.) From 77a7538a02f61c44b46e658e89c3ea2b92c03cb7 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Wed, 13 Jul 2022 10:41:36 +0800 Subject: [PATCH 12/16] docs: changes docs supported targets tables * Original commit: espressif/esp-idf@c0568611dd3918c30dda9a7cf3e2ce46d74a95ba --- examples/protocols/slip/slip_udp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md index 67d21736f..e83944da8 100644 --- a/examples/protocols/slip/slip_udp/README.md +++ b/examples/protocols/slip/slip_udp/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | | ----------------- | ----- | -------- | -------- | -------- | # SLIP device client From 56cb58ced7f15d990d76d97c82270f6a956ca5ce Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 31 Jan 2022 23:05:03 +0100 Subject: [PATCH 13/16] build system: re-add -Wno-format as private flag for some example components * Original commit: espressif/esp-idf@e596c84d49aa316d1bb57448d86cb40087f7509a --- .../protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt | 1 + examples/protocols/slip/slip_udp/main/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index f35a62ba3..838d5a975 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -5,3 +5,4 @@ idf_component_register( INCLUDE_DIRS "include" REQUIRES esp_netif driver ) +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/examples/protocols/slip/slip_udp/main/CMakeLists.txt b/examples/protocols/slip/slip_udp/main/CMakeLists.txt index cecffd821..eace917e5 100644 --- a/examples/protocols/slip/slip_udp/main/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/main/CMakeLists.txt @@ -5,3 +5,4 @@ idf_component_register( INCLUDE_DIRS "." REQUIRES esp_netif slip_modem driver ) +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") From 52d7458b99f3a5525c954bc5b3430c969232accb Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 22 Jul 2022 17:37:47 +0200 Subject: [PATCH 14/16] esp_netif: Migrate SLIP interface to user-space * Original commit: espressif/esp-idf@83b8556f107fc3d5fd411eb7a2bba185f988cc0f --- examples/protocols/slip/slip_udp/README.md | 6 +- .../components/slip_modem/CMakeLists.txt | 2 +- .../slip_modem/include/slip_modem.h | 70 +++++-- .../slip_modem/library/slip_modem.c | 78 ++++--- .../slip_modem/library/slip_modem_netif.c | 192 ++++++++++++++++++ .../slip_modem/library/slip_modem_netif.h | 42 ++++ .../slip/slip_udp/main/Kconfig.projbuild | 4 +- .../slip/slip_udp/main/slip_client_main.c | 41 ++-- 8 files changed, 354 insertions(+), 81 deletions(-) create mode 100644 examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c create mode 100644 examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md index e83944da8..f8c50d9c3 100644 --- a/examples/protocols/slip/slip_udp/README.md +++ b/examples/protocols/slip/slip_udp/README.md @@ -9,6 +9,8 @@ This provides SLIP support for connection to Contiki gateway devices, allowing the ESP platform board to be used to bridge between low-power networks and IP (Wifi / Ethernet). +This example also demonstrates creating custom network interfaces, including UART drivers and lwIP netif layers, and attaching them to the standard `esp_netif` component, so the generic system interfaces can still use the common approach of listing all interfaces, updating states, posting events and handling routing priorities. Please refer to the implementation of [slip_modem](components/slip_modem) component for more details. + ## How to use example ### Hardware Required @@ -49,8 +51,8 @@ nc -u 10.0.0.2 5678 | ESP32 | Gateway | | ------ | -------------- | -| GPIO4 | RX | -| GPIO36 | TX | +| GPIO25 | RX | +| GPIO26 | TX | | GND | GND | | 3v3 | VCC | diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index 838d5a975..683738628 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -1,7 +1,7 @@ # SLIP Modem Component idf_component_register( - SRCS "library/slip_modem.c" + SRCS "library/slip_modem.c" "library/slip_modem_netif.c" INCLUDE_DIRS "include" REQUIRES esp_netif driver ) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h index 2cbd4be51..53b8eba5b 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h +++ b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,15 +10,30 @@ #include #include "esp_netif.h" -#include "esp_netif_slip.h" - #include "driver/uart.h" +/** @brief Configuration of SLIP network interface + * + */ +#define ESP_NETIF_INHERENT_DEFAULT_SLIP() \ + { \ + ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \ + ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \ + .get_ip_event = 0, \ + .lost_ip_event = 0, \ + .if_key = "SLP_DEF", \ + .if_desc = "slip", \ + .route_prio = 16, \ + .bridge_info = NULL \ +}; + +extern esp_netif_netstack_config_t *netstack_default_slip; + // Forward declare modem object -typedef struct esp_slip_modem esp_slip_modem_t; +typedef struct slip_modem slip_modem_t; // Filter callbacks for handling application specific slip messages -typedef bool slip_rx_filter_cb_t(void *ctx, uint8_t *data, uint32_t len); +typedef bool slip_rx_filter_cb_t(slip_modem_t *slip, uint8_t *data, uint32_t len); /** @brief Configuration structure for SLIP modem interface @@ -43,9 +50,10 @@ typedef struct { uint32_t rx_buffer_len; /* Length of buffer for RX messages */ slip_rx_filter_cb_t *rx_filter; /* Filter for parsing out non-SLIP messages from incoming SLIP stream */ - void *rx_filter_ctx; /* Context to be passed to SLIP filter function */ + esp_ip6_addr_t *ipv6_addr; + +} slip_modem_config_t; -} esp_slip_modem_config_t; /** @brief Create a slip modem @@ -56,7 +64,7 @@ typedef struct { * @returns * - slip modem driver glue object */ -void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config); +slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, slip_modem_config_t *modem_config); /** @brief Destroy a slip modem * @@ -65,4 +73,24 @@ void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *mo * @return * - ESP_OK on success */ -esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem); +esp_err_t slip_modem_destroy(slip_modem_t *slip); + +/** + * @brief Getter for the internally configured IPv6 address + * + * @param[in] slip modem object + * + * @returns + * - ipv6 address + */ +const esp_ip6_addr_t *slip_modem_get_ipv6_address(slip_modem_t *slip); + +/** + * @brief Data path API that forward the supplied data to the attached network interface + * + * @param[in] slip modem object + * @param[in] buffer pointer to the outgoing data + * @param[in] len length of the data + * + */ +void slip_modem_raw_output(slip_modem_t *slip, void *buffer, size_t len); diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index 816ffdded..907270a61 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -4,17 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "slip_modem.h" #include "esp_netif.h" -#include "esp_netif_slip.h" +#include "slip_modem_netif.h" #include "esp_event.h" #include "esp_log.h" #define SLIP_RX_TASK_PRIORITY 10 #define SLIP_RX_TASK_STACK_SIZE (4 * 1024) -static const char *TAG = "esp-slip_modem"; +static const char *TAG = "slip-modem"; // UART container object @@ -40,7 +41,7 @@ typedef struct { // Modem object, implements glue logic for slip_driver and esp_netif -struct esp_slip_modem { +struct slip_modem { // ESP base netif driver esp_netif_driver_base_t base; @@ -53,50 +54,54 @@ struct esp_slip_modem { // Filter callbacks for application-specific slip message handling slip_rx_filter_cb_t *rx_filter; - void *rx_filter_ctx; // Running flag bool running; + + // esp_netif related: SLIP interface IP6 address + esp_ip6_addr_t addr; + }; // Forward function declaration -static void esp_slip_modem_uart_rx_task(void *arg); -static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args); +static void slip_modem_uart_rx_task(void *arg); +static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args); -// Create a new slip netif -void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config) +// Create a new slip modem +slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, slip_modem_config_t *modem_config) { ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif); - esp_slip_modem_t *slip_modem = calloc(1, sizeof(esp_slip_modem_t)); + slip_modem_t *slip_modem = calloc(1, sizeof(slip_modem_t)); if (!slip_modem) { ESP_LOGE(TAG, "create netif glue failed"); return NULL; } // Attach driver and post_attach callbacks - slip_modem->base.post_attach = esp_slip_modem_post_attach; + slip_modem->base.post_attach = slip_modem_post_attach; + slip_modem->base.netif = slip_netif; // Attach config slip_modem->buffer_len = modem_config->rx_buffer_len; slip_modem->rx_filter = modem_config->rx_filter; - slip_modem->rx_filter_ctx = modem_config->rx_filter_ctx; slip_modem->uart.uart_dev = modem_config->uart_dev; slip_modem->uart.uart_baud = modem_config->uart_baud; slip_modem->uart.uart_rx_pin = modem_config->uart_rx_pin; slip_modem->uart.uart_tx_pin = modem_config->uart_tx_pin; + memcpy(&slip_modem->addr, modem_config->ipv6_addr, sizeof(esp_ip6_addr_t)); - // Return new modem, with a cast to the first item - return &slip_modem->base; + // Return the new modem + return slip_modem; } // Internal handler called on driver start -static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) +static esp_err_t esp_slip_driver_start(slip_modem_t *slip_modem) { ESP_LOGD(TAG, "%s: Starting SLIP modem (modem %p)", __func__, slip_modem); @@ -129,38 +134,39 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) // Start slip RX task slip_modem->running = true; - xTaskCreate(esp_slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task); + xTaskCreate(slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task); // Finally, initialise slip network interface esp_netif_action_start(slip_modem->base.netif, 0, 0, 0); - + ESP_ERROR_CHECK(slip_modem_netif_start(slip_modem->base.netif, &slip_modem->addr)); return ESP_OK; } -esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) +esp_err_t slip_modem_destroy(slip_modem_t *slip) { // Stop slip driver - esp_netif_action_stop(slip_modem->base.netif, 0, 0, 0); + esp_netif_action_stop(slip->base.netif, 0, 0, 0); + ESP_ERROR_CHECK(slip_modem_netif_stop(slip->base.netif)); // Stop uart rx task - vTaskDelete(slip_modem->uart.uart_rx_task); + vTaskDelete(slip->uart.uart_rx_task); // Delete driver - uart_driver_delete(slip_modem->uart.uart_dev); + uart_driver_delete(slip->uart.uart_dev); // Free slip interface - free(slip_modem); + free(slip); return ESP_OK; } // Modem transmit for glue logic -static esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) +static esp_err_t slip_modem_transmit(void *slip_driver, void *buffer, size_t len) { ESP_LOGD(TAG, "%s", __func__); ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); - esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) slip_driver; + slip_modem_t *slip_modem = (slip_modem_t *) slip_driver; int32_t res = uart_write_bytes(slip_modem->uart.uart_dev, (char *)buffer, len); if (res < 0) { @@ -172,15 +178,15 @@ static esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t } // Post-attach handler for netif -static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) +static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args) { - esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) args; + slip_modem_t *slip_modem = (slip_modem_t *) args; ESP_LOGD(TAG, "%s (netif: %p args: %p)", __func__, esp_netif, args); const esp_netif_driver_ifconfig_t driver_ifconfig = { .driver_free_rx_buffer = NULL, - .transmit = esp_slip_modem_transmit, + .transmit = slip_modem_transmit, .handle = slip_modem, }; @@ -192,9 +198,9 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -static void esp_slip_modem_uart_rx_task(void *arg) +static void slip_modem_uart_rx_task(void *arg) { - esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg; + slip_modem_t *slip_modem = (slip_modem_t *) arg; ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p filter: %p)", slip_modem, slip_modem->rx_filter); ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len); @@ -213,11 +219,12 @@ static void esp_slip_modem_uart_rx_task(void *arg) slip_modem->buffer[len] = '\0'; // Filter if provided - if ((slip_modem->rx_filter != NULL) && slip_modem->rx_filter(slip_modem->rx_filter_ctx, slip_modem->buffer, len)) { + if ((slip_modem->rx_filter != NULL) && slip_modem->rx_filter(slip_modem, slip_modem->buffer, len)) { continue; } // Pass received bytes in to slip interface + ESP_LOGI(TAG, "esp_netif %p", slip_modem->base.netif); esp_netif_receive(slip_modem->base.netif, slip_modem->buffer, len, NULL); } @@ -225,3 +232,16 @@ static void esp_slip_modem_uart_rx_task(void *arg) vTaskDelay(1 * portTICK_PERIOD_MS); } } + +/** + * @brief Gets the internally configured ipv6 address + */ +const esp_ip6_addr_t *slip_modem_get_ipv6_address(slip_modem_t *slip) +{ + return &slip->addr; +} + +void slip_modem_raw_output(slip_modem_t *slip, void *buffer, size_t len) +{ + slip_modem_netif_raw_output(slip->base.netif, buffer, len); +} diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c new file mode 100644 index 000000000..ee90bb6e0 --- /dev/null +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_netif.h" +#include "esp_log.h" +#include "esp_netif_net_stack.h" +#include "lwip/esp_netif_net_stack.h" +#include "lwip/dns.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "netif/slipif.h" +#include "lwip/sio.h" + +static const char *TAG = "slip-modem-netif"; + +/** + * @brief Stops the SLIP interface + */ +esp_err_t slip_modem_netif_stop(esp_netif_t *esp_netif) +{ + struct netif *netif = esp_netif_get_netif_impl(esp_netif); + + ESP_LOGI(TAG, "%s: Stopped SLIP connection: lwip netif:%p", __func__, netif); + + // Stop interface + netif_set_link_down(netif); + + return ESP_OK; +} + +/** + * @brief Starts the SLIP interface + */ +esp_err_t slip_modem_netif_start(esp_netif_t *esp_netif, esp_ip6_addr_t *addr) +{ + struct netif *netif = esp_netif_get_netif_impl(esp_netif); + + ESP_LOGI(TAG, "%s: Starting SLIP interface: lwip netif:%p", __func__, netif); + + // Set the netif up + netif_set_up(netif); + netif_set_link_up(netif); +#if CONFIG_LWIP_IPV6 + int8_t addr_index = 0; + + netif_ip6_addr_set(netif, addr_index, (ip6_addr_t *)addr); + netif_ip6_addr_set_state(netif, addr_index, IP6_ADDR_VALID); +#endif + return ESP_OK; +} + +/** + * @brief Write incoming serial data to the SLIP interface + */ +void esp_netif_lwip_slip_input(void *h, void *buffer, unsigned int len, void *eb) +{ + struct netif *netif = h; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + + // Update slip netif with data + const int max_batch = 255; + int sent = 0; + while(sent < len) { + int batch = (len - sent) > max_batch ? max_batch : (len - sent); + slipif_received_bytes(netif, buffer+sent, batch); + sent += batch; + } + + // Process incoming bytes + for (int i = 0; i < len; i++) { + slipif_process_rxqueue(netif); + } +} + +/** + * @brief Write raw data out the SLIP interface + */ +void slip_modem_netif_raw_output(esp_netif_t *netif, void *buffer, size_t len) +{ + struct netif *lwip_netif = esp_netif_get_netif_impl(netif); + + ESP_LOGD(TAG, "%s", __func__); + + struct pbuf p = { + .next = NULL, + .payload = buffer, + .tot_len = len, + .len = len, + }; + + // Call slip if output function to feed data out slip interface +#if CONFIG_LWIP_IPV6 + lwip_netif->output_ip6(lwip_netif, &p, NULL); +#else + lwip_netif->output(lwip_netif, &p, NULL); +#endif +} + + +/** @brief Get esp-netif object corresponding to registration index + */ +static esp_netif_t * get_netif_with_esp_index(int index) +{ + esp_netif_t *netif = NULL; + int counter = 0; + while ((netif = esp_netif_next(netif)) != NULL) { + if (counter == index) { + return netif; + } + counter++; + } + return NULL; +} + +/** @brief Return list registration index of the supplied netif ptr + */ +static int get_esp_netif_index(esp_netif_t * esp_netif) +{ + esp_netif_t *netif = NULL; + int counter = 0; + while ((netif = esp_netif_next(netif)) != NULL) { + if (esp_netif == netif) { + return counter; + } + counter++; + } + return -1; +} + +err_t esp_slipif_init(struct netif *netif) +{ + esp_netif_t *esp_netif = netif->state; + int esp_index = get_esp_netif_index(esp_netif); + if (esp_index < 0) { + return ERR_IF; + } + + // Store netif index in net interface for SIO open command to abstract the dev + netif->state = (void *)esp_index; + + return slipif_init(netif); +} + +const struct esp_netif_netstack_config s_netif_config_slip = { + .lwip = { + .init_fn = esp_slipif_init, + .input_fn = esp_netif_lwip_slip_input, + } +}; + +const esp_netif_netstack_config_t *netstack_default_slip = &s_netif_config_slip; + + +/*** + * @brief Open a serial device for communication + */ +sio_fd_t sio_open(uint8_t devnum) +{ + ESP_LOGD(TAG, "Opening device: %d\r\n", devnum); + + esp_netif_t *esp_netif = get_netif_with_esp_index(devnum); + if (!esp_netif) { + ESP_LOGE(TAG, "didn't find esp-netif with index=%d\n", devnum); + return NULL; + } + + // Return SIO handle + return esp_netif; +} + +/*** + * @brief Send a single character to the serial device (blocking) + */ +void sio_send(uint8_t c, sio_fd_t fd) +{ + esp_netif_t *esp_netif = fd; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG); + + esp_err_t ret = esp_netif_transmit(esp_netif, &c, 1); + if (ret != ESP_OK) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, ret); + } +} diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h new file mode 100644 index 000000000..339ee675b --- /dev/null +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @brief Stop the esp slip netif + * + * @param[in] esp_netif handle to slip esp-netif instance + * + * @return + * - ESP_OK on success + */ +esp_err_t slip_modem_netif_stop(esp_netif_t *esp_netif); + +/** + * @brief Start the esp slip netif + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] addr IPv6 address associated with this SLIP interface + * + * @return + * - ESP_OK on success + */ +esp_err_t slip_modem_netif_start(esp_netif_t *esp_netif, esp_ip6_addr_t *addr); + +/** + * @brief Data path API to write raw packet ous the SLIP interface + * + * This API is typically used when implementing user defined methods + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] buffer pointer to the outgoing data + * @param[in] len length of the data + * + * @return + * - ESP_OK on success + */ +void slip_modem_netif_raw_output(esp_netif_t *netif, void *buffer, size_t len); diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild index e23abfa08..047ba12e2 100644 --- a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild +++ b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild @@ -3,14 +3,14 @@ menu "Example Configuration" menu "UART Configuration" config EXAMPLE_UART_TX_PIN int "TXD Pin Number" - default 4 + default 25 range 0 36 help Pin number of UART TX. config EXAMPLE_UART_RX_PIN int "RXD Pin Number" - default 36 + default 26 range 0 36 help Pin number of UART RX. diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c index 8bb131f98..72a364a4f 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -7,20 +7,18 @@ CONDITIONS OF ANY KIND, either express or implied. */ #include +#include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" - #include "esp_system.h" #include "esp_log.h" #include "esp_event.h" #include "esp_netif.h" -#include "esp_netif_slip.h" - -#include "lwip/sockets.h" #include "slip_modem.h" -static const char *TAG = "SLIP_EXAMPLE"; +static const char *TAG = "slip-example"; #define STACK_SIZE (10 * 1024) #define PRIORITY 10 @@ -118,13 +116,10 @@ esp_err_t udp_rx_tx_init(void) } // Write a prefix to the contiki slip device -static void slip_set_prefix(esp_netif_t *slip_netif) +static void slip_set_prefix(slip_modem_t *slip) { uint8_t buff[10] = {0}; - - // Fetch the slip interface IP - const esp_ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); - + const esp_ip6_addr_t *addr = slip_modem_get_ipv6_address(slip); ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); @@ -138,21 +133,18 @@ static void slip_set_prefix(esp_netif_t *slip_netif) } // Write raw data out the slip interface - esp_netif_lwip_slip_raw_output(slip_netif, buff, 2 + 8); + slip_modem_raw_output(slip, buff, 2 + 8); } // slip_rx_filter filters incoming commands from the slip interface // this implementation is designed for use with contiki slip devices -bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) +static bool slip_rx_filter(slip_modem_t *slip, uint8_t *data, uint32_t len) { - - esp_netif_t *slip_netif = (esp_netif_t *)ctx; - if (data[1] == '?') { switch (data[2]) { case 'P': ESP_LOGI(TAG, "Prefix request"); - slip_set_prefix(slip_netif); + slip_set_prefix(slip); return true; @@ -191,24 +183,21 @@ esp_netif_t *slip_if_init(void) #endif esp_netif_config_t cfg = { .base = &base_cfg, .driver = NULL, - .stack = ESP_NETIF_NETSTACK_DEFAULT_SLIP }; + .stack = netstack_default_slip }; esp_netif_t *slip_netif = esp_netif_new(&cfg); - esp_netif_slip_config_t slip_config; - - IP6_ADDR(&slip_config.ip6_addr, + esp_ip6_addr_t local_addr; /* Local IP6 address */ + IP6_ADDR(&local_addr, lwip_htonl(0xfd0000), lwip_htonl(0x00000000), lwip_htonl(0x00000000), lwip_htonl(0x00000001) ); - esp_netif_slip_set_params(slip_netif, &slip_config); - ESP_LOGI(TAG, "Initialising SLIP modem"); - esp_slip_modem_config_t modem_cfg = { + slip_modem_config_t modem_cfg = { .uart_dev = UART_NUM_1, .uart_tx_pin = CONFIG_EXAMPLE_UART_TX_PIN, @@ -216,12 +205,12 @@ esp_netif_t *slip_if_init(void) .uart_baud = CONFIG_EXAMPLE_UART_BAUD, .rx_buffer_len = 1024, - .rx_filter = slip_rx_filter, - .rx_filter_ctx = slip_netif, + .ipv6_addr = &local_addr }; - void *slip_modem = esp_slip_modem_create(slip_netif, &modem_cfg); + void *slip_modem = slip_modem_create(slip_netif, &modem_cfg); + assert(slip_modem); ESP_ERROR_CHECK(esp_netif_attach(slip_netif, slip_modem)); ESP_LOGI(TAG, "SLIP init complete"); From fcd6f0bb14f2e7480ce90a43f9f2036d0c3d91ac Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 14 Sep 2022 15:19:27 +0200 Subject: [PATCH 15/16] feat(examples): Move the slip example to esp-netif folder And update the slip_modem_get_ipv6_address() to return the address by copy instead of reference (to employ return value optimizaiton where possible) --- .../slip_custom_netif}/CMakeLists.txt | 0 .../slip_custom_netif}/README.md | 0 .../components/slip_modem/CMakeLists.txt | 0 .../components/slip_modem/include/slip_modem.h | 9 ++++----- .../components/slip_modem/library/slip_modem.c | 13 ++++++------- .../slip_modem/library/slip_modem_netif.c | 2 +- .../slip_modem/library/slip_modem_netif.h | 2 +- .../slip_custom_netif}/main/CMakeLists.txt | 0 .../slip_custom_netif}/main/Kconfig.projbuild | 0 .../slip_custom_netif}/main/slip_client_main.c | 8 ++++---- .../slip_custom_netif}/sdkconfig.defaults | 0 11 files changed, 16 insertions(+), 18 deletions(-) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/CMakeLists.txt (100%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/README.md (100%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/components/slip_modem/CMakeLists.txt (100%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/components/slip_modem/include/slip_modem.h (88%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/components/slip_modem/library/slip_modem.c (94%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/components/slip_modem/library/slip_modem_netif.c (98%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/components/slip_modem/library/slip_modem_netif.h (92%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/main/CMakeLists.txt (100%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/main/Kconfig.projbuild (100%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/main/slip_client_main.c (96%) rename examples/{protocols/slip/slip_udp => esp_netif/slip_custom_netif}/sdkconfig.defaults (100%) diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/esp_netif/slip_custom_netif/CMakeLists.txt similarity index 100% rename from examples/protocols/slip/slip_udp/CMakeLists.txt rename to examples/esp_netif/slip_custom_netif/CMakeLists.txt diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/esp_netif/slip_custom_netif/README.md similarity index 100% rename from examples/protocols/slip/slip_udp/README.md rename to examples/esp_netif/slip_custom_netif/README.md diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt b/examples/esp_netif/slip_custom_netif/components/slip_modem/CMakeLists.txt similarity index 100% rename from examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt rename to examples/esp_netif/slip_custom_netif/components/slip_modem/CMakeLists.txt diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h b/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h similarity index 88% rename from examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h rename to examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h index 53b8eba5b..4dd0be4e7 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h @@ -29,7 +29,6 @@ extern esp_netif_netstack_config_t *netstack_default_slip; -// Forward declare modem object typedef struct slip_modem slip_modem_t; // Filter callbacks for handling application specific slip messages @@ -64,7 +63,7 @@ typedef struct { * @returns * - slip modem driver glue object */ -slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, slip_modem_config_t *modem_config); +slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config); /** @brief Destroy a slip modem * @@ -81,9 +80,9 @@ esp_err_t slip_modem_destroy(slip_modem_t *slip); * @param[in] slip modem object * * @returns - * - ipv6 address + * - ipv6 address returned by copy */ -const esp_ip6_addr_t *slip_modem_get_ipv6_address(slip_modem_t *slip); +esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip); /** * @brief Data path API that forward the supplied data to the attached network interface @@ -93,4 +92,4 @@ const esp_ip6_addr_t *slip_modem_get_ipv6_address(slip_modem_t *slip); * @param[in] len length of the data * */ -void slip_modem_raw_output(slip_modem_t *slip, void *buffer, size_t len); +void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len); diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c similarity index 94% rename from examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c rename to examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c index 907270a61..d12283531 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c @@ -64,12 +64,11 @@ struct slip_modem { }; -// Forward function declaration static void slip_modem_uart_rx_task(void *arg); static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args); // Create a new slip modem -slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, slip_modem_config_t *modem_config) +slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config) { ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); @@ -228,7 +227,7 @@ static void slip_modem_uart_rx_task(void *arg) esp_netif_receive(slip_modem->base.netif, slip_modem->buffer, len, NULL); } - // Yeild to allow other tasks to progress + // Yield to allow other tasks to progress vTaskDelay(1 * portTICK_PERIOD_MS); } } @@ -236,12 +235,12 @@ static void slip_modem_uart_rx_task(void *arg) /** * @brief Gets the internally configured ipv6 address */ -const esp_ip6_addr_t *slip_modem_get_ipv6_address(slip_modem_t *slip) +esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip) { - return &slip->addr; + return slip->addr; } -void slip_modem_raw_output(slip_modem_t *slip, void *buffer, size_t len) +void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len) { - slip_modem_netif_raw_output(slip->base.netif, buffer, len); + slip_modem_netif_raw_write(slip->base.netif, buffer, len); } diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c similarity index 98% rename from examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c rename to examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c index ee90bb6e0..dd7328faa 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.c +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c @@ -81,7 +81,7 @@ void esp_netif_lwip_slip_input(void *h, void *buffer, unsigned int len, void *eb /** * @brief Write raw data out the SLIP interface */ -void slip_modem_netif_raw_output(esp_netif_t *netif, void *buffer, size_t len) +void slip_modem_netif_raw_write(esp_netif_t *netif, void *buffer, size_t len) { struct netif *lwip_netif = esp_netif_get_netif_impl(netif); diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.h similarity index 92% rename from examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h rename to examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.h index 339ee675b..ad5694c2a 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem_netif.h +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.h @@ -39,4 +39,4 @@ esp_err_t slip_modem_netif_start(esp_netif_t *esp_netif, esp_ip6_addr_t *addr); * @return * - ESP_OK on success */ -void slip_modem_netif_raw_output(esp_netif_t *netif, void *buffer, size_t len); +void slip_modem_netif_raw_write(esp_netif_t *netif, void *buffer, size_t len); diff --git a/examples/protocols/slip/slip_udp/main/CMakeLists.txt b/examples/esp_netif/slip_custom_netif/main/CMakeLists.txt similarity index 100% rename from examples/protocols/slip/slip_udp/main/CMakeLists.txt rename to examples/esp_netif/slip_custom_netif/main/CMakeLists.txt diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/esp_netif/slip_custom_netif/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/slip/slip_udp/main/Kconfig.projbuild rename to examples/esp_netif/slip_custom_netif/main/Kconfig.projbuild diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/esp_netif/slip_custom_netif/main/slip_client_main.c similarity index 96% rename from examples/protocols/slip/slip_udp/main/slip_client_main.c rename to examples/esp_netif/slip_custom_netif/main/slip_client_main.c index 72a364a4f..414d01044 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/esp_netif/slip_custom_netif/main/slip_client_main.c @@ -119,21 +119,21 @@ esp_err_t udp_rx_tx_init(void) static void slip_set_prefix(slip_modem_t *slip) { uint8_t buff[10] = {0}; - const esp_ip6_addr_t *addr = slip_modem_get_ipv6_address(slip); + const esp_ip6_addr_t addr = slip_modem_get_ipv6_address(slip); ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, - lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); + lwip_ntohl(addr.addr[0]), lwip_ntohl(addr.addr[1])); // Build slip set message buff[0] = '!'; buff[1] = 'P'; for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) { - buff[2 + i * 4 + j] = addr->addr[i] >> (j * 8); + buff[2 + i * 4 + j] = addr.addr[i] >> (j * 8); } } // Write raw data out the slip interface - slip_modem_raw_output(slip, buff, 2 + 8); + slip_modem_raw_write(slip, buff, 2 + 8); } // slip_rx_filter filters incoming commands from the slip interface diff --git a/examples/protocols/slip/slip_udp/sdkconfig.defaults b/examples/esp_netif/slip_custom_netif/sdkconfig.defaults similarity index 100% rename from examples/protocols/slip/slip_udp/sdkconfig.defaults rename to examples/esp_netif/slip_custom_netif/sdkconfig.defaults From 7a21db23ad8f184da502f70c7dddfa851055c729 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 30 Sep 2022 15:25:43 +0200 Subject: [PATCH 16/16] fix(examples): Update SLIP example with error checks --- .../slip_modem/include/slip_modem.h | 18 +++---- .../slip_modem/library/slip_modem.c | 48 +++++++++++-------- .../slip_modem/library/slip_modem_netif.c | 5 +- .../slip_custom_netif/main/slip_client_main.c | 13 ++--- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h b/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h index 4dd0be4e7..7dcd422de 100644 --- a/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/include/slip_modem.h @@ -29,10 +29,10 @@ extern esp_netif_netstack_config_t *netstack_default_slip; -typedef struct slip_modem slip_modem_t; +typedef struct slip_modem* slip_modem_handle; // Filter callbacks for handling application specific slip messages -typedef bool slip_rx_filter_cb_t(slip_modem_t *slip, uint8_t *data, uint32_t len); +typedef bool slip_rx_filter_cb_t(slip_modem_handle slip, uint8_t *data, uint32_t len); /** @brief Configuration structure for SLIP modem interface @@ -63,26 +63,26 @@ typedef struct { * @returns * - slip modem driver glue object */ -slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config); +slip_modem_handle slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config); /** @brief Destroy a slip modem * - * @param[in] slip modem object for destruction + * @param[in] slip modem handle for destruction * * @return * - ESP_OK on success */ -esp_err_t slip_modem_destroy(slip_modem_t *slip); +esp_err_t slip_modem_destroy(slip_modem_handle slip); /** * @brief Getter for the internally configured IPv6 address * - * @param[in] slip modem object + * @param[in] slip modem handle * * @returns - * - ipv6 address returned by copy + * - ipv6 address */ -esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip); +esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_handle slip); /** * @brief Data path API that forward the supplied data to the attached network interface @@ -92,4 +92,4 @@ esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip); * @param[in] len length of the data * */ -void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len); +void slip_modem_raw_write(slip_modem_handle slip, void *buffer, size_t len); diff --git a/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c index d12283531..278f926ae 100644 --- a/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem.c @@ -68,13 +68,17 @@ static void slip_modem_uart_rx_task(void *arg); static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args); // Create a new slip modem -slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config) +slip_modem_handle slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config_t *modem_config) { + if (slip_netif == NULL || modem_config == NULL) { + ESP_LOGE(TAG, "invalid parameters"); + return NULL; + } ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif); - slip_modem_t *slip_modem = calloc(1, sizeof(slip_modem_t)); + slip_modem_handle slip_modem = calloc(1, sizeof(struct slip_modem)); if (!slip_modem) { ESP_LOGE(TAG, "create netif glue failed"); return NULL; @@ -93,14 +97,14 @@ slip_modem_t *slip_modem_create(esp_netif_t *slip_netif, const slip_modem_config slip_modem->uart.uart_baud = modem_config->uart_baud; slip_modem->uart.uart_rx_pin = modem_config->uart_rx_pin; slip_modem->uart.uart_tx_pin = modem_config->uart_tx_pin; - memcpy(&slip_modem->addr, modem_config->ipv6_addr, sizeof(esp_ip6_addr_t)); + slip_modem->addr = *modem_config->ipv6_addr; // Return the new modem return slip_modem; } // Internal handler called on driver start -static esp_err_t esp_slip_driver_start(slip_modem_t *slip_modem) +static esp_err_t esp_slip_driver_start(slip_modem_handle slip_modem) { ESP_LOGD(TAG, "%s: Starting SLIP modem (modem %p)", __func__, slip_modem); @@ -142,20 +146,22 @@ static esp_err_t esp_slip_driver_start(slip_modem_t *slip_modem) } -esp_err_t slip_modem_destroy(slip_modem_t *slip) +esp_err_t slip_modem_destroy(slip_modem_handle slip) { - // Stop slip driver - esp_netif_action_stop(slip->base.netif, 0, 0, 0); - ESP_ERROR_CHECK(slip_modem_netif_stop(slip->base.netif)); + if (slip != NULL) { + // Stop slip driver + esp_netif_action_stop(slip->base.netif, 0, 0, 0); + ESP_ERROR_CHECK(slip_modem_netif_stop(slip->base.netif)); - // Stop uart rx task - vTaskDelete(slip->uart.uart_rx_task); + // Stop uart rx task + vTaskDelete(slip->uart.uart_rx_task); - // Delete driver - uart_driver_delete(slip->uart.uart_dev); + // Delete driver + uart_driver_delete(slip->uart.uart_dev); - // Free slip interface - free(slip); + // Free slip interface + free(slip); + } return ESP_OK; } @@ -165,7 +171,7 @@ static esp_err_t slip_modem_transmit(void *slip_driver, void *buffer, size_t len { ESP_LOGD(TAG, "%s", __func__); ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); - slip_modem_t *slip_modem = (slip_modem_t *) slip_driver; + slip_modem_handle slip_modem = (slip_modem_handle)slip_driver; int32_t res = uart_write_bytes(slip_modem->uart.uart_dev, (char *)buffer, len); if (res < 0) { @@ -179,7 +185,7 @@ static esp_err_t slip_modem_transmit(void *slip_driver, void *buffer, size_t len // Post-attach handler for netif static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args) { - slip_modem_t *slip_modem = (slip_modem_t *) args; + slip_modem_handle slip_modem = (slip_modem_handle) args; ESP_LOGD(TAG, "%s (netif: %p args: %p)", __func__, esp_netif, args); @@ -199,7 +205,11 @@ static esp_err_t slip_modem_post_attach(esp_netif_t *esp_netif, void *args) static void slip_modem_uart_rx_task(void *arg) { - slip_modem_t *slip_modem = (slip_modem_t *) arg; + if (arg == NULL) { + ESP_LOGE(TAG, "Starting a task with invalid parameters, deleting"); + vTaskDelete(NULL); + } + slip_modem_handle slip_modem = (slip_modem_handle) arg; ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p filter: %p)", slip_modem, slip_modem->rx_filter); ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len); @@ -235,12 +245,12 @@ static void slip_modem_uart_rx_task(void *arg) /** * @brief Gets the internally configured ipv6 address */ -esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_t *slip) +esp_ip6_addr_t slip_modem_get_ipv6_address(slip_modem_handle slip) { return slip->addr; } -void slip_modem_raw_write(slip_modem_t *slip, void *buffer, size_t len) +void slip_modem_raw_write(slip_modem_handle slip, void *buffer, size_t len) { slip_modem_netif_raw_write(slip->base.netif, buffer, len); } diff --git a/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c index dd7328faa..d82318096 100644 --- a/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c +++ b/examples/esp_netif/slip_custom_netif/components/slip_modem/library/slip_modem_netif.c @@ -133,8 +133,11 @@ static int get_esp_netif_index(esp_netif_t * esp_netif) return -1; } -err_t esp_slipif_init(struct netif *netif) +static err_t esp_slipif_init(struct netif *netif) { + if (netif == NULL) { + return ERR_IF; + } esp_netif_t *esp_netif = netif->state; int esp_index = get_esp_netif_index(esp_netif); if (esp_index < 0) { diff --git a/examples/esp_netif/slip_custom_netif/main/slip_client_main.c b/examples/esp_netif/slip_custom_netif/main/slip_client_main.c index 414d01044..82188556c 100644 --- a/examples/esp_netif/slip_custom_netif/main/slip_client_main.c +++ b/examples/esp_netif/slip_custom_netif/main/slip_client_main.c @@ -66,7 +66,7 @@ static void udp_rx_tx_task(void *arg) vTaskDelete(NULL); } -esp_err_t udp_rx_tx_init(void) +static esp_err_t udp_rx_tx_start(void) { // Setup bind address struct sockaddr_in6 dest_addr; @@ -116,7 +116,7 @@ esp_err_t udp_rx_tx_init(void) } // Write a prefix to the contiki slip device -static void slip_set_prefix(slip_modem_t *slip) +static void slip_set_prefix(slip_modem_handle slip) { uint8_t buff[10] = {0}; const esp_ip6_addr_t addr = slip_modem_get_ipv6_address(slip); @@ -138,7 +138,7 @@ static void slip_set_prefix(slip_modem_t *slip) // slip_rx_filter filters incoming commands from the slip interface // this implementation is designed for use with contiki slip devices -static bool slip_rx_filter(slip_modem_t *slip, uint8_t *data, uint32_t len) +static bool slip_rx_filter(slip_modem_handle slip, uint8_t *data, uint32_t len) { if (data[1] == '?') { switch (data[2]) { @@ -229,8 +229,9 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); // Setup slip interface - slip_if_init(); + esp_netif_t* esp_netif = slip_if_init(); + assert(esp_netif); - // Setup UDP loopback service - udp_rx_tx_init(); + // Start the UDP user application + udp_rx_tx_start(); }