Linux port: Initial implementation of linux port and mock layers

This commit is contained in:
David Cermak
2021-05-15 22:09:08 +02:00
parent 5fdb0b572b
commit 9f4fe3a177
42 changed files with 1122 additions and 673 deletions

View File

@ -32,3 +32,5 @@ idf_component_register(SRCS "${srcs}"
REQUIRES ${dependencies})
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_FLAGS -Wno-format)

View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS ../.. ../../port/linux)
set(COMPONENTS main)
project(linux_modem)
idf_component_get_property(esp_modem esp_modem COMPONENT_LIB)
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_COMPILER_CXX_EXCEPTIONS")
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")

View File

@ -0,0 +1,19 @@
# Linux modem example
This is an experimental port of the esp_modem to linux.
It mocks some IDF functionality with `port/linux` layers (used for modem host test suite) and implements `esp_netif`,
which supports `tun` interface and uses lwIP `ppp` implementation to parse or wrap IP packets to be send/receive
over PPPoS, i.e. over the modem serial line.
## Configuration
* Set path to the lwip and lwip_contrib repositories as environmental variables:
- `LWIP_PATH`: path to the lwip repository
- `LWIP_CONTRIB_PATH`: path to the lwip_contrib repository
* Create a `tun` interface using `make_tun_netif` script.
* Set SIO dev name directly in the code: This is the serial port which is the modem connected to
* (Set the tun device na interface name in the code: Not needed if the device was created using the script above.)
* Build and run the example (no elevated privileges needed)
* Experiment with the network, after getting the IP from the modem device
- directly in the code
- in the system (need to set `tun` interface IP, dns servers, and routing the desired traffic over the tun interface)

View File

@ -0,0 +1,9 @@
idf_component_register(SRCS "modem_main.cpp"
REQUIRES esp_modem)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
target_compile_definitions(${COMPONENT_LIB} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")

View File

@ -0,0 +1,58 @@
#include <memory>
#include <cassert>
#include <unistd.h>
#include <esp_log.h>
#include "cxx_include/esp_modem_terminal.hpp"
#include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_modem_config.h"
#include "esp_netif.h"
using namespace esp_modem;
[[maybe_unused]] static const char *TAG = "linux_modem_main";
#define CONFIG_EXAMPLE_SIM_PIN "1234"
int main()
{
// init the DTE
esp_modem_dte_config_t dte_config = {
.dte_buffer_size = 512,
.vfs_config = { }
};
dte_config.vfs_config.dev_name = "/dev/ttyUSB0";
esp_netif_config_t netif_config = {
.dev_name = "/dev/net/tun",
.if_name = "tun0"
};
esp_netif_t *tun_netif = esp_netif_new(&netif_config);
auto uart_dte = create_vfs_dte(&dte_config);
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("internet");
auto dce = create_SIM7600_dce(&dce_config, uart_dte, tun_netif);
assert(dce != nullptr);
dce->set_command_mode();
bool pin_ok = true;
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
throw_if_false(dce->set_pin(CONFIG_EXAMPLE_SIM_PIN) == command_result::OK, "Cannot set PIN!");
usleep(1000000);
}
std::string str;
dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
dce->get_imsi(str);
ESP_LOGI(TAG, "Modem IMSI number: %s",str.c_str());
dce->get_imei(str);
ESP_LOGI(TAG, "Modem IMEI number: %s",str.c_str());
dce->get_operator_name(str);
ESP_LOGI(TAG, "Operator name: %s",str.c_str());
dce->set_mode(esp_modem::modem_mode::DATA_MODE);
usleep(100'000'000);
esp_netif_destroy(tun_netif);
}

View File

@ -0,0 +1,3 @@
sudo ip tuntap add mode tun user `whoami`
sudo ip link set dev tun0 up
sudo ifconfig tun0 10.184.178.109 netmask 255.255.255.255 up

View File

@ -0,0 +1,5 @@
CONFIG_IDF_TARGET="linux"
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_COMPILER_CXX_RTTI=y
CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
CONFIG_COMPILER_STACK_CHECK_NONE=y

View File

@ -18,6 +18,7 @@
#include "cxx_include/esp_modem_api.hpp"
#include <iostream>
#include "esp_https_ota.h"
#include "esp_app_trace.h"
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
@ -149,7 +150,11 @@ extern "C" void app_main(void)
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
dte_config.dte_buffer_size = 512;
dte_config.uart_config.port_num = UART_NUM_2;
auto uart_dte = create_uart_dte(&dte_config);
// auto uart_dte = create_vfs_dte(&dte_config2);
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);

View File

@ -97,11 +97,11 @@ struct esp_modem_dte_config {
.rx_io_num = 26, \
.rts_io_num = 27, \
.cts_io_num = 23, \
.rx_buffer_size = 1024, \
.rx_buffer_size = 4096, \
.tx_buffer_size = 512, \
.event_queue_size = 30, \
.event_task_stack_size = 4096, \
.event_task_priority = 5, \
.event_task_priority = 20, \
} \
}

View File

@ -0,0 +1,21 @@
set(LWIP_DIR "$ENV{LWIP_PATH}")
set(LWIP_CONTRIB_DIR "$ENV{LWIP_CONTRIB_PATH}")
set(lwipcontribportunix_SRCS ${LWIP_CONTRIB_DIR}/ports/unix/port/sys_arch.c)
include(${LWIP_DIR}/src/Filelists.cmake)
set (LWIP_INCLUDE_DIRS
"${LWIP_DIR}/src/include"
"${LWIP_CONTRIB_DIR}/ports/unix/port/include")
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/netif/slipif.c")
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ip4.c")
list(REMOVE_ITEM lwipnoapps_SRCS "${LWIP_DIR}/src/core/ipv6/ip6.c")
idf_component_register(SRCS esp_netif_linux.cpp tun_io.c ip6_stub.c ${lwipnoapps_SRCS} ${lwipcontribportunix_SRCS}
INCLUDE_DIRS include ${LWIP_INCLUDE_DIRS}
PRIV_INCLUDE_DIRS .
REQUIRES esp_system_protocols_linux)

View File

@ -0,0 +1,136 @@
//
// 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 <thread>
#include <atomic>
#include <stdexcept>
#include <cstring>
#include <net/if.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/if_tun.h>
#include "esp_netif.h"
#include "esp_err.h"
#include "esp_log.h"
#define BUF_SIZE 1518
static const char *TAG = "esp_netif_linux";
extern "C" int ppp_netif_init(esp_netif_t *netif);
extern "C" int tun_read(void);
class NetifStorage;
void read_task(NetifStorage *netif);
class NetifStorage: public esp_netif_obj
{
public:
explicit NetifStorage(const esp_netif_config_t *config) : esp_netif_obj(), exit(false)
{
if ((fd = open(config->dev_name, O_RDWR)) == -1) {
ESP_LOGE(TAG, "Cannot open %s", config->dev_name);
throw std::runtime_error("Failed to open device");
}
struct ifreq ifr = { };
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, config->if_name, IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
ESP_LOGE(TAG, "Cannot set ioctl TUNSETIFF %m");
throw std::runtime_error("Failed to set tun device interface name");
}
ioctl(fd, TUNSETNOCSUM, 1);
in_buf = new uint8_t[BUF_SIZE];
out_buf = new uint8_t[BUF_SIZE];
if (!ppp_netif_init(this)) {
ESP_LOGE(TAG, "Cannot initialize pppos lwip netif %m");
throw std::runtime_error("Failed setup ppp interface");
}
task = std::thread(read_task, this);
}
~NetifStorage()
{
exit = true;
task.join();
close(fd);
delete[] in_buf;
delete[] out_buf;
}
std::thread task;
std::atomic<bool> exit;
static void read_task(NetifStorage *netif)
{
while (!netif->exit.load()) {
tun_read();
}
}
};
extern "C" esp_netif_t *esp_netif_new(const esp_netif_config_t *config)
{
return new NetifStorage(config);
// struct ifreq ifr = { };
// esp_netif_t * netif = netif_storage;
// if (netif == NULL) {
// return NULL;
// }
// if ((netif->fd = open(config->dev_name, O_RDWR)) == -1) {
// ESP_LOGE(TAG, "Cannot open %s", config->dev_name);
// goto cleanup;
// }
// ifr.ifr_flags = IFF_TUN;
// strncpy(ifr.ifr_name, config->if_name, IFNAMSIZ);
//
// if (ioctl(netif->fd, TUNSETIFF, (void *)&ifr) == -1) {
// ESP_LOGE(TAG, "Cannot set ioctl TUNSETIFF %m");
// goto cleanup;
// }
// ioctl(netif->fd, TUNSETNOCSUM, 1);
//
// netif->in_buf = new uint8_t[BUF_SIZE];
// netif->out_buf = new uint8_t[BUF_SIZE];
// if (netif->in_buf == nullptr || netif->out_buf == nullptr) {
// goto cleanup;
// }
//
// if (!ppp_netif_init(netif)) {
// ESP_LOGE(TAG, "Cannot initialize pppos lwip netif %m");
// goto cleanup;
// }
//
// return netif;
//
//cleanup:
// close(netif->fd);
// delete[] netif->in_buf;
// delete[] netif->out_buf;
// delete netif_storage;
// return nullptr;
}
void esp_netif_destroy(esp_netif_t *netif)
{
delete static_cast<NetifStorage*>(netif);
}

View File

@ -0,0 +1,67 @@
//
// 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.
#ifndef _HOST_ESP_NETIF_H_
#define _HOST_ESP_NETIF_H_
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "esp_netif_ip_addr.h"
#include "esp_err.h"
#include "esp_event_base.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct esp_netif_obj esp_netif_t;
typedef struct esp_netif_driver_base_s {
esp_err_t (*post_attach)(esp_netif_t *netif, void *h);
esp_netif_t *netif;
} esp_netif_driver_base_t;
struct esp_netif_driver_ifconfig {
void *handle;
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
esp_err_t (*transmit_wrap)(void *h, void *buffer, size_t len, void *netstack_buffer);
void (*driver_free_rx_buffer)(void *h, void *buffer);
};
struct esp_netif_config {
const char * dev_name; /**< Name of the file device */
const char * if_name; /**< Network interface name */
};
struct esp_netif_obj {
uint8_t *in_buf;
uint8_t *out_buf;
int fd;
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
void *ctx;
};
int esp_netif_receive(esp_netif_t *netif, uint8_t *data, size_t len);
typedef struct esp_netif_config esp_netif_config_t;
esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config);
void esp_netif_destroy(esp_netif_t *esp_netif);
#ifdef __cplusplus
}
#endif
#endif // _HOST_ESP_NETIF_H_

View File

@ -94,21 +94,7 @@ extern "C" {
#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4))
#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0)
#define IP_GET_TYPE(ipaddr) ((ipaddr)->type)
#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == ESP_IPADDR_TYPE_V6)
#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr)
#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \
(dest).addr[1] = (src).addr[1]; \
(dest).addr[2] = (src).addr[2]; \
(dest).addr[3] = (src).addr[3];}while(0)
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0)
#define IP_MULTICAST(a) IN_CLASSD(a)
#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & htonl(0xff000000UL)) == htonl(0xff000000UL))
#define IP6_NO_ZONE 0
#define ip6_addr_clear_zone(ip6addr) ((ip6addr)->zone = IP6_NO_ZONE)

View File

@ -0,0 +1,25 @@
#include "lwip/ip6.h"
err_t
ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
u8_t hl, u8_t tc,
u8_t nexth, struct netif *netif)
{ return ERR_OK; }
struct netif *
ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
{ return NULL; }
err_t
ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
u8_t hl, u8_t tc,
u8_t nexth, struct netif *netif)
{ return ERR_OK; }
const ip_addr_t *
ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
{ return NULL; }
err_t
ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
{ return ERR_OK; }

View File

@ -0,0 +1,347 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_LWIPOPTS_H
#define LWIP_LWIPOPTS_H
#ifdef LWIP_OPTTEST_FILE
#include "lwipopts_test.h"
#else /* LWIP_OPTTEST_FILE */
#define LWIP_IPV4 1
#define LWIP_IPV6 1
#define NO_SYS 0
#define LWIP_SOCKET (NO_SYS==0)
#define LWIP_NETCONN (NO_SYS==0)
#define LWIP_NETIF_API (NO_SYS==0)
#define LWIP_IGMP 0
#define LWIP_ICMP 0
#define LWIP_SNMP 0
#define MIB2_STATS 0
#ifdef LWIP_HAVE_MBEDTLS
#define LWIP_SNMP_V3 (LWIP_SNMP)
#endif
#define LWIP_DNS LWIP_UDP
#define LWIP_MDNS_RESPONDER 0
#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER)
#define LWIP_HAVE_LOOPIF 0
#define LWIP_NETIF_LOOPBACK 1
#define LWIP_LOOPBACK_MAX_PBUFS 10
#define TCP_LISTEN_BACKLOG 1
#define LWIP_COMPAT_SOCKETS 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_TCPIP_CORE_LOCKING 0
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
#define PPP_DEBUG LWIP_DBG_ON
#define LWIP_DEBUG LWIP_DBG_ON
#define PPP_IPV6_SUPPORT 0
#define PPP_NOTIFY_PHASE 1
#define PAP_SUPPORT 0
#define CHAP_SUPPORT 0
#define MSCHAP_SUPPORT 0
#define MPPE_SUPPORT 0
#define PPP_MAXIDLEFLAG 0
#define PRINTPKT_SUPPORT 1
#define PPP_PROTOCOLNAME 1
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define DNS_DEBUG LWIP_DBG_OFF
#define AUTOIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define IGMP_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
/* MSVC port: intel processors don't need 4-byte alignment,
but are faster that way! */
#define MEM_ALIGNMENT 4U
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 10240
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 16
/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
per active RAW "connection". */
#define MEMP_NUM_RAW_PCB 3
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 5
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 16
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 17
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 10
/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG_API 16
#define MEMP_NUM_TCPIP_MSG_INPKT 16
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 120
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 256
/** SYS_LIGHTWEIGHT_PROT
* define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
* for certain critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0)
/* ---------- TCP options ---------- */
#define LWIP_TCP 0
#define TCP_TTL 255
#define LWIP_ALTCP (LWIP_TCP)
#ifdef LWIP_HAVE_MBEDTLS
#define LWIP_ALTCP_TLS (LWIP_TCP)
#define LWIP_ALTCP_TLS_MBEDTLS (LWIP_TCP)
#endif
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 1
/* TCP Maximum segment size. */
#define TCP_MSS 1024
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 2048
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)
/* TCP writable space (bytes). This must be less than or equal
to TCP_SND_BUF. It is the amount of space which must be
available in the tcp snd_buf for select to return writable */
#define TCP_SNDLOWAT (TCP_SND_BUF/2)
/* TCP receive window. */
#define TCP_WND (20 * 1024)
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define LWIP_ARP 1
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 1
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 1
/* IP reassembly and segmentation.These are orthogonal even
* if they both deal with IP fragments */
#define IP_REASSEMBLY 1
#define IP_REASS_MAX_PBUFS (10 * ((1500 + PBUF_POOL_BUFSIZE - 1) / PBUF_POOL_BUFSIZE))
#define MEMP_NUM_REASSDATA IP_REASS_MAX_PBUFS
#define IP_FRAG 1
#define IPV6_FRAG_COPYHEADER 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. */
#define LWIP_DHCP LWIP_UDP
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
/* ---------- AUTOIP options ------- */
#define LWIP_AUTOIP (LWIP_DHCP)
#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP)
/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define LWIP_UDPLITE LWIP_UDP
#define UDP_TTL 255
/* ---------- RAW options ---------- */
#define LWIP_RAW 1
/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_STATS_DISPLAY 0
#if LWIP_STATS
#define LINK_STATS 1
#define IP_STATS 1
#define ICMP_STATS 1
#define IGMP_STATS 1
#define IPFRAG_STATS 1
#define UDP_STATS 1
#define TCP_STATS 1
#define MEM_STATS 1
#define MEMP_STATS 1
#define PBUF_STATS 1
#define SYS_STATS 1
#endif /* LWIP_STATS */
/* ---------- NETBIOS options ---------- */
#define LWIP_NETBIOS_RESPOND_NAME_QUERY 1
/* ---------- PPP options ---------- */
#define PPP_SUPPORT 1 /* Set > 0 for PPP */
#if PPP_SUPPORT
#define NUM_PPP 1 /* Max PPP sessions. */
/* Select modules to enable. Ideally these would be set in the makefile but
* we're limited by the command line length so you need to modify the settings
* in this file.
*/
#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP */
#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
#define CCP_SUPPORT 0 /* Set > 0 for CCP */
#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */
#endif /* PPP_SUPPORT */
#endif /* LWIP_OPTTEST_FILE */
/* The following defines must be done even in OPTTEST mode: */
#if !defined(NO_SYS) || !NO_SYS /* default is 0 */
void sys_check_core_locking(void);
#define LWIP_ASSERT_CORE_LOCKED() sys_check_core_locking()
void sys_mark_tcpip_thread(void);
#define LWIP_MARK_TCPIP_THREAD() sys_mark_tcpip_thread()
#if !defined(LWIP_TCPIP_CORE_LOCKING) || LWIP_TCPIP_CORE_LOCKING /* default is 1 */
void sys_lock_tcpip_core(void);
#define LOCK_TCPIP_CORE() sys_lock_tcpip_core()
void sys_unlock_tcpip_core(void);
#define UNLOCK_TCPIP_CORE() sys_unlock_tcpip_core()
#endif
#endif
#ifdef CONFIG_LWIP_DHCP_STATE_DEBUG
#define ESP_DHCP_DEBUG LWIP_DBG_ON
#else
#define ESP_DHCP_DEBUG LWIP_DBG_OFF
#endif
#define ESP_LWIP_SELECT 1
#endif /* LWIP_LWIPOPTS_H */

View File

@ -0,0 +1,209 @@
#include <string.h>
#include <unistd.h>
#include "netif/ppp/pppos.h"
#include "lwip/ip6.h"
#include "lwip/tcpip.h"
#include "netif/ppp/pppos.h"
#include "lwip/dns.h"
#include "esp_netif.h"
#define BUF_SIZE 1518
void ppp_init(void);
static const unsigned char ip6_header[4] = { 0, 0, 0x86, 0xdd }; // Ethernet (IPv6)
static const unsigned char ip4_header[4] = { 0, 0, 0x08, 0 }; // Ethernet (IPv4)
static esp_netif_t *esp_netif = NULL;
static struct netif pppos_netif;
static ppp_pcb *ppp;
static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
{
struct netif *pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch(err_code) {
case PPPERR_NONE: /* No error. */
{
#if LWIP_DNS
const ip_addr_t *ns;
#endif /* LWIP_DNS */
fprintf(stderr, "ppp_link_status_cb: PPPERR_NONE\n\r");
#if LWIP_IPV4
fprintf(stderr, " our_ip4addr = %s\n\r", ip4addr_ntoa(netif_ip4_addr(pppif)));
fprintf(stderr, " his_ipaddr = %s\n\r", ip4addr_ntoa(netif_ip4_gw(pppif)));
fprintf(stderr, " netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(pppif)));
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
fprintf(stderr, " our_ip6addr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif /* LWIP_IPV6 */
#if LWIP_DNS
ns = dns_getserver(0);
fprintf(stderr, " dns1 = %s\n\r", ipaddr_ntoa(ns));
ns = dns_getserver(1);
fprintf(stderr, " dns2 = %s\n\r", ipaddr_ntoa(ns));
#endif /* LWIP_DNS */
#if PPP_IPV6_SUPPORT
fprintf(stderr, " our6_ipaddr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif /* PPP_IPV6_SUPPORT */
}
break;
case PPPERR_PARAM: /* Invalid parameter. */
printf("ppp_link_status_cb: PPPERR_PARAM\n");
break;
case PPPERR_OPEN: /* Unable to open PPP session. */
printf("ppp_link_status_cb: PPPERR_OPEN\n");
break;
case PPPERR_DEVICE: /* Invalid I/O device for PPP. */
printf("ppp_link_status_cb: PPPERR_DEVICE\n");
break;
case PPPERR_ALLOC: /* Unable to allocate resources. */
printf("ppp_link_status_cb: PPPERR_ALLOC\n");
break;
case PPPERR_USER: /* User interrupt. */
printf("ppp_link_status_cb: PPPERR_USER\n");
break;
case PPPERR_CONNECT: /* Connection lost. */
printf("ppp_link_status_cb: PPPERR_CONNECT\n");
break;
case PPPERR_AUTHFAIL: /* Failed authentication challenge. */
printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n");
break;
case PPPERR_PROTOCOL: /* Failed to meet protocol. */
printf("ppp_link_status_cb: PPPERR_PROTOCOL\n");
break;
case PPPERR_PEERDEAD: /* Connection timeout. */
printf("ppp_link_status_cb: PPPERR_PEERDEAD\n");
break;
case PPPERR_IDLETIMEOUT: /* Idle Timeout. */
printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n");
break;
case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */
printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n");
break;
case PPPERR_LOOPBACK: /* Connection timeout. */
printf("ppp_link_status_cb: PPPERR_LOOPBACK\n");
break;
default:
printf("ppp_link_status_cb: unknown errCode %d\n", err_code);
break;
}
}
static u32_t ppp_output_cb(struct ppp_pcb_s *pcb, const void *data, u32_t len, void *ctx)
{
esp_netif_t *netif = (esp_netif_t *)ctx;
if (netif->transmit)
return netif->transmit(netif->ctx, (uint8_t*)data, len);
return 0;
}
int esp_netif_receive(esp_netif_t *netif, uint8_t *data, size_t len)
{
pppos_input(ppp, data, len);
return 1;
}
int ppp_netif_init(esp_netif_t *netif)
{
// Init necessary units of lwip (no need for the tcpip thread)
sys_init();
mem_init();
memp_init();
netif_init();
dns_init();
ppp_init();
sys_timeouts_init();
// init and start connection attempts on PPP interface
ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, (void*)netif);
if (ppp == NULL) {
return 0;
}
ppp_connect(ppp, 0);
ppp_set_usepeerdns(ppp, 1);
esp_netif = netif;
return 1;
}
static err_t tun_input(struct pbuf *p, const unsigned char tun_header[4])
{
struct pbuf *n;
size_t offset = 4;
memcpy(esp_netif->in_buf, tun_header, offset);
for (n = p; n; n = n->next) {
memcpy(esp_netif->in_buf + offset, n->payload, n->len);
offset += n->len;
}
if (write(esp_netif->fd, esp_netif->in_buf, offset) != offset) {
pbuf_free(p);
return ERR_ABRT;
}
pbuf_free(p);
return ERR_OK;
}
err_t ip6_input(struct pbuf *p, struct netif *inp)
{
return tun_input(p, ip6_header);
}
err_t ip4_input(struct pbuf *p, struct netif *inp)
{
return tun_input(p, ip4_header);
}
int tun_read(void)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(esp_netif->fd, &fds);
struct timeval tv = { .tv_usec = 0, .tv_sec = 1 };
if (select(esp_netif->fd +1, &fds, NULL, NULL, &tv) <= 0) {
sys_check_timeouts();
return 0;
}
struct pbuf *p;
ssize_t len = read(esp_netif->fd, esp_netif->out_buf, BUF_SIZE);
if (len < 0) {
perror("read returned -1");
return -1;
}
if (len <= 4) {
return -1;
}
len -= 4;
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p == NULL) {
perror("Cannot allocate pbuf");
return -1;
}
pbuf_take(p, esp_netif->out_buf + 4, len);
if (memcmp(esp_netif->out_buf, ip6_header, 4) == 0) {
pppos_netif.output_ip6(&pppos_netif, p, NULL);
} else if (memcmp(esp_netif->out_buf, ip4_header, 4) == 0) {
pppos_netif.output(&pppos_netif, p, NULL);
} else {
printf("Unknown protocol %x %x\n", esp_netif->out_buf[2], esp_netif->out_buf[3]);
}
pbuf_free(p);
return 1;
}

View File

@ -0,0 +1,49 @@
//
// 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.
#ifndef MDNS_HOST_ESP_LOG_H
#define MDNS_HOST_ESP_LOG_H
#include <stdio.h>
#define ESP_LOG_INFO 1
#define ESP_LOG_BUFFER_HEXDUMP(...)
#define LOG_COLOR_BLACK "30"
#define LOG_COLOR_RED "31"
#define LOG_COLOR_GREEN "32"
#define LOG_COLOR_BROWN "33"
#define LOG_COLOR_BLUE "34"
#define LOG_COLOR_PURPLE "35"
#define LOG_COLOR_CYAN "36"
#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
#define LOG_RESET_COLOR "\033[0m"
#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) "E"
#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) "W"
#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) "I"
#define LOG_COLOR_D LOG_COLOR(LOG_COLOR_CYAN) "D"
#define LOG_COLOR_V "V"
#define ESP_LOGE(TAG, ...) do { \
printf(LOG_COLOR_E); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
#define ESP_LOGW(TAG, ...) do { \
printf(LOG_COLOR_W); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
#define ESP_LOGI(TAG, ...) do { \
printf(LOG_COLOR_I); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
#define ESP_LOGD(TAG, ...) do { \
printf(LOG_COLOR_D); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
#define ESP_LOGV(TAG, ...) do { \
printf(LOG_COLOR_V); printf("(%s) ", TAG); printf(__VA_ARGS__); printf(LOG_RESET_COLOR "\n"); } while(0)
#endif //MDNS_HOST_ESP_LOG_H

View File

@ -23,7 +23,7 @@
return nullptr; \
} catch (esp_err_exception& e) { \
esp_err_t err = e.get_err_t(); \
ESP_LOGE(TAG, "Error occurred during UART term init: %d", err); \
ESP_LOGE(TAG, "%s: Exception caught with ESP err_code=%d", __func__, err); \
ESP_LOGE(TAG, "%s", e.what()); \
return nullptr; \
}

View File

@ -15,7 +15,7 @@
#include <cstring>
#include <unistd.h>
#include <cxx_include/esp_modem_cmux.hpp>
//#include "esp_app_trace.h"
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_log.h"
@ -90,13 +90,13 @@ void CMux::data_available(uint8_t *data, size_t len)
if (data && type == 0xFF && len > 0 && dlci > 0) {
int virtual_term = dlci - 1;
if (virtual_term < max_terms && read_cb[virtual_term]) {
if (payload_start == nullptr) {
payload_start = data;
total_payload_size = 0;
}
total_payload_size += len;
// if (payload_start == nullptr) {
// payload_start = data;
// total_payload_size = 0;
// }
// total_payload_size += len;
// Post partial data (if configured)
// read_cb[virtual_term](payload_start, total_payload_size);
read_cb[virtual_term](data, len);
}
} else if (data == nullptr && type == 0x73 && len == 0) { // notify the initial SABM command
@ -105,7 +105,7 @@ void CMux::data_available(uint8_t *data, size_t len)
} else if (data == nullptr) {
int virtual_term = dlci - 1;
if (virtual_term < max_terms && read_cb[virtual_term]) {
read_cb[virtual_term](payload_start, total_payload_size);
// read_cb[virtual_term](payload_start, total_payload_size);
}
}
@ -124,10 +124,24 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
actual_len = term->read(data, data_to_read);
// ESP_LOGE("Received", "data_to_read=%d, actual_len=%d, total_payload=%d", data_to_read, actual_len, total_payload_size);
}
printf("my_data[%d] = { ", actual_len);
#if 0
if (0){
static char buf[8*1024];
for (int i=0; i<actual_len; ++i)
printf("0x%02x, ", data[i]);
printf("};\n");
sprintf(buf + 6*i, "0x%02x, ", data[i]);
buf[actual_len*6] = '\n';
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, buf, actual_len*6+1, ESP_APPTRACE_TMO_INFINITE);
if (res != ESP_OK) {
ESP_LOGE("cmux", "Failed to write data to host!");
}
esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, 1000);
// usleep(1000000);
}
#endif
// printf("my_data[%d] = { ", actual_len);
// for (int i=0; i<actual_len; ++i)
// printf("0x%02x, ", data[i]);
// printf("};\n");
// ESP_LOG_BUFFER_HEXDUMP("Received", data, actual_len, ESP_LOG_INFO);
uint8_t* frame = data;
uint8_t* recover_ptr;
@ -175,12 +189,12 @@ bool CMux::on_cmux(uint8_t *data, size_t actual_len)
frame++;
break;
case cmux_state::HEADER:
// if (available_len > 0 && frame_header_offset == 1 && frame[0] == SOF_MARKER) {
// // Previously trailing SOF interpreted as heading SOF, remove it and restart HEADER
// available_len--;
// frame++;
// break;
// }
if (available_len > 0 && frame_header_offset == 1 && frame[0] == SOF_MARKER) {
// Previously trailing SOF interpreted as heading SOF, remove it and restart HEADER
available_len--;
frame++;
break;
}
if (available_len + frame_header_offset < 4) {
memcpy(frame_header + frame_header_offset, frame, available_len);
frame_header_offset += available_len;

View File

@ -44,6 +44,8 @@ command_result DTE::command(const std::string &command, got_line_cb got_line, ui
} else {
consumed = 0;
}
// ESP_LOGD("CMD_read!", "-----");
// for (int i=0; i<len; i++) ESP_LOGV("CMD_read", "%02x",data[i] );
if (memchr(data + consumed, separator, len)) {
res = got_line(data, consumed + len);
if (res == command_result::OK || res == command_result::FAIL) {

View File

@ -12,7 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <thread>
#include "cxx_include/esp_modem_netif.hpp"
#include "cxx_include/esp_modem_dte.hpp"
namespace esp_modem {
@ -20,29 +22,39 @@ void Netif::on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) {
}
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len) {
return ESP_OK;
esp_err_t Netif::esp_modem_dte_transmit(void *h, void *buffer, size_t len)
{
auto *this_netif = static_cast<Netif *>(h);
this_netif->ppp_dte->write((uint8_t *) buffer, len);
return len;
}
esp_err_t Netif::esp_modem_post_attach(esp_netif_t *esp_netif, void *args) {
return ESP_OK;
}
void Netif::receive(uint8_t *data, size_t len) {
void Netif::receive(uint8_t *data, size_t len)
{
esp_netif_receive(netif, data, len);
}
Netif::Netif(std::shared_ptr<DTE> e, esp_netif_t *ppp_netif) :
ppp_dte(std::move(e)), netif(ppp_netif) {
ppp_dte(std::move(e)), netif(ppp_netif) {}
void Netif::start()
{
ppp_dte->set_read_cb([this](uint8_t *data, size_t len) -> bool {
receive(data, len);
return false;
});
netif->transmit = esp_modem_dte_transmit;
netif->ctx = (void*)this;
signal.set(PPP_STARTED);
}
void Netif::start() {
}
void Netif::stop() {}
void Netif::stop() {
}
Netif::~Netif() {
}
Netif::~Netif() = default;
void Netif::wait_until_ppp_exits() {

View File

@ -33,12 +33,14 @@ void SignalGroup::set(uint32_t bits)
{
std::unique_lock<std::mutex> lock(event_group->m);
event_group->flags |= bits;
event_group->notify.notify_all();
}
void SignalGroup::clear(uint32_t bits)
{
std::unique_lock<std::mutex> lock(event_group->m);
event_group->flags &= ~bits;
event_group->notify.notify_all();
}
bool SignalGroup::wait(uint32_t flags, uint32_t time_ms)
@ -71,12 +73,12 @@ SignalGroup::~SignalGroup() = default;
Task::Task(size_t stack_size, size_t priority, void *task_param, TaskFunction_t task_function)
{
#warning "Define this for linux"
task_handle = std::thread(task_function, task_param);
}
Task::~Task()
{
task_handle.join();
}
void Task::Delete() {}

View File

@ -32,6 +32,7 @@ struct uart_resource {
};
class vfs_terminal : public Terminal {
public:
explicit vfs_terminal(const esp_modem_dte_config *config) :
@ -42,14 +43,16 @@ public:
Task::Delete();
}) {}
~vfs_terminal() override = default;
~vfs_terminal() override {
stop();
}
void start() override {
signal.set(TASK_START);
}
void stop() override {
signal.set(TASK_STOP);
signal.clear(TASK_START);
}
int write(uint8_t *data, size_t len) override;
@ -98,7 +101,7 @@ void vfs_terminal::task() {
int s;
fd_set rfds;
struct timeval tv = {
.tv_sec = 5,
.tv_sec = 1,
.tv_usec = 0,
};
FD_ZERO(&rfds);
@ -113,9 +116,10 @@ void vfs_terminal::task() {
if (s < 0) {
break;
} else if (s == 0) {
// ESP_LOGV(TAG, "Select exitted with timeout");
} else {
if (FD_ISSET(uart.fd, &rfds)) {
// ESP_LOGV(TAG, "FD is readable");
// uart_get_buffered_data_len(uart.port, &len);
if (on_data_priv) {
if (on_data_priv(nullptr, 0)) {
@ -131,13 +135,19 @@ void vfs_terminal::task() {
int vfs_terminal::read(uint8_t *data, size_t len)
{
int size = ::read(uart.fd, data, len);
// if (size < 0 && errno == EWOULDBLOCK)
// return 0;
// for (int i=0; i<size; i++) ESP_LOGD(TAG, "Read: %02x",data[i] );
if (size < 0) {
ESP_LOGE(TAG, "Error occurred during read: %d", errno);
return 0;
}
return size;
}
int vfs_terminal::write(uint8_t *data, size_t len)
{
// for (int i=0; i<len; i++) ESP_LOGD(TAG, "%02x",data[i] );
return ::write(uart.fd, data, len);
}

View File

@ -78,7 +78,7 @@ uart_resource::uart_resource(const esp_modem_dte_config *config) :
uart_config.stop_bits = config->uart_config.stop_bits;
uart_config.flow_ctrl = (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
: UART_HW_FLOWCTRL_DISABLE;
uart_config.source_clk = UART_SCLK_REF_TICK;
uart_config.source_clk = UART_SCLK_APB;
throw_if_esp_fail(uart_param_config(config->uart_config.port_num, &uart_config), "config uart parameter failed");
@ -224,11 +224,11 @@ void uart_terminal::task() {
int uart_terminal::read(uint8_t *data, size_t len) {
size_t length = 0;
uart_get_buffered_data_len(uart.port, &length);
// if (esp_random() < UINT32_MAX/4 && length > 32) {
// printf("ahoj!\n");
// length = length - length/2;
// }
// size_t new_size = length/2;
if (esp_random() < UINT32_MAX/4 && length > 32) {
printf("ahoj!\n");
length -= length/4;
}
size_t new_size = length/2;
length = std::min(len, length);
if (length > 0) {
return uart_read_bytes(uart.port, data, length, portMAX_DELAY);

View File

@ -13,3 +13,63 @@
// limitations under the License.
#include "cxx_include/esp_modem_dte.hpp"
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_log.h"
#include "driver/uart.h"
#include "esp_modem_config.h"
#include "exception_stub.hpp"
namespace esp_modem::terminal {
constexpr const char *TAG = "uart_term";
struct uart_resource {
explicit uart_resource(const esp_modem_dte_config *config);
~uart_resource();
uart_port_t port{};
int fd;
};
uart_resource::uart_resource(const esp_modem_dte_config *config)
{
ESP_LOGD(TAG, "Creating uart resource" );
struct termios tty = {};
fd = open( config->vfs_config.dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK );
throw_if_false(fd >= 0 , "Failed to open serial port");
throw_if_false(tcgetattr(fd, &tty) == 0, "Failed to tcgetattr()");
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE; // Clear all the size bits, then use one of the statements below
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 0;
cfsetispeed(&tty, B115200);
cfsetospeed(&tty, B115200);
cfsetspeed(&tty, B115200);
ioctl(fd, TCSETS, &tty);
}
uart_resource::~uart_resource()
{
close(fd);
}
}

View File

@ -2,15 +2,14 @@ cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS ../..)
set(EXTRA_COMPONENT_DIRS # Add esp_modem component and linux port components
../..
../../port/linux)
set(COMPONENTS main)
project(host_modem_test)
idf_component_get_property(esp_modem esp_modem COMPONENT_LIB)
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_COMPILER_CXX_EXCEPTIONS")
target_compile_definitions(${esp_modem} PRIVATE "-DCONFIG_IDF_TARGET_LINUX")
target_link_options(${esp_modem} INTERFACE -fsanitize=address)
#set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
#set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

View File

@ -0,0 +1,5 @@
# Host test for esp_modem
This test uses linux port and some idf mocks in order to compile and execute it under linux.
This test uses `catch` as a test framework and implements a test terminal class `LoopbackTerm`

View File

@ -1,3 +0,0 @@
idf_component_register(SRCS esp_netif_linux.c
INCLUDE_DIRS include
REQUIRES esp_system_protocols_linux)

View File

@ -1,69 +0,0 @@
//
// 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<stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#include "esp_netif.h"
#include "esp_err.h"
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
{
return NULL;
}
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
{
ESP_IPADDR4_INIT(&ip_info->ip, 1,2,3,4);
return ESP_OK;
}
esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status)
{
return ESP_OK;
}
esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6)
{
struct ifaddrs *addrs, *tmp;
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) {
char addr[64];
struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;
inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) );
printf("%s: %s\n", tmp->ifa_name, addr);
inet6_addr_to_ip6addr(if_ip6, &pAddr->sin6_addr);
}
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
return ESP_OK;
}
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
{
char * ifname = "enp1s0";
uint32_t interfaceIndex = if_nametoindex(ifname);
printf("%s: %d\n", ifname, interfaceIndex);
return interfaceIndex;
}

View File

@ -1,60 +0,0 @@
//
// 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.
#ifndef _HOST_ESP_NETIF_H_
#define _HOST_ESP_NETIF_H_
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "esp_netif_ip_addr.h"
#include "esp_err.h"
#include "esp_event_base.h"
struct esp_netif_obj {};
typedef struct esp_netif_obj esp_netif_t;
typedef struct esp_netif_driver_base_s {
esp_err_t (*post_attach)(esp_netif_t *netif, void* h);
esp_netif_t *netif;
} esp_netif_driver_base_t;
struct esp_netif_driver_ifconfig {
void* handle;
esp_err_t (*transmit)(void *h, void *buffer, size_t len);
esp_err_t (*transmit_wrap)(void *h, void *buffer, size_t len, void *netstack_buffer);
void (*driver_free_rx_buffer)(void *h, void* buffer);
};
/** @brief Status of DHCP client or DHCP server */
typedef enum {
ESP_NETIF_DHCP_INIT = 0, /**< DHCP client/server is in initial state (not yet started) */
ESP_NETIF_DHCP_STARTED, /**< DHCP client/server has been started */
ESP_NETIF_DHCP_STOPPED, /**< DHCP client/server has been stopped */
ESP_NETIF_DHCP_STATUS_MAX
} esp_netif_dhcp_status_t;
esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key);
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info);
esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status);
esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6);
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif);
void esp_netif_action_connected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
void esp_netif_action_disconnected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
#endif // _HOST_ESP_NETIF_H_

View File

@ -1,31 +0,0 @@
//
// 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.
#ifndef MDNS_HOST_ESP_LOG_H
#define MDNS_HOST_ESP_LOG_H
#include <stdio.h>
#define ESP_LOG_INFO 1
#define ESP_LOG_BUFFER_HEXDUMP(...)
#define ESP_LOGE(TAG, ...)
//printf(TAG); printf("ERROR: " __VA_ARGS__); printf("\n")
#define ESP_LOGW(TAG, ...)
//printf(TAG); printf("WARN: "__VA_ARGS__); printf("\n")
#define ESP_LOGI(TAG, ...)
//printf(TAG); printf("INFO: "__VA_ARGS__); printf("\n")
#define ESP_LOGD(TAG, ...)
//printf(TAG); printf("DEBUG: "__VA_ARGS__); printf("\n")
#endif //MDNS_HOST_ESP_LOG_H

View File

@ -1,135 +0,0 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
//#include <i86.h>
//#include <conio.h>
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 ) /* This can be made smaller if required. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 1
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 1
#define configUSE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 0 /* Do not use this option on the PC port. */
#define configUSE_APPLICATION_TASK_TAG 1
#define configQUEUE_REGISTRY_SIZE 0
#define configMAX_PRIORITIES ( 10 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* Do not use this option on the PC port. */
/* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human
readable ASCII form. See the notes in the implementation of vTaskList() within
FreeRTOS/Source/tasks.c for limitations. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* An example "task switched in" hook macro definition. */
#define traceTASK_SWITCHED_IN() xTaskCallApplicationTaskHook( NULL, ( void * ) 0xabcd )
extern void vMainQueueSendPassed( void );
#define traceQUEUE_SEND( pxQueue ) vMainQueueSendPassed()
#define IRAM_ATTR
#endif /* FREERTOS_CONFIG_H */

View File

@ -1,311 +0,0 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <limits.h>
//#include "sdkconfig.h"
//#include "esp_attr.h"
//#include "esp_heap_caps.h"
//#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
//#include "soc/soc_memory_layout.h"
//#endif
//#include "soc/spinlock.h"
//#include "soc/interrupt_core0_reg.h"
//#include "esp_rom_sys.h"
//#include "soc/cpu.h"
//#include "esp_system.h"
//#include "esp_newlib.h"
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR uint8_t
#define portFLOAT float
#define portDOUBLE double
#define portLONG int32_t
#define portSHORT int16_t
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE int
// interrupt module will mask interrupt with priority less than threshold
#define RVHAL_EXCM_LEVEL 4
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) (1000 / configTICK_RATE_HZ) )
#define portBYTE_ALIGNMENT 16
/*-----------------------------------------------------------*/
//#include "portbenchmark.h"
//static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) {
//return cpu_hal_get_core_id();
//}
//static inline bool IRAM_ATTR xPortCanYield(void)
//{
//uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
/* when enter critical code, freertos will mask threshold to RVHAL_EXCM_LEVEL
* and exit critical code, will recover threshold value (1). so threshold <= 1
* means not in critical code
*/
//return (threshold <= 1);
//}
//static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
//{
//#if defined(CONFIG_SPIRAM)
//compare_and_set_extram(addr, compare, set);
//#endif
//}
//static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
//compare_and_set_native(addr, compare, set);
//}
#define portCRITICAL_NESTING_IN_TCB 0
/*
* Send an interrupt to another core in order to make the task running
* on it yield for a higher-priority task.
*/
void vPortYieldOtherCore( BaseType_t coreid);
/*
Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
watchpoint around.
*/
void vPortSetStackWatchpoint( void* pxStackStart );
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*/
BaseType_t xPortInIsrContext(void);
/*
* This function will be called in High prio ISRs. Returns true if the current core was in ISR context
* before calling into high prio ISR context.
*/
BaseType_t xPortInterruptedFromISRContext(void);
/* "mux" data structure (spinlock) */
typedef struct {
/* owner field values:
* 0 - Uninitialized (invalid)
* portMUX_FREE_VAL - Mux is free, can be locked by either CPU
* CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core
*
*
* Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption
*/
uint32_t owner;
/* count field:
* If mux is unlocked, count should be zero.
* If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
*/
uint32_t count;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn;
int lastLockedLine;
#endif
} portMUX_TYPE;
#define portMUX_FREE_VAL SPINLOCK_FREE
/* Special constants for vPortCPUAcquireMutexTimeout() */
#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /* When passed for 'timeout_cycles', spin forever if necessary */
#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /* Try to acquire the spinlock a single time only */
// Keep this in sync with the portMUX_TYPE struct definition please.
#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
#define portMUX_INITIALIZER_UNLOCKED { \
.owner = portMUX_FREE_VAL, \
.count = 0, \
}
#else
#define portMUX_INITIALIZER_UNLOCKED { \
.owner = portMUX_FREE_VAL, \
.count = 0, \
.lastLockedFn = "(never locked)", \
.lastLockedLine = -1 \
}
#endif
/* Scheduler utilities. */
extern void vPortYield( void );
extern void vPortYieldFromISR( void );
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
until interrupts are re-enabled.
To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This
is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is
happening on the same CPU.
*/
#define portYIELD_WITHIN_API() portYIELD()
/*-----------------------------------------------------------*/
/* Critical section management. */
extern int vPortSetInterruptMask(void);
extern void vPortClearInterruptMask( int );
void vPortCPUInitializeMutex(portMUX_TYPE *mux);
void vPortCPUAcquireMutex(portMUX_TYPE *mux);
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
void vPortCPUReleaseMutex(portMUX_TYPE *mux);
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
/*
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK_FROM_ISR()
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK_FROM_ISR(1)
#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();}
#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();}
#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux)
#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux)
#define portENTER_CRITICAL_SAFE(mux) do { \
if (xPortInIsrContext()) { \
portENTER_CRITICAL_ISR(mux); \
} else { \
portENTER_CRITICAL(mux); \
} \
} while(0)
#define portEXIT_CRITICAL_SAFE(mux) do { \
if (xPortInIsrContext()) { \
portEXIT_CRITICAL_ISR(mux); \
} else { \
portEXIT_CRITICAL(mux); \
} \
} while(0)
*/
//[>------------------------------------------------------------<]
//#define portSET_INTERRUPT_MASK_FROM_ISR() vPortSetInterruptMask()
//#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue )
//#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()
// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
//static inline unsigned portENTER_CRITICAL_NESTED(void) {
//unsigned state = portSET_INTERRUPT_MASK_FROM_ISR();
//return state;
//}
//#define portEXIT_CRITICAL_NESTED(state) do { portCLEAR_INTERRUPT_MASK_FROM_ISR( state );} while(0);
/*-----------------------------------------------------------*/
//Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force
//the stack memory to always be internal.
//#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
//#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
//#define pvPortMallocTcbMem(size) pvPortMalloc(size)
//#define pvPortMallocStackMem(size) pvPortMalloc(size)
//[> Fine resolution time <]
//#define portGET_RUN_TIME_COUNTER_VALUE() 0
//#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
//#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
//[> Coarse resolution time (us) <]
//#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do{(void)x; }while(0)
//#endif
extern void esp_vApplicationIdleHook( void );
extern void esp_vApplicationTickHook( void );
#ifndef CONFIG_FREERTOS_LEGACY_HOOKS
#define vApplicationIdleHook esp_vApplicationIdleHook
#define vApplicationTickHook esp_vApplicationTickHook
#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
void vApplicationSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
#define portNOP() //__asm volatile ( " nop " )
#define portVALID_TCB_MEM(ptr)// esp_ptr_byte_accessible(ptr)
#define portVALID_STACK_MEM(ptr)// esp_ptr_byte_accessible(ptr)
// configASSERT_2 if requested
//#if configASSERT_2
//#include <stdio.h>
//void exit(int);
//#define configASSERT( x ) if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); }
//#endif
#endif //__ASSEMBLER__
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */