提交 e383a112 编写于 作者: M me-no-dev

Add Server and UDP and fix WiFi.hostByName

上级 f6d48436
......@@ -34,6 +34,8 @@
#include "WiFiGeneric.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "WiFiUdp.h"
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass
{
......@@ -55,6 +57,8 @@ public:
public:
void printDiag(Print& dest);
friend class WiFiClient;
friend class WiFiServer;
friend class WiFiUDP;
};
extern WiFiClass WiFi;
......
......@@ -304,7 +304,21 @@ bool WiFiGenericClass::enableAP(bool enable)
// ------------------------------------------------ Generic Network function ---------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
static bool _dns_busy = false;
/**
* DNS callback
* @param name
* @param ipaddr
* @param callback_arg
*/
static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
{
if(ipaddr) {
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->u_addr.ip4.addr;
}
_dns_busy = false;
}
/**
* Resolve the given hostname to an IP address.
......@@ -313,36 +327,24 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
* @return 1 if aIPAddrString was successfully converted to an IP address,
* else error code
*/
static bool _dns_busy = false;
int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult)
{
ip_addr_t addr;
aResult = static_cast<uint32_t>(0);
_dns_busy = true;
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
_dns_busy = err == ERR_INPROGRESS;
while(_dns_busy);
if(err == ERR_INPROGRESS && aResult) {
//found by search
} else if(err == ERR_OK && addr.u_addr.ip4.addr) {
if(err == ERR_OK && addr.u_addr.ip4.addr) {
aResult = addr.u_addr.ip4.addr;
_dns_busy = false;
} else if(err == ERR_INPROGRESS) {
while(_dns_busy){
delay(1);
}
} else {
_dns_busy = false;
return 0;
}
return 1;
}
/**
* DNS callback
* @param name
* @param ipaddr
* @param callback_arg
*/
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
{
if(ipaddr) {
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->u_addr.ip4.addr;
}
_dns_busy = false;
}
/*
Server.cpp - Server class for Raspberry Pi
Copyright (c) 2016 Hristo Gochkov All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "WiFiServer.h"
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#undef write
int WiFiServer::setTimeout(uint32_t seconds){
struct timeval tv;
tv.tv_sec = seconds;
tv.tv_usec = 0;
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0)
return -1;
return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
}
size_t WiFiServer::write(const uint8_t *data, size_t len){
return 0;
}
void WiFiServer::stopAll(){}
WiFiClient WiFiServer::available(){
if(!_listening)
return WiFiClient();
struct sockaddr_in _client;
int cs = sizeof(struct sockaddr_in);
int client_sock = accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs);
if(client_sock >= 0){
int val = 1;
if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK)
return WiFiClient(client_sock);
}
return WiFiClient();
}
void WiFiServer::begin(){
if(_listening)
return;
struct sockaddr_in server;
sockfd = socket(AF_INET , SOCK_STREAM, 0);
if (sockfd < 0)
return;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(_port);
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
return;
if(listen(sockfd , _max_clients) < 0)
return;
fcntl(sockfd, F_SETFL, O_NONBLOCK);
_listening = true;
}
void WiFiServer::end(){
close(sockfd);
sockfd = -1;
_listening = false;
}
/*
Server.h - Server class for Raspberry Pi
Copyright (c) 2016 Hristo Gochkov All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _WIFISERVER_H_
#define _WIFISERVER_H_
#include "Arduino.h"
#include "Server.h"
#include "WiFiClient.h"
class WiFiServer : public Server {
private:
int sockfd;
uint16_t _port;
uint8_t _max_clients;
bool _listening;
public:
void listenOnLocalhost(){}
WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_port(port),_max_clients(max_clients),_listening(false){}
~WiFiServer(){ end();}
WiFiClient available();
WiFiClient accept(){return available();}
void begin();
size_t write(const uint8_t *data, size_t len);
size_t write(uint8_t data){
return write(&data, 1);
}
using Print::write;
void end();
operator bool(){return _listening;}
int setTimeout(uint32_t seconds);
void stopAll();
};
#endif /* _WIFISERVER_H_ */
/*
Udp.cpp - UDP class for Raspberry Pi
Copyright (c) 2016 Hristo Gochkov All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "WiFiUdp.h"
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <errno.h>
#undef write
#undef read
WiFiUDP::WiFiUDP()
: udp_server(-1)
, server_port(0)
, remote_port(0)
, tx_buffer(0)
, tx_buffer_len(0)
, rx_buffer(0)
{}
WiFiUDP::~WiFiUDP(){
stop();
}
uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){
stop();
server_port = port;
tx_buffer = new char[1460];
if(!tx_buffer){
log_e("could not create tx buffer: %d", errno);
return 0;
}
if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){
log_e("could not create socket: %d", errno);
return 0;
}
int yes = 1;
if (setsockopt(udp_server,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
log_e("could not set socket option: %d", errno);
stop();
return 0;
}
struct sockaddr_in addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(server_port);
addr.sin_addr.s_addr = (in_addr_t)address;
if(bind(udp_server , (struct sockaddr*)&addr, sizeof(addr)) == -1){
log_e("could not bind socket: %d", errno);
stop();
return 0;
}
fcntl(udp_server, F_SETFL, O_NONBLOCK);
return 1;
}
uint8_t WiFiUDP::begin(uint16_t p){
return begin(IPAddress(INADDR_ANY), p);
}
uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){
if(begin(IPAddress(INADDR_ANY), p)){
if(a != 0){
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = (in_addr_t)a;
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
log_e("could not join igmp: %d", errno);
stop();
return 0;
}
multicast_ip = a;
}
return 1;
}
return 0;
}
void WiFiUDP::stop(){
if(tx_buffer){
delete[] tx_buffer;
}
tx_buffer_len = 0;
if(rx_buffer){
cbuf *b = rx_buffer;
rx_buffer = NULL;
delete b;
}
if(udp_server == -1)
return;
if(multicast_ip != 0){
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip;
mreq.imr_interface.s_addr = (in_addr_t)0;
setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
multicast_ip = IPAddress(INADDR_ANY);
}
close(udp_server);
udp_server = -1;
}
int WiFiUDP::beginMulticastPacket(){
if(!server_port || multicast_ip == IPAddress(INADDR_ANY))
return 0;
remote_ip = server_port;
remote_port = multicast_ip;
return beginPacket();
}
int WiFiUDP::beginPacket(){
if(!remote_port)
return 0;
tx_buffer_len = 0;
return 1;
}
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port){
remote_ip = ip;
remote_port = port;
return beginPacket();
}
int WiFiUDP::beginPacket(const char *host, uint16_t port){
struct hostent *server;
server = gethostbyname(host);
if (server == NULL){
log_e("could not get host from dns: %d", errno);
return 0;
}
return beginPacket(IPAddress((const uint8_t *)(server->h_addr_list[0])), port);
}
int WiFiUDP::endPacket(){
struct sockaddr_in recipient;
recipient.sin_addr.s_addr = (uint32_t)remote_ip;
recipient.sin_family = AF_INET;
recipient.sin_port = htons(remote_port);
int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient));
if(sent < 0){
log_e("could not send data: %d", errno);
}
return sent;
}
size_t WiFiUDP::write(uint8_t data){
if(tx_buffer_len == 1460){
endPacket();
tx_buffer_len = 0;
}
tx_buffer[tx_buffer_len++] = data;
return 1;
}
size_t WiFiUDP::write(const uint8_t *buffer, size_t size){
size_t i;
for(i=0;i<size;i++)
write(buffer[i]);
return i;
}
int WiFiUDP::parsePacket(){
if(rx_buffer)
return 0;
struct sockaddr_in si_other;
int slen = sizeof(si_other) , len;
char * buf = new char[1460];
if(!buf){
return 0;
}
if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){
delete[] buf;
if(errno == EWOULDBLOCK){
return 0;
}
log_e("could not receive data: %d", errno);
return 0;
}
remote_ip = IPAddress(si_other.sin_addr.s_addr);
remote_port = ntohs(si_other.sin_port);
rx_buffer = new cbuf(len);
rx_buffer->write(buf, len);
delete[] buf;
return len;
}
int WiFiUDP::available(){
if(!rx_buffer) return 0;
return rx_buffer->size();
}
int WiFiUDP::read(){
if(!rx_buffer) return -1;
int out = rx_buffer->read();
if(!rx_buffer->size()){
cbuf *b = rx_buffer;
rx_buffer = 0;
delete b;
}
return out;
}
int WiFiUDP::read(unsigned char* buffer, size_t len){
return read((char *)buffer, len);
}
int WiFiUDP::read(char* buffer, size_t len){
if(!rx_buffer) return 0;
int out = rx_buffer->read(buffer, len);
if(!rx_buffer->size()){
cbuf *b = rx_buffer;
rx_buffer = 0;
delete b;
}
return out;
}
int WiFiUDP::peek(){
if(!rx_buffer) return -1;
return rx_buffer->peek();
}
void WiFiUDP::flush(){
cbuf *b = rx_buffer;
rx_buffer = 0;
delete b;
}
IPAddress WiFiUDP::remoteIP(){
return remote_ip;
}
uint16_t WiFiUDP::remotePort(){
return remote_port;
}
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* 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.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef _WIFIUDP_H_
#define _WIFIUDP_H_
#include <Arduino.h>
#include <Udp.h>
#include <cbuf.h>
class WiFiUDP : public UDP {
private:
int udp_server;
IPAddress multicast_ip;
IPAddress remote_ip;
uint16_t server_port;
uint16_t remote_port;
char * tx_buffer;
size_t tx_buffer_len;
cbuf * rx_buffer;
public:
WiFiUDP();
~WiFiUDP();
uint8_t begin(IPAddress a, uint16_t p);
uint8_t begin(uint16_t p);
uint8_t beginMulticast(IPAddress a, uint16_t p);
void stop();
int beginMulticastPacket();
int beginPacket();
int beginPacket(IPAddress ip, uint16_t port);
int beginPacket(const char *host, uint16_t port);
int endPacket();
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
int parsePacket();
int available();
int read();
int read(unsigned char* buffer, size_t len);
int read(char* buffer, size_t len);
int peek();
void flush();
IPAddress remoteIP();
uint16_t remotePort();
};
#endif /* _WIFIUDP_H_ */
......@@ -13,6 +13,7 @@
#define CONFIG_NEWLIB_STDOUT_ADDCR 1
#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB"
#define CONFIG_ETHERNET 1
#define CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE 1
#define CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL 1
#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1
#define CONFIG_BT_RESERVE_DRAM 0x10000
......@@ -20,6 +21,7 @@
#define CONFIG_CONSOLE_UART_BAUDRATE 115200
#define CONFIG_LWIP_MAX_SOCKETS 4
#define CONFIG_ESP32_ENABLE_STACK_BT 1
#define CONFIG_EMAC_TASK_PRIORITY 20
#define CONFIG_ULP_COPROC_RESERVE_MEM 512
#define CONFIG_ESPTOOLPY_BAUD 921600
#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-"
......
......@@ -156,6 +156,7 @@ typedef enum {
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */
GPIO_NUM_MAX = 40,
} gpio_num_t;
typedef enum {
......@@ -205,9 +206,8 @@ typedef enum {
} gpio_pull_mode_t;
typedef void (*gpio_isr_t)(void*);
typedef intr_handle_t gpio_isr_handle_t;
typedef void (*gpio_event_callback)(gpio_num_t gpio_intr_num);
/**
* @brief GPIO common configuration
......@@ -269,7 +269,7 @@ esp_err_t gpio_intr_disable(gpio_num_t gpio_num);
*
* @return
* - ESP_OK Success
* - GPIO_IS_VALID_GPIO GPIO number error
* - ESP_ERR_INVALID_ARG GPIO number error
*
*/
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
......@@ -343,9 +343,6 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
/**
* @brief register GPIO interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @note
* Users should know that which CPU is running and then pick a INUM that is not used by system.
* We can find the information of INUM and interrupt level in soc.h.
*
* @param fn Interrupt handler function.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
......@@ -360,8 +357,6 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
*/
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
/**
* @brief Enable pull-up on GPIO.
*
......@@ -406,97 +401,55 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
*/
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
/**
* *************** ATTENTION ********************/
/**
*@attention
* Each GPIO has its own separate configuration register, so we do not use
* a lock to serialize access to them. This works under the assumption that
* no situation will occur where two tasks try to configure the same GPIO
* pin simultaneously. It is up to the application developer to guarantee this.
*/
* @brief Install a GPIO ISR service, so we can assign different ISR handler for different pins
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Operation fail
* - ESP_ERR_NO_MEM No memory to install this service
*/
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
/**
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
* @code{c}
* gpio_config_t io_conf;
* io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
* io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
* io_conf.pin_bit_mask = GPIO_SEL_18 | GPIO_SEL_19; //bit mask of the pins that you want to set,e.g.GPIO18/19
* io_conf.pull_down_en = 0; //disable pull-down mode
* io_conf.pull_up_en = 0; //disable pull-up mode
* gpio_config(&io_conf); //configure GPIO with the given settings
* @endcode
**/
* @brief Un-install GPIO ISR service, free the resources.
*/
void gpio_uninstall_isr_service();
/**
*----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
* @code{c}
* io_conf.intr_type = GPIO_INTR_POSEDGE; //set posedge interrupt
* io_conf.mode = GPIO_MODE_INPUT; //set as input
* io_conf.pin_bit_mask = GPIO_SEL_4 | GPIO_SEL_5; //bit mask of the pins that you want to set, e.g.,GPIO4/5
* io_conf.pull_down_en = 0; //disable pull-down mode
* io_conf.pull_up_en = 1; //enable pull-up mode
* gpio_config(&io_conf); //configure GPIO with the given settings
* @endcode
*/
/**
*----------EXAMPLE TO SET ISR HANDLER ----------------------
* @code{c}
* gpio_isr_register(gpio_intr_test,NULL, 0); //hook the isr handler for GPIO interrupt
* @endcode
* @note
* 1. user should arrange the INUMs that used, better not to use a same INUM for different interrupt.
* 2. do not pick the INUM that already occupied by the system.
* 3. refer to soc.h to check which INUMs that can be used.
*/
/**
*-------------EXAMPLE OF HANDLER FUNCTION-------------------*
* @code{c}
* #include "esp_attr.h"
* void IRAM_ATTR gpio_intr_test(void* arg)
* {
* //GPIO intr process
* ets_printf("in gpio_intr\n");
* uint32_t gpio_num = 0;
* uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG); //read status to get interrupt status for GPIO0-31
* uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
* SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status); //Clear intr for gpio0-gpio31
* SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
* do {
* if(gpio_num < 32) {
* if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
* ets_printf("Intr GPIO%d ,val: %d\n",gpio_num,gpio_get_level(gpio_num));
* //This is an isr handler, you should post an event to process it in RTOS queue.
* }
* } else {
* if(gpio_intr_status_h & BIT(gpio_num - 32)) {
* ets_printf("Intr GPIO%d, val : %d\n",gpio_num,gpio_get_level(gpio_num));
* //This is an isr handler, you should post an event to process it in RTOS queue.
* }
* }
* } while(++gpio_num < GPIO_PIN_COUNT);
* }
* @endcode
*/
* @brief Add ISR handler for the corresponding GPIO.
*
* Interrupt handlers no longer need to be declared with IRAM_ATTR, unless you pass the ESP_INTR_FLAG_IRAM flag
* when allocating the ISR in gpio_install_isr_service().
* This ISR handler will be called from an ISR. So there probably is some stack size limit, and this limit
* is smaller compared to a "raw" interrupt handler due to another level of indirection.
*
* @param gpio_num GPIO number
* @param isr_handler ISR handler function for the corresponding GPIO number.
* @param args parameter for ISR handler.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args);
/**
*----EXAMPLE OF I2C CONFIG AND PICK SIGNAL FOR IO MATRIX---*
* @code{c}
* gpio_config_t io_conf;
* io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
* io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD; //set as output mode
* io_conf.pin_bit_mask = GPIO_SEL_21 | GPIO_SEL_22; //bit mask of the pins that you want to set,e.g.GPIO21/22
* io_conf.pull_down_en = 0; //disable pull-down mode
* io_conf.pull_up_en = 1; //enable pull-up mode
* gpio_config(&io_conf); //configure GPIO with the given settings
* gpio_matrix_out(21, EXT_I2C_SCL_O_IDX, 0, 0); //set output signal for io_matrix
* gpio_matrix_out(22, EXT_I2C_SDA_O_IDX, 0, 0); //set output signal for io_matrix
* gpio_matrix_in( 22, EXT_I2C_SDA_I_IDX, 0); //set input signal for io_matrix
* @endcode
*
*/
* @brief Remove ISR handler for the corresponding GPIO.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);
#ifdef __cplusplus
}
......
......@@ -253,7 +253,7 @@ int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction,
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction,
uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale);
/**
......@@ -354,7 +354,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel);
* - ESP_OK Success
*
*/
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx);
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx);
/***************************EXAMPLE**********************************
*
......@@ -391,7 +391,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint
*
* ----------------EXAMPLE OF SETTING DUTY --- -----------------
* @code{c}
* uint32_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73)
* ledc_channel_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73)
* uint32_t duty = 2000; //duty range is 0 ~ ((2**bit_num)-1)
* LEDC_set_duty(LEDC_HIGH_SPEED_MODE, ledc_channel, duty); //set speed mode, channel, and duty.
* ledc_update_duty(LEDC_HIGH_SPEED_MODE, ledc_channel); //after set duty, we need to call ledc_update_duty to update the settings.
......
......@@ -524,7 +524,9 @@ esp_err_t rmt_set_err_intr_en(rmt_channel_t channel, bool en);
esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en);
/**
* @brief Set RMT TX event interrupt enable
* @brief Set RMT TX threshold event interrupt enable
*
* Causes an interrupt when a threshold number of items have been transmitted.
*
* @param channel RMT channel (0 - 7)
*
......@@ -536,7 +538,7 @@ esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en);
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t rmt_set_evt_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);
esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh);
/**
* @brief Set RMT pins
......
......@@ -23,6 +23,7 @@ extern "C" {
#include "soc/uart_reg.h"
#include "soc/uart_struct.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "driver/periph_ctrl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
......@@ -129,6 +130,7 @@ typedef enum {
UART_PARITY_ERR, /*!< UART RX parity event*/
UART_DATA_BREAK, /*!< UART TX data and break event*/
UART_EVENT_MAX, /*!< UART event max index*/
UART_PATTERN_DET, /*!< UART pattern detected */
} uart_event_type_t;
/**
......@@ -139,6 +141,8 @@ typedef struct {
size_t size; /*!< UART data size for UART_DATA event*/
} uart_event_t;
typedef intr_handle_t uart_isr_handle_t;
/**
* @brief Set UART data bits.
*
......@@ -372,12 +376,14 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
* @param arg parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags);
esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags, uart_isr_handle_t *handle);
/**
......@@ -467,11 +473,12 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
* We can find the information of INUM and interrupt level in soc.h.
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param rx_buffer_size UART RX ring buffer size
* @param rx_buffer_size UART RX ring buffer size, rx_buffer_size should be greater than UART_FIFO_LEN.
* @param tx_buffer_size UART TX ring buffer size.
* If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out..
* @param queue_size UART event queue size/depth.
* @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue.
* @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide
* access to UART events. If set to NULL, driver will not use an event queue.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
......@@ -479,7 +486,7 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, void* uart_queue, int intr_alloc_flags);
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags);
/**
* @brief Uninstall UART driver.
......@@ -588,6 +595,48 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
*/
esp_err_t uart_flush(uart_port_t uart_num);
/**
* @brief UART get RX ring buffer cached data length
*
* @param uart_num UART port number.
* @param size Pointer of size_t to accept cached data length
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
/**
* @brief UART disable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detect a series of one same character, the interrupt will be triggered.
*
* @param uart_num UART port number.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num);
/**
* @brief UART enable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detect a series of one same character, the interrupt will be triggered.
*
* @param uart_num UART port number.
* @param pattern_chr character of the pattern
* @param chr_num number of the character, 8bit value.
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB(80Mhz) clock cycle.
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
/***************************EXAMPLE**********************************
*
*
......@@ -599,7 +648,7 @@ esp_err_t uart_flush(uart_port_t uart_num);
* //a. Set UART parameter
* int uart_num = 0; //uart port number
* uart_config_t uart_config = {
* .baud_rate = UART_BITRATE_115200, //baudrate
* .baud_rate = 115200, //baudrate
* .data_bits = UART_DATA_8_BITS, //data bit mode
* .parity = UART_PARITY_DISABLE, //parity mode
* .stop_bits = UART_STOP_BITS_1, //stop bit mode
......@@ -658,7 +707,7 @@ esp_err_t uart_flush(uart_port_t uart_num);
* //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19)
* uart_set_pin(uart_num, 16, 17, 18, 19);
* //Install UART driver( We don't need an event queue here)
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF);
* uart_driver_install(uart_num, 1024 * 2, 1024*4, 0, NULL, 0);
* uint8_t data[1000];
* while(1) {
* //Read data from UART
......@@ -692,7 +741,6 @@ esp_err_t uart_flush(uart_port_t uart_num);
* ESP_LOGI(TAG,"data, len: %d", event.size);
* int len = uart_read_bytes(uart_num, dtmp, event.size, 10);
* ESP_LOGI(TAG, "uart read: %d", len);
uart_write_bytes(uart_num, (const char*)dtmp, len);
* break;
* //Event of HW FIFO overflow detected
* case UART_FIFO_OVF:
......
......@@ -107,17 +107,15 @@ typedef struct {
* WiFi NVS structure etc, this WiFi also start WiFi task
*
* @attention 1. This API must be called before all other WiFi API can be called
* @attention 2. Generally we should init event_q in *config, WiFi driver will post the event
* to this queue when event happens, such as, when station connects to WiFi, WiFi driver
* will post station connected event to this queue. If the queue is not initialized, WiFi
* will not post any events
* @attention 2. event_handler field in cfg should be set to a valid event handler function.
* In most cases, use the WIFI_INIT_CONFIG_DEFAULT macro which sets esp_event_send().
*
* @param config provide WiFi init configuration
*
* @return
* - ESP_OK: succeed
* - ESP_ERR_WIFI_NO_MEM: out of memory
* - others: refer to error code esp_err.h
* - others: refer to error code esp_err.h
*/
esp_err_t esp_wifi_init(wifi_init_config_t *config);
......
......@@ -96,7 +96,7 @@ typedef enum {
} wifi_second_chan_t;
typedef struct {
char *ssid; /**< SSID of AP */
uint8_t *ssid; /**< SSID of AP */
uint8_t *bssid; /**< MAC address of AP */
uint8_t channel; /**< channel, scan the specific channel */
bool show_hidden; /**< enable to scan AP whose SSID is hidden */
......@@ -126,8 +126,8 @@ typedef enum {
} wifi_bandwidth_t;
typedef struct {
char ssid[32]; /**< SSID of ESP32 soft-AP */
char password[64]; /**< Password of ESP32 soft-AP */
uint8_t ssid[32]; /**< SSID of ESP32 soft-AP */
uint8_t password[64]; /**< Password of ESP32 soft-AP */
uint8_t ssid_len; /**< Length of SSID. If softap_config.ssid_len==0, check the SSID until there is a termination character; otherwise, set the SSID length according to softap_config.ssid_len. */
uint8_t channel; /**< Channel of ESP32 soft-AP */
wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */
......@@ -137,8 +137,8 @@ typedef struct {
} wifi_ap_config_t;
typedef struct {
char ssid[32]; /**< SSID of target AP*/
char password[64]; /**< password of target AP*/
uint8_t ssid[32]; /**< SSID of target AP*/
uint8_t password[64]; /**< password of target AP*/
bool bssid_set; /**< whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/
uint8_t bssid[6]; /**< MAC address of target AP*/
} wifi_sta_config_t;
......@@ -215,7 +215,7 @@ typedef struct {
typedef struct {
wifi_pkt_rx_ctrl_t rx_ctrl;
char payload[0]; /**< ieee80211 packet buff, The length of payload is described by sig_len */
uint8_t payload[0]; /**< ieee80211 packet buff, The length of payload is described by sig_len */
} wifi_promiscuous_pkt_t;
/**
......
......@@ -26,6 +26,16 @@
#define WSR(reg, newval) asm volatile ("wsr %0, " #reg : : "r" (newval));
#define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval));
/** @brief Read current stack pointer address
*
*/
static inline void *get_sp()
{
void *sp;
asm volatile ("mov %0, sp;" : "=r" (sp));
return sp;
}
/* Return true if the CPU is in an interrupt context
(PS.UM == 0)
*/
......
......@@ -22,15 +22,21 @@
extern "C" {
#endif
typedef void (*eth_phy_fun)(void);
typedef esp_err_t (*eth_tcpip_input_fun)(void *buffer, uint16_t len, void *eb);
typedef void (*eth_gpio_config_func)(void);
typedef enum {
ETH_MODE_RMII = 0,
ETH_MDOE_MII,
} eth_mode_t;
typedef enum {
ETH_SPEED_MODE_10M = 0,
ETH_SPEED_MODE_100M,
} eth_speed_mode_t;
typedef enum {
ETH_MODE_HALFDUPLEX = 0,
ETH_MDOE_FULLDUPLEX,
} eth_duplex_mode_t;
typedef enum {
PHY0 = 0,
PHY1,
......@@ -66,6 +72,15 @@ typedef enum {
PHY31,
} eth_phy_base_t;
typedef bool (*eth_phy_check_link_func)(void);
typedef void (*eth_phy_check_init_func)(void);
typedef eth_speed_mode_t (*eth_phy_get_speed_mode_func)(void);
typedef eth_duplex_mode_t (*eth_phy_get_duplex_mode_func)(void);
typedef void (*eth_phy_func)(void);
typedef esp_err_t (*eth_tcpip_input_func)(void *buffer, uint16_t len, void *eb);
typedef void (*eth_gpio_config_func)(void);
/**
* @brief ethernet configuration
*
......@@ -73,8 +88,12 @@ typedef enum {
typedef struct {
eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */
eth_mode_t mac_mode; /*!< mac mode only support RMII now */
eth_tcpip_input_fun tcpip_input; /*!< tcpip input func */
eth_phy_fun phy_init; /*!< phy init func */
eth_tcpip_input_func tcpip_input; /*!< tcpip input func */
eth_phy_func phy_init; /*!< phy init func */
eth_phy_check_link_func phy_check_link; /*!< phy check link func */
eth_phy_check_init_func phy_check_init; /*!< phy check init func */
eth_phy_get_speed_mode_func phy_get_speed_mode; /*!< phy check init func */
eth_phy_get_duplex_mode_func phy_get_duplex_mode; /*!< phy check init func */
eth_gpio_config_func gpio_config; /*!< gpio config func */
} eth_config_t;
......@@ -159,6 +178,16 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value);
*/
uint16_t esp_eth_smi_read(uint32_t reg_num);
/**
* @brief Free emac rx buf.
*
* @note buf can not be null,and it is tcpip input buf.
*
* @param[in] buf: start address of recevie packet data.
*
*/
void esp_eth_free_rx_buf(void *buf);
#ifdef __cplusplus
}
#endif
......
......@@ -22,9 +22,10 @@ typedef struct {
/* Please keep this definition same as BlockLink_t */
typedef struct _os_block_t {
struct _os_block_t *next;
size_t size;
unsigned int xtag;
struct _os_block_t *next; /*<< The next free block in the list. */
int size: 24; /*<< The size of the free block. */
int xtag: 7; /*<< Tag of this region */
int xAllocated: 1; /*<< 1 if allocated */
}os_block_t;
typedef struct {
......@@ -50,7 +51,7 @@ typedef struct _mem_dbg_ctl{
#define OS_BLOCK(_b) ((os_block_t*)((debug_block_t*)((char*)(_b) + BLOCK_HEAD_LEN)))
#define DEBUG_BLOCK(_b) ((debug_block_t*)((char*)(_b) - BLOCK_HEAD_LEN))
#define HEAD_DOG(_b) ((_b)->head.dog)
#define TAIL_DOG(_b) (*(unsigned int*)((char*)(_b) + (((_b)->os_block.size & (~g_alloc_bit) ) - BLOCK_TAIL_LEN)))
#define TAIL_DOG(_b) (*(unsigned int*)((char*)(_b) + (((_b)->os_block.size ) - BLOCK_TAIL_LEN)))
#define DOG_ASSERT()\
{\
......
......@@ -213,7 +213,6 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux);
#define portEXIT_CRITICAL_ISR(mux) vPortCPUReleaseMutex(mux)
#endif
// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
//NOT SMP-COMPATIBLE! Use only if all you want is to disable the interrupts locally!
......
......@@ -105,6 +105,12 @@ typedef enum {
/** indicates this pbuf includes a TCP FIN flag */
#define PBUF_FLAG_TCP_FIN 0x20U
#if ESP_LWIP
#define PBUF_USER_FLAG_OWNER_NULL 0
#define PBUF_USER_FLAG_OWNER_WIFI 1
#define PBUF_USER_FLAG_OWNER_ETH 2
#endif
struct pbuf {
/** next pbuf in singly linked pbuf chain */
struct pbuf *next;
......@@ -138,7 +144,8 @@ struct pbuf {
u16_t ref;
#if ESP_LWIP
void *eb;
void *user_buf;
u8_t user_flag;
#endif
};
......
......@@ -154,14 +154,14 @@
* this option does not affect outgoing packet sizes, which can be controlled
* via IP_FRAG.
*/
#define IP_REASSEMBLY 0
#define IP_REASSEMBLY CONFIG_LWIP_IP_REASSEMBLY
/**
* IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
* that this option does not affect incoming packet sizes, which can be
* controlled via IP_REASSEMBLY.
*/
#define IP_FRAG 0
#define IP_FRAG CONFIG_LWIP_IP_FRAG
/**
* IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
......
......@@ -154,14 +154,14 @@
* this option does not affect outgoing packet sizes, which can be controlled
* via IP_FRAG.
*/
#define IP_REASSEMBLY 0
#define IP_REASSEMBLY CONFIG_LWIP_IP_REASSEMBLY
/**
* IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
* that this option does not affect incoming packet sizes, which can be
* controlled via IP_REASSEMBLY.
*/
#define IP_FRAG 0
#define IP_FRAG CONFIG_LWIP_IP_FRAG
/**
* IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
......
......@@ -78,13 +78,13 @@ esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
* @note If source address is in DROM, this function will return
* ESP_ERR_INVALID_ARG.
*
* @param dest destination address in Flash. Must be a multiple of 4 bytes.
* @param src pointer to the source buffer.
* @param size length of data, in bytes. Must be a multiple of 4 bytes.
* @param dest_addr destination address in Flash. Must be a multiple of 4 bytes.
* @param src pointer to the source buffer.
* @param size length of data, in bytes. Must be a multiple of 4 bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write(size_t dest, const void *src, size_t size);
esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size);
/**
......@@ -97,24 +97,24 @@ esp_err_t spi_flash_write(size_t dest, const void *src, size_t size);
* @note If source address is in DROM, this function will return
* ESP_ERR_INVALID_ARG.
*
* @param dest destination address in Flash. Must be a multiple of 32 bytes.
* @param src pointer to the source buffer.
* @param size length of data, in bytes. Must be a multiple of 32 bytes.
* @param dest_addr destination address in Flash. Must be a multiple of 32 bytes.
* @param src pointer to the source buffer.
* @param size length of data, in bytes. Must be a multiple of 32 bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write_encrypted(size_t dest, const void *src, size_t size);
esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
/**
* @brief Read data from Flash.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
* @param src_addr source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
* @return esp_err_t
*/
esp_err_t spi_flash_read(size_t src, void *dest, size_t size);
esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);
/**
* @brief Enumeration which specifies memory space requested in an mmap call
......@@ -149,7 +149,7 @@ typedef uint32_t spi_flash_mmap_handle_t;
*
* @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
*/
esp_err_t spi_flash_mmap(uint32_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册