├── include ├── string.h ├── lwip │ ├── netif.h │ ├── app │ │ ├── dhcpserver.h │ │ ├── encdhcpserver.h │ │ └── dhcpserver_common.h │ ├── ip_route.h │ ├── lwip_napt.h │ └── netif │ │ └── espenc.h └── driver │ ├── spi.h │ ├── uart.h │ ├── uart_register.h │ └── spi_register.h ├── rboot.bin ├── AutoMesh.JPG ├── WebConfig.jpg ├── firmware ├── 0x00000.bin ├── 0x02000.bin ├── 0x82000.bin ├── esp_init_data_default_v08_vdd33.bin └── sha1sums ├── liblwip_open_napt.a ├── FlashRepeaterWindows.jpg ├── mqtt ├── include │ ├── utils.h │ ├── typedef.h │ ├── debug.h │ ├── ringbuf_mqtt.h │ ├── proto.h │ ├── queue.h │ ├── mqtt_msg.h │ └── mqtt.h ├── Makefile ├── ringbuf_mqtt.c ├── queue.c ├── proto.c └── utils.c ├── user ├── sys_time.h ├── sys_time.c ├── pcap.h ├── acl.h ├── rboot-ota.h ├── web.h ├── user_config.h ├── ringbuf.h ├── rboot.h ├── rboot-api.h ├── rboot-api.c ├── ringbuf.c ├── config_flash.h ├── acl.c ├── config_flash.c └── rboot-ota.c ├── easygpio ├── easygpio.h └── easygpio.c ├── Makefile ├── rom0.ld ├── rom1.ld └── driver └── spi.c /include/string.h: -------------------------------------------------------------------------------- 1 | //Nothing here. 2 | -------------------------------------------------------------------------------- /rboot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/rboot.bin -------------------------------------------------------------------------------- /AutoMesh.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/AutoMesh.JPG -------------------------------------------------------------------------------- /WebConfig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/WebConfig.jpg -------------------------------------------------------------------------------- /firmware/0x00000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/firmware/0x00000.bin -------------------------------------------------------------------------------- /firmware/0x02000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/firmware/0x02000.bin -------------------------------------------------------------------------------- /firmware/0x82000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/firmware/0x82000.bin -------------------------------------------------------------------------------- /include/lwip/netif.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/include/lwip/netif.h -------------------------------------------------------------------------------- /liblwip_open_napt.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/liblwip_open_napt.a -------------------------------------------------------------------------------- /FlashRepeaterWindows.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/FlashRepeaterWindows.jpg -------------------------------------------------------------------------------- /firmware/esp_init_data_default_v08_vdd33.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mobizt/esp_wifi_repeater/master/firmware/esp_init_data_default_v08_vdd33.bin -------------------------------------------------------------------------------- /firmware/sha1sums: -------------------------------------------------------------------------------- 1 | 0b4a8a907b1042cc0a5df43b7e61a98eb6724f3c firmware/0x02000.bin 2 | 421d80d57e62bb6e4bad5f3a101c1b9e01037252 firmware/0x82000.bin 3 | 9bd7d25204d71b3db5f35e0b2def8a6aaa7f765c firmware/0x00000.bin 4 | -------------------------------------------------------------------------------- /mqtt/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include "c_types.h" 5 | 6 | uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s); 7 | uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip); 8 | uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str); 9 | #endif 10 | -------------------------------------------------------------------------------- /user/sys_time.h: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | 3 | // returns time until boot in us 4 | uint64_t ICACHE_FLASH_ATTR get_long_systime(); 5 | 6 | // returns lower half of time until boot in us 7 | uint64_t ICACHE_FLASH_ATTR get_low_systime(); 8 | 9 | // initializes the timer 10 | void init_long_systime(); 11 | 12 | 13 | -------------------------------------------------------------------------------- /mqtt/include/typedef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Standard Types definition 4 | */ 5 | 6 | #ifndef _TYPE_DEF_H_ 7 | #define _TYPE_DEF_H_ 8 | 9 | typedef char I8; 10 | typedef unsigned char U8; 11 | typedef short I16; 12 | typedef unsigned short U16; 13 | typedef long I32; 14 | typedef unsigned long U32; 15 | typedef unsigned long long U64; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /mqtt/include/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * debug.h 3 | * 4 | * Created on: Dec 4, 2014 5 | * Author: Minh 6 | */ 7 | 8 | #ifndef USER_DEBUG_H_ 9 | #define USER_DEBUG_H_ 10 | 11 | #if defined(MQTT_DEBUG_ON) 12 | #define MQTT_INFO( format, ... ) os_printf( format, ## __VA_ARGS__ ) 13 | #else 14 | #define MQTT_INFO( format, ... ) 15 | #endif 16 | 17 | 18 | #endif /* USER_DEBUG_H_ */ 19 | -------------------------------------------------------------------------------- /mqtt/include/ringbuf_mqtt.h: -------------------------------------------------------------------------------- 1 | #ifndef _RING_BUF_MQTT_H_ 2 | #define _RING_BUF_MQTT_H_ 3 | 4 | #include 5 | #include 6 | #include "typedef.h" 7 | 8 | typedef struct { 9 | U8* p_o; /**< Original pointer */ 10 | U8* volatile p_r; /**< Read pointer */ 11 | U8* volatile p_w; /**< Write pointer */ 12 | volatile I32 fill_cnt; /**< Number of filled slots */ 13 | I32 size; /**< Buffer size */ 14 | } RINGBUF; 15 | 16 | I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size); 17 | I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c); 18 | I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c); 19 | #endif 20 | -------------------------------------------------------------------------------- /include/lwip/app/dhcpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef __DHCPS_H__ 2 | #define __DHCPS_H__ 3 | 4 | #define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) 5 | #include "dhcpserver_common.h" 6 | #define DHCPS_DEBUG 0 7 | 8 | extern uint32 dhcps_lease_time; 9 | #define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0 10 | 11 | void dhcps_start(struct ip_info *info); 12 | void dhcps_stop(void); 13 | 14 | void dhcps_set_DNS(struct ip_addr *dns_ip) ICACHE_FLASH_ATTR; 15 | struct dhcps_pool *dhcps_get_mapping(uint16_t no) ICACHE_FLASH_ATTR; 16 | void dhcps_set_mapping(struct ip_addr *addr, uint8 *mac, uint32 lease_time) ICACHE_FLASH_ATTR; 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /user/sys_time.c: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | #include "osapi.h" 3 | 4 | typedef union _timer { 5 | uint32_t time_s[2]; 6 | uint64_t time_l; 7 | } long_time_t; 8 | 9 | static long_time_t time; 10 | static uint32_t old; 11 | 12 | uint64_t ICACHE_FLASH_ATTR get_long_systime() { 13 | uint32_t now = system_get_time(); 14 | if (now < old) { 15 | time.time_s[1]++; 16 | } 17 | old = now; 18 | time.time_s[0] = now; 19 | return time.time_l; 20 | } 21 | 22 | uint64_t ICACHE_FLASH_ATTR get_low_systime() { 23 | get_long_systime(); 24 | return time.time_s[0]; 25 | } 26 | 27 | void init_long_systime() { 28 | old = system_get_time(); 29 | time.time_l = (uint64_t)old; 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /include/lwip/app/encdhcpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef __enc_DHCPS_H__ 2 | #define __enc_DHCPS_H__ 3 | 4 | #define enc_dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) 5 | #include "dhcpserver_common.h" 6 | 7 | extern uint32 enc_dhcps_lease_time; 8 | #define enc_DHCPS_LEASE_TIMER enc_dhcps_lease_time //0x05A0 9 | #define ENCDHCPS_DEBUG 0 10 | 11 | 12 | void enc_dhcps_start(struct netif* enetif); 13 | void enc_dhcps_stop(void); 14 | 15 | void enc_dhcps_set_DNS(struct ip_addr *dns_ip) ICACHE_FLASH_ATTR; 16 | struct dhcps_pool *enc_dhcps_get_mapping(uint16_t no) ICACHE_FLASH_ATTR; 17 | void enc_dhcps_set_mapping(struct ip_addr *addr, uint8 *mac, uint32 lease_time) ICACHE_FLASH_ATTR; 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /user/pcap.h: -------------------------------------------------------------------------------- 1 | #ifndef __PCAP_H__ 2 | #define __PCAP_H__ 3 | 4 | #define PCAP_VERSION_MAJOR 2 5 | #define PCAP_VERSION_MINOR 4 6 | #define PCAP_MAGIC_NUMBER 0xa1b2c3d4 7 | 8 | #define LINKTYPE_ETHERNET 1 9 | 10 | struct pcap_file_header { 11 | uint32_t magic; 12 | uint16_t version_major; 13 | uint16_t version_minor; 14 | uint32_t thiszone; /* gmt to local correction */ 15 | uint32_t sigfigs; /* accuracy of timestamps */ 16 | uint32_t snaplen; /* max length saved portion of each pkt */ 17 | uint32_t linktype; /* data link type (LINKTYPE_*) */ 18 | }; 19 | 20 | struct pcap_pkthdr { 21 | uint32_t ts_sec; /* time stamp sec */ 22 | uint32_t ts_usec; /* time stamp usec */ 23 | uint32_t caplen; /* length of portion present */ 24 | uint32_t len; /* length this packet (off wire) */ 25 | }; 26 | 27 | #endif /* __PCAP_H__ */ 28 | -------------------------------------------------------------------------------- /mqtt/include/proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: proto.h 3 | * Author: ThuHien 4 | * 5 | * Created on November 23, 2012, 8:57 AM 6 | */ 7 | 8 | #ifndef _PROTO_H_ 9 | #define _PROTO_H_ 10 | #include 11 | #include "typedef.h" 12 | #include "ringbuf_mqtt.h" 13 | 14 | typedef void(PROTO_PARSE_CALLBACK)(); 15 | 16 | typedef struct { 17 | U8 *buf; 18 | U16 bufSize; 19 | U16 dataLen; 20 | U8 isEsc; 21 | U8 isBegin; 22 | PROTO_PARSE_CALLBACK* callback; 23 | } PROTO_PARSER; 24 | 25 | I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize); 26 | I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len); 27 | I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize); 28 | I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len); 29 | I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value); 30 | I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen); 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /include/lwip/ip_route.h: -------------------------------------------------------------------------------- 1 | #ifndef __LWIP_IP_ROUTE_H__ 2 | #define __LWIP_IP_ROUTE_H__ 3 | 4 | #include "lwip/opt.h" 5 | #include "lwip/ip_addr.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define MAX_ROUTES 10 12 | 13 | struct route_entry { 14 | ip_addr_t ip; 15 | ip_addr_t mask; 16 | ip_addr_t gw; 17 | }; 18 | 19 | extern struct route_entry ip_rt_table[MAX_ROUTES]; 20 | extern int ip_route_max; 21 | 22 | /* Add a static route, true on success */ 23 | bool ip_add_route(ip_addr_t ip, ip_addr_t mask, ip_addr_t gw); 24 | 25 | /* Remove a static route, true on success */ 26 | bool ip_rm_route(ip_addr_t ip, ip_addr_t mask); 27 | 28 | /* Finds a route entry for an address, NULL if none */ 29 | struct route_entry *ip_find_route(ip_addr_t ip); 30 | 31 | /* Delete all static routes */ 32 | void ip_delete_routes(void); 33 | 34 | /* Returns the n_th entry of the routing table, true on success */ 35 | bool ip_get_route(uint32_t no, ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif /* __LWIP_IP_ROUTE_H__ */ 42 | -------------------------------------------------------------------------------- /user/acl.h: -------------------------------------------------------------------------------- 1 | #ifndef _ACL_H_ 2 | #define _ACL_H_ 3 | 4 | #include "lwip/ip.h" 5 | #include "lwip/pbuf.h" 6 | 7 | #define MAX_NO_ACLS 4 8 | #define MAX_ACL_ENTRIES 16 9 | 10 | #define ACL_DENY 0x0 11 | #define ACL_ALLOW 0x1 12 | #define ACL_MONITOR 0x2 13 | 14 | typedef struct _acl_entry { 15 | uint32_t src; 16 | uint32_t s_mask; 17 | uint32_t dest; 18 | uint32_t d_mask; 19 | uint16_t s_port; 20 | uint16_t d_port; 21 | uint8_t proto; 22 | uint8_t allow; 23 | uint32_t hit_count; 24 | } acl_entry; 25 | 26 | extern acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES]; 27 | extern uint8_t acl_freep[MAX_NO_ACLS]; 28 | extern uint32_t acl_allow_count; 29 | extern uint32_t acl_deny_count; 30 | 31 | typedef uint8_t (*packet_deny_cb)(uint8_t proto, uint32_t saddr, uint16_t s_port, uint32_t daddr, uint16_t d_port, uint8_t allow); 32 | 33 | void acl_init(); 34 | bool acl_is_empty(uint8_t acl_no); 35 | void acl_clear(uint8_t acl_no); 36 | void acl_clear_stats(uint8_t acl_no); 37 | bool acl_add(uint8_t acl_no, 38 | uint32_t src, uint32_t s_mask, uint32_t dest, uint32_t d_mask, 39 | uint8_t proto, uint16_t s_port, uint16_t d_port, uint8_t allow); 40 | uint8_t acl_check_packet(uint8_t acl_no, struct pbuf *p); 41 | void acl_set_deny_cb(packet_deny_cb cb); 42 | 43 | void addr2str(uint8_t *buf, uint32_t addr, uint32_t mask); 44 | void acl_show(uint8_t acl_no, uint8_t *buf); 45 | 46 | #endif /* _ACL_H_ */ 47 | 48 | -------------------------------------------------------------------------------- /user/rboot-ota.h: -------------------------------------------------------------------------------- 1 | #ifndef __RBOOT_OTA_H__ 2 | #define __RBOOT_OTA_H__ 3 | 4 | ////////////////////////////////////////////////// 5 | // rBoot OTA sample code for ESP8266. 6 | // Copyright 2015 Richard A Burton 7 | // richardaburton@gmail.com 8 | // See license.txt for license terms. 9 | // OTA code based on SDK sample from Espressif. 10 | ////////////////////////////////////////////////// 11 | 12 | #include "rboot-api.h" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | // ota server details 19 | //#define OTA_HOST "192.168.178.25" 20 | //#define OTA_PORT 8080 21 | #define OTA_ROM0 "0x02000.bin" 22 | #define OTA_ROM1 "0x82000.bin" 23 | // OTA_FILE is not required, but is part of the example 24 | // code for writing arbitrary files to flash 25 | #define OTA_FILE "file.bin" 26 | 27 | // general http header 28 | #define HTTP_HEADER "Connection: keep-alive\r\n\ 29 | Cache-Control: no-cache\r\n\ 30 | User-Agent: rboot-ota/1.0\r\n\ 31 | Accept: */*\r\n\r\n" 32 | /* this comment to keep notepad++ happy */ 33 | 34 | // timeout for the initial connect and each recv (in ms) 35 | #define OTA_NETWORK_TIMEOUT 10000 36 | 37 | // used to indicate a non-rom flash 38 | #define FLASH_BY_ADDR 0xff 39 | 40 | // callback method should take this format 41 | typedef void (*ota_callback)(bool result, uint8 rom_slot); 42 | 43 | // function to perform the ota update 44 | bool ICACHE_FLASH_ATTR rboot_ota_start(ota_callback callback); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /mqtt/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libmqtt.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /mqtt/ringbuf_mqtt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * Ring Buffer library 4 | */ 5 | 6 | #include "ringbuf_mqtt.h" 7 | 8 | 9 | /** 10 | * \brief init a RINGBUF object 11 | * \param r pointer to a RINGBUF object 12 | * \param buf pointer to a byte array 13 | * \param size size of buf 14 | * \return 0 if successfull, otherwise failed 15 | */ 16 | I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size) 17 | { 18 | if (r == NULL || buf == NULL || size < 2) return -1; 19 | 20 | r->p_o = r->p_r = r->p_w = buf; 21 | r->fill_cnt = 0; 22 | r->size = size; 23 | 24 | return 0; 25 | } 26 | /** 27 | * \brief put a character into ring buffer 28 | * \param r pointer to a ringbuf object 29 | * \param c character to be put 30 | * \return 0 if successfull, otherwise failed 31 | */ 32 | I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c) 33 | { 34 | if (r->fill_cnt >= r->size)return -1; // ring buffer is full, this should be atomic operation 35 | 36 | 37 | r->fill_cnt++; // increase filled slots count, this should be atomic operation 38 | 39 | 40 | *r->p_w++ = c; // put character into buffer 41 | 42 | if (r->p_w >= r->p_o + r->size) // rollback if write pointer go pass 43 | r->p_w = r->p_o; // the physical boundary 44 | 45 | return 0; 46 | } 47 | /** 48 | * \brief get a character from ring buffer 49 | * \param r pointer to a ringbuf object 50 | * \param c read character 51 | * \return 0 if successfull, otherwise failed 52 | */ 53 | I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c) 54 | { 55 | if (r->fill_cnt <= 0)return -1; // ring buffer is empty, this should be atomic operation 56 | 57 | 58 | r->fill_cnt--; // decrease filled slots count 59 | 60 | 61 | *c = *r->p_r++; // get the character out 62 | 63 | if (r->p_r >= r->p_o + r->size) // rollback if write pointer go pass 64 | r->p_r = r->p_o; // the physical boundary 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /mqtt/include/queue.h: -------------------------------------------------------------------------------- 1 | /* str_queue.h -- 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef USER_QUEUE_H_ 32 | #define USER_QUEUE_H_ 33 | #include "os_type.h" 34 | #include "ringbuf_mqtt.h" 35 | typedef struct { 36 | uint8_t *buf; 37 | RINGBUF rb; 38 | } QUEUE; 39 | 40 | void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize); 41 | int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len); 42 | int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen); 43 | BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue); 44 | #endif /* USER_QUEUE_H_ */ 45 | -------------------------------------------------------------------------------- /mqtt/queue.c: -------------------------------------------------------------------------------- 1 | /* str_queue.c 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "queue.h" 31 | 32 | #include "user_interface.h" 33 | #include "osapi.h" 34 | #include "os_type.h" 35 | #include "mem.h" 36 | #include "proto.h" 37 | void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize) 38 | { 39 | queue->buf = (uint8_t*)os_zalloc(bufferSize); 40 | RINGBUF_Init(&queue->rb, queue->buf, bufferSize); 41 | } 42 | int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len) 43 | { 44 | return PROTO_AddRb(&queue->rb, buffer, len); 45 | } 46 | int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen) 47 | { 48 | 49 | return PROTO_ParseRb(&queue->rb, buffer, len, maxLen); 50 | } 51 | 52 | BOOL ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue) 53 | { 54 | if (queue->rb.fill_cnt <= 0) 55 | return TRUE; 56 | return FALSE; 57 | } 58 | -------------------------------------------------------------------------------- /include/lwip/app/dhcpserver_common.h: -------------------------------------------------------------------------------- 1 | #ifndef __DHCPS_COMMON_H__ 2 | #define __DHCPS_COMMON_H__ 3 | 4 | #define USE_DNS 5 | 6 | typedef struct dhcps_state{ 7 | sint16_t state; 8 | } dhcps_state; 9 | 10 | // ����dhcpclient�Զ����һ��DHCP msg�ṹ�� 11 | typedef struct dhcps_msg { 12 | uint8_t op, htype, hlen, hops; 13 | uint8_t xid[4]; 14 | uint16_t secs, flags; 15 | uint8_t ciaddr[4]; 16 | uint8_t yiaddr[4]; 17 | uint8_t siaddr[4]; 18 | uint8_t giaddr[4]; 19 | uint8_t chaddr[16]; 20 | uint8_t sname[64]; 21 | uint8_t file[128]; 22 | uint8_t options[312]; 23 | }dhcps_msg; 24 | 25 | #ifndef LWIP_OPEN_SRC 26 | struct dhcps_lease { 27 | bool enable; 28 | struct ip_addr start_ip; 29 | struct ip_addr end_ip; 30 | }; 31 | 32 | enum dhcps_offer_option{ 33 | OFFER_START = 0x00, 34 | OFFER_ROUTER = 0x01, 35 | OFFER_END 36 | }; 37 | #endif 38 | 39 | struct dhcps_pool{ 40 | struct ip_addr ip; 41 | uint8 mac[6]; 42 | uint32 lease_timer; 43 | }; 44 | 45 | typedef struct _list_node{ 46 | void *pnode; 47 | struct _list_node *pnext; 48 | }list_node; 49 | 50 | #define DHCPS_MAX_LEASE 0x64 51 | #define BOOTP_BROADCAST 0x8000 52 | 53 | #define DHCP_REQUEST 1 54 | #define DHCP_REPLY 2 55 | #define DHCP_HTYPE_ETHERNET 1 56 | #define DHCP_HLEN_ETHERNET 6 57 | #define DHCP_MSG_LEN 236 58 | 59 | #define DHCPS_SERVER_PORT 67 60 | #define DHCPS_CLIENT_PORT 68 61 | 62 | #define DHCPDISCOVER 1 63 | #define DHCPOFFER 2 64 | #define DHCPREQUEST 3 65 | #define DHCPDECLINE 4 66 | #define DHCPACK 5 67 | #define DHCPNAK 6 68 | #define DHCPRELEASE 7 69 | 70 | #define DHCP_OPTION_SUBNET_MASK 1 71 | #define DHCP_OPTION_ROUTER 3 72 | #define DHCP_OPTION_DNS_SERVER 6 73 | #define DHCP_OPTION_REQ_IPADDR 50 74 | #define DHCP_OPTION_LEASE_TIME 51 75 | #define DHCP_OPTION_MSG_TYPE 53 76 | #define DHCP_OPTION_SERVER_ID 54 77 | #define DHCP_OPTION_INTERFACE_MTU 26 78 | #define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 79 | #define DHCP_OPTION_BROADCAST_ADDRESS 28 80 | #define DHCP_OPTION_REQ_LIST 55 81 | #define DHCP_OPTION_END 255 82 | 83 | //#define USE_CLASS_B_NET 1 84 | #define MAX_STATION_NUM 8 85 | 86 | #define DHCPS_STATE_OFFER 1 87 | #define DHCPS_STATE_DECLINE 2 88 | #define DHCPS_STATE_ACK 3 89 | #define DHCPS_STATE_NAK 4 90 | #define DHCPS_STATE_IDLE 5 91 | #define DHCPS_STATE_RELEASE 6 92 | 93 | #endif 94 | 95 | -------------------------------------------------------------------------------- /mqtt/proto.c: -------------------------------------------------------------------------------- 1 | #include "proto.h" 2 | #include "ringbuf_mqtt.h" 3 | I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize) 4 | { 5 | parser->buf = buf; 6 | parser->bufSize = bufSize; 7 | parser->dataLen = 0; 8 | parser->callback = completeCallback; 9 | parser->isEsc = 0; 10 | return 0; 11 | } 12 | 13 | I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value) 14 | { 15 | switch (value) { 16 | case 0x7D: 17 | parser->isEsc = 1; 18 | break; 19 | 20 | case 0x7E: 21 | parser->dataLen = 0; 22 | parser->isEsc = 0; 23 | parser->isBegin = 1; 24 | break; 25 | 26 | case 0x7F: 27 | if (parser->callback != NULL) 28 | parser->callback(); 29 | parser->isBegin = 0; 30 | return 0; 31 | break; 32 | 33 | default: 34 | if (parser->isBegin == 0) break; 35 | 36 | if (parser->isEsc) { 37 | value ^= 0x20; 38 | parser->isEsc = 0; 39 | } 40 | 41 | if (parser->dataLen < parser->bufSize) 42 | parser->buf[parser->dataLen++] = value; 43 | 44 | break; 45 | } 46 | return -1; 47 | } 48 | 49 | I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len) 50 | { 51 | while (len--) 52 | PROTO_ParseByte(parser, *buf++); 53 | 54 | return 0; 55 | } 56 | I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen) 57 | { 58 | U8 c; 59 | 60 | PROTO_PARSER proto; 61 | PROTO_Init(&proto, NULL, bufOut, maxBufLen); 62 | while (RINGBUF_Get(rb, &c) == 0) { 63 | if (PROTO_ParseByte(&proto, c) == 0) { 64 | *len = proto.dataLen; 65 | return 0; 66 | } 67 | } 68 | return -1; 69 | } 70 | I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize) 71 | { 72 | U16 i = 2; 73 | U16 len = *(U16*) packet; 74 | 75 | if (bufSize < 1) return -1; 76 | 77 | *buf++ = 0x7E; 78 | bufSize--; 79 | 80 | while (len--) { 81 | switch (*packet) { 82 | case 0x7D: 83 | case 0x7E: 84 | case 0x7F: 85 | if (bufSize < 2) return -1; 86 | *buf++ = 0x7D; 87 | *buf++ = *packet++ ^ 0x20; 88 | i += 2; 89 | bufSize -= 2; 90 | break; 91 | default: 92 | if (bufSize < 1) return -1; 93 | *buf++ = *packet++; 94 | i++; 95 | bufSize--; 96 | break; 97 | } 98 | } 99 | 100 | if (bufSize < 1) return -1; 101 | *buf++ = 0x7F; 102 | 103 | return i; 104 | } 105 | 106 | I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len) 107 | { 108 | U16 i = 2; 109 | if (RINGBUF_Put(rb, 0x7E) == -1) return -1; 110 | while (len--) { 111 | switch (*packet) { 112 | case 0x7D: 113 | case 0x7E: 114 | case 0x7F: 115 | if (RINGBUF_Put(rb, 0x7D) == -1) return -1; 116 | if (RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1; 117 | i += 2; 118 | break; 119 | default: 120 | if (RINGBUF_Put(rb, *packet++) == -1) return -1; 121 | i++; 122 | break; 123 | } 124 | } 125 | if (RINGBUF_Put(rb, 0x7F) == -1) return -1; 126 | 127 | return i; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /include/lwip/lwip_napt.h: -------------------------------------------------------------------------------- 1 | #ifndef __LWIP_NAPT_H__ 2 | #define __LWIP_NAPT_H__ 3 | 4 | #include "lwip/opt.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #if IP_FORWARD 11 | #if IP_NAPT 12 | 13 | /* Default size of the tables used for NAPT */ 14 | #define IP_NAPT_MAX 512 15 | #define IP_PORTMAP_MAX 32 16 | 17 | /* Timeouts in sec for the various protocol types */ 18 | #define IP_NAPT_TIMEOUT_MS_TCP (30*60*1000) 19 | #define IP_NAPT_TIMEOUT_MS_TCP_DISCON (20*1000) 20 | #define IP_NAPT_TIMEOUT_MS_UDP (2*1000) 21 | #define IP_NAPT_TIMEOUT_MS_ICMP (2*1000) 22 | 23 | #define IP_NAPT_PORT_RANGE_START 49152 24 | #define IP_NAPT_PORT_RANGE_END 61439 25 | 26 | struct napt_table { 27 | u32_t last; 28 | u32_t src; 29 | u32_t dest; 30 | u16_t sport; 31 | u16_t dport; 32 | u16_t mport; 33 | u8_t proto; 34 | u8_t fin1 : 1; 35 | u8_t fin2 : 1; 36 | u8_t finack1 : 1; 37 | u8_t finack2 : 1; 38 | u8_t synack : 1; 39 | u8_t rst : 1; 40 | u16_t next, prev; 41 | }; 42 | 43 | struct portmap_table { 44 | u32_t maddr; 45 | u32_t daddr; 46 | u16_t mport; 47 | u16_t dport; 48 | u8_t proto; 49 | u8 valid; 50 | }; 51 | 52 | extern struct portmap_table *ip_portmap_table; 53 | 54 | /** 55 | * Allocates and initializes the NAPT tables. 56 | * 57 | * @param max_nat max number of enties in the NAPT table (use IP_NAPT_MAX if in doubt) 58 | * @param max_portmap max number of enties in the NAPT table (use IP_PORTMAP_MAX if in doubt) 59 | */ 60 | void 61 | ip_napt_init(uint16_t max_nat, uint8_t max_portmap); 62 | 63 | 64 | /** 65 | * Enable/Disable NAPT for a specified interface. 66 | * 67 | * @param addr ip address of the interface 68 | * @param enable non-zero to enable NAPT, or 0 to disable. 69 | */ 70 | void 71 | ip_napt_enable(u32_t addr, int enable); 72 | 73 | 74 | /** 75 | * Enable/Disable NAPT for a specified interface. 76 | * 77 | * @param netif number of the interface 78 | * @param enable non-zero to enable NAPT, or 0 to disable. 79 | */ 80 | void 81 | ip_napt_enable_no(u8_t number, int enable); 82 | 83 | 84 | /** 85 | * Register port mapping on the external interface to internal interface. 86 | * When the same port mapping is registered again, the old mapping is overwritten. 87 | * In this implementation, only 1 unique port mapping can be defined for each target address/port. 88 | * 89 | * @param proto target protocol 90 | * @param maddr ip address of the external interface 91 | * @param mport mapped port on the external interface, in host byte order. 92 | * @param daddr destination ip address 93 | * @param dport destination port, in host byte order. 94 | */ 95 | u8_t 96 | ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport); 97 | 98 | 99 | /** 100 | * Unregister port mapping on the external interface to internal interface. 101 | * 102 | * @param proto target protocol 103 | * @param maddr ip address of the external interface 104 | */ 105 | u8_t 106 | ip_portmap_remove(u8_t proto, u16_t mport); 107 | 108 | 109 | /** 110 | * Sets the NAPT timeout for TCP connections. 111 | * 112 | * @param secs timeout in secs 113 | */ 114 | void 115 | ip_napt_set_tcp_timeout(u32_t secs); 116 | 117 | 118 | /** 119 | * Sets the NAPT timeout for UDP 'connections'. 120 | * 121 | * @param secs timeout in secs 122 | */ 123 | void 124 | ip_napt_set_udp_timeout(u32_t secs); 125 | 126 | #endif /* IP_NAPT */ 127 | #endif /* IP_FORWARD */ 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | #endif /* __LWIP_NAPT_H__ */ 134 | -------------------------------------------------------------------------------- /user/web.h: -------------------------------------------------------------------------------- 1 | #define CONFIG_PAGE "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n\ 2 | \ 3 | \ 4 | \ 5 | \ 6 |

ESP WiFi NAT Router Config

\ 7 |
\ 8 | \ 16 |

STA Settings

\ 17 |
\ 18 | \ 19 | \ 20 | \ 21 | \ 22 | \ 23 | \ 24 | \ 25 | \ 26 | \ 27 | \ 28 | \ 29 | \ 30 | \ 31 | \ 32 | \ 33 | \ 34 | \ 35 |
SSID:
Password:
Automesh:
\ 36 |
\ 37 | \ 38 |

AP Settings

\ 39 |
\ 40 | \ 41 | \ 42 | \ 43 | \ 44 | \ 45 | \ 46 | \ 47 | \ 48 | \ 49 | \ 50 | \ 51 | \ 57 | \ 58 | \ 59 | \ 60 | \ 61 | \ 62 | \ 63 | \ 64 | \ 65 | \ 66 |
SSID:
Password:
Security:\ 52 | \ 56 |
Subnet:
\ 67 | \ 68 | Password: min. 8 chars
\ 69 |
\ 70 |
\ 71 | \ 72 |

Lock Config

\ 73 |
\ 74 | \ 75 | \ 76 | \ 77 | \ 78 | \ 79 | \ 80 | \ 81 | \ 82 | \ 83 |
Lock Device:
\ 84 |
\ 85 | \ 86 |

Device Management

\ 87 |
\ 88 | \ 89 | \ 90 | \ 91 | \ 92 | \ 93 |
Reset Device:
\ 94 |
\ 95 |
\ 96 | \ 97 | \ 98 | " 99 | 100 | #define LOCK_PAGE "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n\ 101 | \ 102 | \ 103 | \ 104 | \ 105 |

ESP WiFi NAT Router Config

\ 106 |
\ 107 | \ 115 |

Config Locked

\ 116 |
\ 117 | \ 118 | \ 119 | \ 120 | \ 121 | \ 122 | \ 123 | \ 124 | \ 125 | \ 126 | \ 127 |
Password:
\ 128 | \ 129 | Default: STA password to unlock
\ 130 |
\ 131 | \ 132 |
\ 133 | \ 134 | \ 135 | " 136 | -------------------------------------------------------------------------------- /include/driver/spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef SPI_APP_H 26 | #define SPI_APP_H 27 | 28 | #include "spi_register.h" 29 | #include "ets_sys.h" 30 | #include "osapi.h" 31 | //#include "uart.h" 32 | #include "os_type.h" 33 | 34 | //Define SPI hardware modules 35 | #define SPI 0 36 | #define HSPI 1 37 | 38 | #define SPI_CLK_USE_DIV 0 39 | #define SPI_CLK_80MHZ_NODIV 1 40 | 41 | #define SPI_BYTE_ORDER_HIGH_TO_LOW 1 42 | #define SPI_BYTE_ORDER_LOW_TO_HIGH 0 43 | 44 | #ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h 45 | #define CPU_CLK_FREQ 80*1000000 46 | #endif 47 | 48 | /* 49 | * Spec says maximum is 20Mhz, 50 | * so why are we running at 4??!! 51 | * 52 | * 1000000 PREDIV: 40 CNTDIV: 2 53 | * 2000000 PREDIV: 20 CNTDIV: 2 54 | * 2962962 PREDIV: 9 CNTDIV: 3 55 | * 4000000 PREDIV: 10 CNTDIV: 2 56 | * 5000000 PREDIV: 8 CNTDIV: 2 57 | * 5714285 PREDIV: 7 CNTDIV: 2 58 | * 6666666 PREDIV: 6 CNTDIV: 2 59 | * 8000000 PREDIV: 5 CNTDIV: 2 60 | * 8888888 PREDIV: 3 CNTDIV: 3 61 | * 10000000 PREDIV: 4 CNTDIV: 2 62 | * 11428571 PREDIV: 1 CNTDIV: 7 63 | * 13333333 PREDIV: 3 CNTDIV: 2 64 | * 16000000 PREDIV: 1 CNTDIV: 5 65 | * 20000000 PREDIV: 2 CNTDIV: 2 66 | * 26666666 PREDIV: 1 CNTDIV: 3 67 | * 40000000 PREDIV: 1 CNTDIV: 2 68 | */ 69 | //Define some default SPI clock settings 70 | #define SPI_CLK_PREDIV 10 71 | #define SPI_CLK_CNTDIV 2 72 | #define SPI_CLK_FREQ CPU_CLK_FREQ/(SPI_CLK_PREDIV*SPI_CLK_CNTDIV) // 80 / 20 = 4 MHz 73 | 74 | 75 | 76 | 77 | 78 | void spi_init(uint8 spi_no); 79 | void spi_mode(uint8 spi_no, uint8 spi_cpha,uint8 spi_cpol); 80 | void spi_init_gpio(uint8 spi_no, uint8 sysclk_as_spiclk); 81 | void spi_clock(uint8 spi_no, uint16 prediv, uint8 cntdiv); 82 | void spi_tx_byte_order(uint8 spi_no, uint8 byte_order); 83 | void spi_rx_byte_order(uint8 spi_no, uint8 byte_order); 84 | uint32 spi_transaction(uint8 spi_no, uint8 cmd_bits, uint16 cmd_data, uint32 addr_bits, uint32 addr_data, uint32 dout_bits, uint32 dout_data, uint32 din_bits, uint32 dummy_bits); 85 | 86 | //Expansion Macros 87 | #define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR 88 | 89 | #define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32) data, 0, 0) 90 | #define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32) data, 0, 0) 91 | #define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32) data, 0, 0) 92 | #define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32) data, 0, 0) 93 | 94 | #define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0) 95 | #define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0) 96 | #define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0) 97 | #define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0) 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /mqtt/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Tuan PM 3 | * Email: tuanpm@live.com 4 | * 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "utils.h" 39 | 40 | 41 | uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str) 42 | { 43 | uint8_t segs = 0; /* Segment count. */ 44 | uint8_t chcnt = 0; /* Character count within segment. */ 45 | uint8_t accum = 0; /* Accumulator for segment. */ 46 | /* Catch NULL pointer. */ 47 | if (str == 0) 48 | return 0; 49 | /* Process every character in string. */ 50 | 51 | while (*str != '\0') { 52 | /* Segment changeover. */ 53 | 54 | if (*str == '.') { 55 | /* Must have some digits in segment. */ 56 | if (chcnt == 0) 57 | return 0; 58 | /* Limit number of segments. */ 59 | if (++segs == 4) 60 | return 0; 61 | /* Reset segment values and restart loop. */ 62 | chcnt = accum = 0; 63 | str++; 64 | continue; 65 | } 66 | 67 | /* Check numeric. */ 68 | if ((*str < '0') || (*str > '9')) 69 | return 0; 70 | 71 | /* Accumulate and check segment. */ 72 | 73 | if ((accum = accum * 10 + *str - '0') > 255) 74 | return 0; 75 | /* Advance other segment specific stuff and continue loop. */ 76 | 77 | chcnt++; 78 | str++; 79 | } 80 | 81 | /* Check enough segments and enough characters in last segment. */ 82 | 83 | if (segs != 3) 84 | return 0; 85 | if (chcnt == 0) 86 | return 0; 87 | /* Address okay. */ 88 | 89 | return 1; 90 | } 91 | uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip) 92 | { 93 | 94 | /* The count of the number of bytes processed. */ 95 | int i; 96 | /* A pointer to the next digit to process. */ 97 | const char * start; 98 | 99 | start = str; 100 | for (i = 0; i < 4; i++) { 101 | /* The digit being processed. */ 102 | char c; 103 | /* The value of this byte. */ 104 | int n = 0; 105 | while (1) { 106 | c = * start; 107 | start++; 108 | if (c >= '0' && c <= '9') { 109 | n *= 10; 110 | n += c - '0'; 111 | } 112 | /* We insist on stopping at "." if we are still parsing 113 | the first, second, or third numbers. If we have reached 114 | the end of the numbers, we will allow any character. */ 115 | else if ((i < 3 && c == '.') || i == 3) { 116 | break; 117 | } 118 | else { 119 | return 0; 120 | } 121 | } 122 | if (n >= 256) { 123 | return 0; 124 | } 125 | ((uint8_t*)ip)[i] = n; 126 | } 127 | return 1; 128 | 129 | } 130 | uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s) 131 | { 132 | uint32_t value = 0, digit; 133 | int8_t c; 134 | 135 | while ((c = *s++)) { 136 | if ('0' <= c && c <= '9') 137 | digit = c - '0'; 138 | else if ('A' <= c && c <= 'F') 139 | digit = c - 'A' + 10; 140 | else if ('a' <= c && c <= 'f') 141 | digit = c - 'a' + 10; 142 | else break; 143 | 144 | value = (value << 4) | digit; 145 | } 146 | 147 | return value; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /easygpio/easygpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * easygpio.h 3 | * 4 | * Copyright (c) 2015, eadf (https://github.com/eadf) 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of Redis nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_ 33 | #define EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_ 34 | 35 | #include "c_types.h" 36 | 37 | typedef enum { 38 | EASYGPIO_INPUT=0, 39 | EASYGPIO_OUTPUT=1 40 | } EasyGPIO_PinMode; 41 | 42 | typedef enum { 43 | EASYGPIO_PULLUP=3, 44 | EASYGPIO_NOPULL=4 45 | } EasyGPIO_PullStatus; 46 | 47 | /** 48 | * Returns the gpio name and func for a specific pin. 49 | */ 50 | bool easygpio_getGPIONameFunc(uint8_t gpio_pin, uint32_t *gpio_name, uint8_t *gpio_func); 51 | 52 | /** 53 | * Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin. 54 | * The 'interruptArg' is the function argument that will be sent to your interruptHandler 55 | * (this way you can several interrupts with one interruptHandler) 56 | */ 57 | bool easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg); 58 | 59 | /** 60 | * Deatach the interrupt handler from the 'gpio_pin' pin. 61 | */ 62 | bool easygpio_detachInterrupt(uint8_t gpio_pin); 63 | 64 | /** 65 | * Returns the number of active pins in the gpioMask. 66 | */ 67 | uint8_t easygpio_countBits(uint32_t gpioMask); 68 | 69 | /** 70 | * Sets the 'gpio_pin' pin as a GPIO and enables/disables the pull-up on that pin. 71 | * 'pullStatus' has no effect on output pins or GPIO16 72 | */ 73 | bool easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode); 74 | 75 | /** 76 | * Enable or disable the internal pull up for a pin. 77 | */ 78 | bool easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus); 79 | 80 | /** 81 | * Uniform way of getting GPIO input value. Handles GPIO 0-16. 82 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 83 | * If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET(). 84 | */ 85 | uint8_t easygpio_inputGet(uint8_t gpio_pin); 86 | 87 | /** 88 | * Uniform way of setting GPIO output value. Handles GPIO 0-16. 89 | * 90 | * You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does. 91 | * Use easygpio_outputEnable() to change an input gpio to output mode. 92 | */ 93 | void easygpio_outputSet(uint8_t gpio_pin, uint8_t value); 94 | 95 | /** 96 | * Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16. 97 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 98 | * This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too. 99 | */ 100 | void easygpio_outputDisable(uint8_t gpio_pin); 101 | 102 | /** 103 | * Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16. 104 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 105 | * 106 | * This function: 107 | * - should only be used to convert a input pin into an output pin. 108 | * - is a little bit slower than easygpio_outputSet() so you should use that 109 | * function to just change output value. 110 | * - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too. 111 | */ 112 | void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value); 113 | 114 | #endif /* EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_ */ 115 | -------------------------------------------------------------------------------- /user/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_CONFIG_ 2 | #define _USER_CONFIG_ 3 | 4 | #define ESP_REPEATER_VERSION "V2.2.6" 5 | 6 | #define LOCAL_ACCESS 0x01 7 | #define REMOTE_ACCESS 0x02 8 | 9 | #define WIFI_SSID "ssid" 10 | #define WIFI_PASSWORD "password" 11 | 12 | #define WIFI_AP_SSID "MyAP" 13 | #define WIFI_AP_PASSWORD "none" 14 | 15 | #define MAX_CLIENTS 8 16 | #define MAX_DHCP 8 17 | 18 | // 19 | // Size of the console buffers 20 | // 21 | #define MAX_CON_SEND_SIZE 1300 22 | #define MAX_CON_CMD_SIZE 80 23 | 24 | // 25 | // Defines the default GPIO pin if you have a status LED connected to a GPIO pin 26 | // Any value > 16 disables this feature 27 | // (I don't know of any that don't --AJK) 28 | // 29 | #define STATUS_LED_GPIO 2 30 | 31 | // 32 | // Defines the default GPIO pin for HW factory reset (when this GPIO is pulled low for more than 3 secs) 33 | // Any value > 16 disables this feature 34 | // 35 | #define FACTORY_RESET_PIN 255 36 | 37 | // 38 | // Define this to 1 to support the "scan" command for AP search 39 | // 40 | #define ALLOW_SCANNING 1 41 | 42 | // 43 | // Define this to 1 to support the "ping" command for IP connectivity check 44 | // 45 | #define ALLOW_PING 1 46 | 47 | // 48 | // Define this to 1 to support the "sleep" command for power management and deep sleep 49 | // Requires a connection of GPIO16 and RST (probably not available on ESP01 modules) 50 | // 51 | #define ALLOW_SLEEP 1 52 | 53 | // 54 | // Define this to 1 to support a daily traffic limit 55 | // 56 | #define DAILY_LIMIT 0 57 | 58 | // 59 | // Define this to support the setting of the WiFi PHY mode 60 | // 61 | #define PHY_MODE 1 62 | 63 | // 64 | // Define this to 1 to support a loopback device (127.0.0.1) 65 | // 66 | #define HAVE_LOOPBACK 1 67 | 68 | // 69 | // Define this to 1 if you want to have access to the config console via TCP. 70 | // Ohterwise only local access via serial is possible 71 | // 72 | #define REMOTE_CONFIG 1 73 | #define CONSOLE_SERVER_PORT 7777 74 | 75 | // 76 | // Define this to 1 if you want to have access to the config via Web. 77 | // 78 | #define WEB_CONFIG 1 79 | #define WEB_CONFIG_PORT 80 80 | 81 | // 82 | // Define this to 1 if you want to have ACLs for the SoftAP. 83 | // 84 | #define ACLS 1 85 | 86 | // 87 | // Define this to 1 if you want to have OTA (Over the air) updates 88 | // 89 | #define OTAUPDATE 1 90 | 91 | // 92 | // Define this to 1 if you want to have QoS for the SoftAP. 93 | // 94 | #define TOKENBUCKET 1 95 | // Burst size (token bucket size) in seconds of average bitrate 96 | #define MAX_TOKEN_RATIO 4 97 | 98 | // 99 | // Define this to 1 if you want to offer monitoring access to all transmitted data between the soft AP and all STAs. 100 | // Packets are mirrored in pcap format to the given port. 101 | // CAUTION: this might be a privacy issue!!! 102 | // 103 | #define REMOTE_MONITORING 1 104 | 105 | #define MONITOR_BUFFER_SIZE 0x3c00 106 | 107 | // Define this if you want to cut packets short in case of too high data rate 108 | #define MONITOR_BUFFER_TIGHT 0x1000 109 | 110 | // Define this to 1 if you want to silently drop any packet that cannot be send to the monitor 111 | #define DROP_PACKET_IF_NOT_RECORDED 1 112 | 113 | // 114 | // 115 | // Define this to 1 if you want to have it work as a MQTT client 116 | // 117 | #define MQTT_CLIENT 1 118 | 119 | #define MQTT_BUF_SIZE 1024 120 | #define MQTT_KEEPALIVE 120 /*seconds*/ 121 | #define MQTT_RECONNECT_TIMEOUT 5 /*seconds*/ 122 | #define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/ 123 | //#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/ 124 | 125 | #define MQTT_PREFIX "/WiFi" 126 | #define MQTT_ID "ESPRouter" 127 | #define MQTT_REPORT_INTERVAL 15 /*seconds*/ 128 | 129 | // Define this if you want to get messages about GPIO pin status changes 130 | // #define USER_GPIO_IN 0 131 | 132 | // Define this if you want to set an output signal 133 | // #define USER_GPIO_OUT 12 134 | 135 | // Define this to 1 support WPA2 PEAP authentication (experimental) 136 | // 137 | #define WPA2_PEAP 1 138 | 139 | // 140 | // Define this to 1 to support an ENC28J60 Ethernet interface 141 | // Experimental feature - not yet stable 142 | // 143 | #define HAVE_ENC28J60 0 144 | 145 | // 146 | // Define this to 1 to support ENC28J60 DHCP server 147 | // Experimental feature - might not yet be stable 148 | // 149 | #define DCHPSERVER_ENC28J60 1 150 | 151 | // 152 | // Define this ESP GPIO, if you have the HW-RESET pin of the ENC28J60 connected to it 153 | // Undefine it, if you have no HW-RESET 154 | // 155 | #define ENC28J60_HW_RESET 4 156 | 157 | // 158 | // Define this to 1 if you want to be able to control GPIO pins from the command line 159 | // 160 | #define GPIO_CMDS 1 161 | 162 | // Internal 163 | 164 | typedef enum { 165 | SIG_DO_NOTHING = 0, SIG_START_SERVER = 1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_CONSOLE_TX_RAW, SIG_GPIO_INT, SIG_LOOPBACK 166 | } USER_SIGNALS; 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /mqtt/include/mqtt_msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: mqtt_msg.h 3 | * Author: Minh Tuan 4 | * 5 | * Created on July 12, 2014, 1:05 PM 6 | */ 7 | 8 | #ifndef MQTT_MSG_H 9 | #define MQTT_MSG_H 10 | #include "user_config.h" 11 | #include "c_types.h" 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* 17 | * Copyright (c) 2014, Stephen Robinson 18 | * All rights reserved. 19 | * 20 | * Redistribution and use in source and binary forms, with or without 21 | * modification, are permitted provided that the following conditions 22 | * are met: 23 | * 24 | * 1. Redistributions of source code must retain the above copyright 25 | * notice, this list of conditions and the following disclaimer. 26 | * 2. Redistributions in binary form must reproduce the above copyright 27 | * notice, this list of conditions and the following disclaimer in the 28 | * documentation and/or other materials provided with the distribution. 29 | * 3. Neither the name of the copyright holder nor the names of its 30 | * contributors may be used to endorse or promote products derived 31 | * from this software without specific prior written permission. 32 | * 33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 37 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 | * POSSIBILITY OF SUCH DAMAGE. 44 | * 45 | */ 46 | /* 7 6 5 4 3 2 1 0*/ 47 | /*| --- Message Type---- | DUP Flag | QoS Level | Retain | 48 | /* Remaining Length */ 49 | 50 | 51 | enum mqtt_message_type 52 | { 53 | MQTT_MSG_TYPE_CONNECT = 1, 54 | MQTT_MSG_TYPE_CONNACK = 2, 55 | MQTT_MSG_TYPE_PUBLISH = 3, 56 | MQTT_MSG_TYPE_PUBACK = 4, 57 | MQTT_MSG_TYPE_PUBREC = 5, 58 | MQTT_MSG_TYPE_PUBREL = 6, 59 | MQTT_MSG_TYPE_PUBCOMP = 7, 60 | MQTT_MSG_TYPE_SUBSCRIBE = 8, 61 | MQTT_MSG_TYPE_SUBACK = 9, 62 | MQTT_MSG_TYPE_UNSUBSCRIBE = 10, 63 | MQTT_MSG_TYPE_UNSUBACK = 11, 64 | MQTT_MSG_TYPE_PINGREQ = 12, 65 | MQTT_MSG_TYPE_PINGRESP = 13, 66 | MQTT_MSG_TYPE_DISCONNECT = 14 67 | }; 68 | 69 | enum mqtt_connect_return_code 70 | { 71 | CONNECTION_ACCEPTED = 0, 72 | CONNECTION_REFUSE_PROTOCOL, 73 | CONNECTION_REFUSE_ID_REJECTED, 74 | CONNECTION_REFUSE_SERVER_UNAVAILABLE, 75 | CONNECTION_REFUSE_BAD_USERNAME, 76 | CONNECTION_REFUSE_NOT_AUTHORIZED 77 | }; 78 | 79 | typedef struct mqtt_message 80 | { 81 | uint8_t* data; 82 | uint16_t length; 83 | 84 | } mqtt_message_t; 85 | 86 | typedef struct mqtt_connection 87 | { 88 | mqtt_message_t message; 89 | 90 | uint16_t message_id; 91 | uint8_t* buffer; 92 | uint16_t buffer_length; 93 | 94 | } mqtt_connection_t; 95 | 96 | typedef struct mqtt_connect_info 97 | { 98 | char* client_id; 99 | char* username; 100 | char* password; 101 | char* will_topic; 102 | char* will_message; 103 | uint32_t keepalive; 104 | int will_qos; 105 | int will_retain; 106 | int clean_session; 107 | 108 | } mqtt_connect_info_t; 109 | 110 | 111 | static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; } 112 | static inline int ICACHE_FLASH_ATTR mqtt_get_connect_return_code(uint8_t* buffer) { return buffer[3]; } 113 | static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; } 114 | static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; } 115 | static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } 116 | 117 | void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); 118 | int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length); 119 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); 120 | const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); 121 | uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length); 122 | 123 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); 124 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id); 125 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id); 126 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id); 127 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id); 128 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id); 129 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id); 130 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id); 131 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection); 132 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection); 133 | mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection); 134 | 135 | 136 | #ifdef __cplusplus 137 | } 138 | #endif 139 | 140 | #endif /* MQTT_MSG_H */ 141 | 142 | -------------------------------------------------------------------------------- /mqtt/include/mqtt.h: -------------------------------------------------------------------------------- 1 | /* mqtt.h 2 | * 3 | * Copyright (c) 2014-2015, Tuan PM 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef USER_AT_MQTT_H_ 31 | #define USER_AT_MQTT_H_ 32 | #include "user_config.h" 33 | #include "mqtt_msg.h" 34 | #include "user_interface.h" 35 | 36 | #include "queue.h" 37 | typedef struct mqtt_event_data_t 38 | { 39 | uint8_t type; 40 | const char* topic; 41 | const char* data; 42 | uint16_t topic_length; 43 | uint16_t data_length; 44 | uint16_t data_offset; 45 | } mqtt_event_data_t; 46 | 47 | typedef struct mqtt_state_t 48 | { 49 | uint16_t port; 50 | int auto_reconnect; 51 | mqtt_connect_info_t* connect_info; 52 | uint8_t* in_buffer; 53 | uint8_t* out_buffer; 54 | int in_buffer_length; 55 | int out_buffer_length; 56 | uint16_t message_length; 57 | uint16_t message_length_read; 58 | mqtt_message_t* outbound_message; 59 | mqtt_connection_t mqtt_connection; 60 | uint16_t pending_msg_id; 61 | int pending_msg_type; 62 | int pending_publish_qos; 63 | } mqtt_state_t; 64 | 65 | typedef enum { 66 | WIFI_INIT, 67 | WIFI_CONNECTING, 68 | WIFI_CONNECTING_ERROR, 69 | WIFI_CONNECTED, 70 | DNS_RESOLVE, 71 | TCP_DISCONNECTING, 72 | TCP_DISCONNECTED, 73 | TCP_RECONNECT_DISCONNECTING, 74 | TCP_RECONNECT_REQ, 75 | TCP_RECONNECT, 76 | TCP_CONNECTING, 77 | TCP_CONNECTING_ERROR, 78 | TCP_CONNECTED, 79 | MQTT_CONNECT_SEND, 80 | MQTT_CONNECT_SENDING, 81 | MQTT_SUBSCIBE_SEND, 82 | MQTT_SUBSCIBE_SENDING, 83 | MQTT_DATA, 84 | MQTT_KEEPALIVE_SEND, 85 | MQTT_PUBLISH_RECV, 86 | MQTT_PUBLISHING, 87 | MQTT_DELETING, 88 | MQTT_DELETED, 89 | } tConnState; 90 | 91 | typedef void (*MqttCallback)(uint32_t *args); 92 | typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh); 93 | 94 | typedef struct { 95 | struct espconn *pCon; 96 | uint8_t security; 97 | uint8_t* host; 98 | uint32_t port; 99 | ip_addr_t ip; 100 | mqtt_state_t mqtt_state; 101 | mqtt_connect_info_t connect_info; 102 | MqttCallback connectedCb; 103 | MqttCallback disconnectedCb; 104 | MqttCallback publishedCb; 105 | MqttCallback timeoutCb; 106 | MqttDataCallback dataCb; 107 | ETSTimer mqttTimer; 108 | uint32_t keepAliveTick; 109 | uint32_t reconnectTick; 110 | uint32_t sendTimeout; 111 | tConnState connState; 112 | QUEUE msgQueue; 113 | void* user_data; 114 | } MQTT_Client; 115 | 116 | #define SEC_NONSSL 0 117 | #define SEC_SSL 1 118 | 119 | #define MQTT_FLAG_CONNECTED 1 120 | #define MQTT_FLAG_READY 2 121 | #define MQTT_FLAG_EXIT 4 122 | 123 | #define MQTT_EVENT_TYPE_NONE 0 124 | #define MQTT_EVENT_TYPE_CONNECTED 1 125 | #define MQTT_EVENT_TYPE_DISCONNECTED 2 126 | #define MQTT_EVENT_TYPE_SUBSCRIBED 3 127 | #define MQTT_EVENT_TYPE_UNSUBSCRIBED 4 128 | #define MQTT_EVENT_TYPE_PUBLISH 5 129 | #define MQTT_EVENT_TYPE_PUBLISHED 6 130 | #define MQTT_EVENT_TYPE_EXITED 7 131 | #define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8 132 | 133 | void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security); 134 | BOOL ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession); 135 | void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient); 136 | void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain); 137 | void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb); 138 | void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb); 139 | void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb); 140 | void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb); 141 | void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb); 142 | BOOL ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos); 143 | BOOL ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic); 144 | void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient); 145 | void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient); 146 | BOOL ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain); 147 | 148 | #endif /* USER_AT_MQTT_H_ */ 149 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # 9 | # Changelog: 10 | # - 2014-10-06: Changed the variables to include the header file directory 11 | # - 2014-10-06: Added global var for the Xtensa tool root 12 | # - 2014-11-23: Updated for SDK 0.9.3 13 | # - 2014-12-25: Replaced esptool by esptool.py 14 | 15 | BUILD_AREA = $(CURDIR)/.. 16 | 17 | # Output directors to store intermediate compiled files 18 | # relative to the project directory 19 | BUILD_BASE = build 20 | FW_BASE = firmware 21 | 22 | # base directory for the compiler 23 | XTENSA_TOOLS_ROOT ?= $(BUILD_AREA)/esp-open-sdk/xtensa-lx106-elf/bin 24 | PATH := $(XTENSA_TOOLS_ROOT):$(PATH) 25 | 26 | # # base directory of the ESP8266 SDK package, absolute 27 | SDK_BASE ?= $(BUILD_AREA)/esp-open-sdk/sdk 28 | 29 | # # esptool.py path and port 30 | ESPTOOL ?= $(XTENSA_TOOLS_ROOT)/esptool.py 31 | ESPPORT ?= /dev/ttyUSB0 32 | ESPTOOLBAUD ?= 115200 33 | ESPTOOLOPTS = -ff 40m -fm dio -fs 32m 34 | 35 | # name for the target project 36 | TARGET = app 37 | 38 | # which modules (subdirectories) of the project to include in compiling 39 | MODULES = driver user mqtt easygpio 40 | #EXTRA_INCDIR = include $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include 41 | EXTRA_INCDIR = include 42 | 43 | #LIB_MODULES = mqtt 44 | 45 | # libraries used in this project, mainly provided by the SDK 46 | LIBS = c gcc hal pp phy net80211 lwip_open_napt wpa wpa2 main 47 | 48 | # compiler flags using during compilation of source files 49 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DLWIP_OPEN_SRC -DUSE_OPTIMIZE_PRINTF 50 | 51 | # linker flags used to generate the main object file 52 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -L. 53 | 54 | # linker script used for the above linkier step 55 | #LD_SCRIPT = eagle.app.v6.ld 56 | LD_SCRIPT1 = -Trom0.ld 57 | LD_SCRIPT2 = -Trom1.ld 58 | 59 | # various paths from the SDK used in this project 60 | SDK_LIBDIR = lib 61 | SDK_LDDIR = ld 62 | SDK_INCDIR = include include/json 63 | 64 | # we create two different files for uploading into the flash 65 | # these are the names and options to generate them 66 | FW_FILE_1_ADDR = 0x02000 67 | FW_FILE_2_ADDR = 0x82000 68 | 69 | # select which tools to use as compiler, librarian and linker 70 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 71 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 72 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 73 | 74 | 75 | 76 | #### 77 | #### no user configurable options below here 78 | #### 79 | SRC_DIR := $(MODULES) 80 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 81 | 82 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 83 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 84 | 85 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 86 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 87 | LIBS := $(addprefix -l,$(LIBS)) 88 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 89 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 90 | 91 | #LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 92 | 93 | INCDIR := $(addprefix -I,$(SRC_DIR)) 94 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 95 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 96 | 97 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 98 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 99 | RBOOT_FILE := $(addprefix $(FW_BASE)/,0x00000.bin) 100 | 101 | V ?= $(VERBOSE) 102 | ifeq ("$(V)","1") 103 | Q := 104 | vecho := @true 105 | else 106 | Q := @ 107 | vecho := @echo 108 | endif 109 | 110 | vpath %.c $(SRC_DIR) 111 | 112 | define compile-objects 113 | $1/%.o: %.c 114 | $(vecho) "CC $$<" 115 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 116 | endef 117 | 118 | .PHONY: all checkdirs clean 119 | 120 | #all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 121 | all: checkdirs $(FW_FILE_1) $(FW_FILE_2) $(RBOOT_FILE) $(FW_BASE)/sha1sums 122 | 123 | #$(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 124 | # $(vecho) "FW" $@ 125 | # $(Q) $(ESPTOOL) elf2image --version=2 $(TARGET_OUT) -o $@ 126 | 127 | #../esp-open-lwip/liblwip_open.a: 128 | # cd ../esp-open-lwip ; make -f Makefile.ajk all 129 | 130 | 131 | $(FW_FILE_1): $(APP_AR) 132 | $(Q) $(LD) -L$(BUILD_AREA)/esp-open-lwip -L$(SDK_LIBDIR) $(LD_SCRIPT1) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $(TARGET_OUT) 133 | $(ESPTOOL) elf2image --version=2 $(TARGET_OUT) -o $(FW_FILE_1) 134 | 135 | 136 | $(FW_FILE_2): $(APP_AR) 137 | $(Q) $(LD) -L$(BUILD_AREA)/esp-open-lwip -L$(SDK_LIBDIR) $(LD_SCRIPT2) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $(TARGET_OUT) 138 | $(ESPTOOL) elf2image --version=2 $(TARGET_OUT) -o $(FW_FILE_2) 139 | 140 | $(RBOOT_FILE): rboot.bin 141 | $(Q) cp rboot.bin $(RBOOT_FILE) 142 | 143 | 144 | $(FW_BASE)/sha1sums: $(APP_AR) $(FW_FILE_1) $(FW_FILE_2) $(RBOOT_FILE) 145 | $(Q) sha1sum $(FW_FILE_1) $(FW_FILE_2) $(RBOOT_FILE) > $(FW_BASE)/sha1sums 146 | 147 | $(APP_AR): $(OBJ) 148 | $(vecho) "AR $@" 149 | $(Q) $(AR) cru $@ $^ 150 | 151 | checkdirs: $(BUILD_DIR) $(FW_BASE) 152 | 153 | $(BUILD_DIR): 154 | $(Q) mkdir -p $@ 155 | 156 | $(FW_BASE): 157 | $(Q) mkdir -p $@ 158 | 159 | flash: $(FW_BASE)/sha1sums 160 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOLBAUD) write_flash $(ESPTOOLOPTS) 0x00000 $(RBOOT_FILE) $(FW_FILE_1_ADDR) $(FW_FILE_1) 161 | 162 | flash1: $(FW_BASE)/sha1sums 163 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOLBAUD) write_flash $(ESPTOOLOPTS) 0x00000 $(RBOOT_FILE) $(FW_FILE_2_ADDR) $(FW_FILE_2) 164 | 165 | flashboth: $(FW_BASE)/sha1sums 166 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOLBAUD) write_flash $(ESPTOOLOPTS) 0x00000 $(RBOOT_FILE) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 167 | 168 | clean: 169 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 170 | $(Q) find . -name "*~" -print0 | xargs -0 rm -rf 171 | 172 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 173 | -------------------------------------------------------------------------------- /user/ringbuf.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_RINGBUF_H 2 | #define INCLUDED_RINGBUF_H 3 | 4 | /* 5 | * ringbuf.h - C ring buffer (FIFO) interface. 6 | * 7 | * Written in 2011 by Drew Hess . 8 | * 9 | * To the extent possible under law, the author(s) have dedicated all 10 | * copyright and related and neighboring rights to this software to 11 | * the public domain worldwide. This software is distributed without 12 | * any warranty. 13 | * 14 | * You should have received a copy of the CC0 Public Domain Dedication 15 | * along with this software. If not, see 16 | * . 17 | */ 18 | 19 | /* 20 | * A byte-addressable ring buffer FIFO implementation. 21 | * 22 | * The ring buffer's head pointer points to the starting location 23 | * where data should be written when copying data *into* the buffer 24 | * (e.g., with ringbuf_read). The ring buffer's tail pointer points to 25 | * the starting location where data should be read when copying data 26 | * *from* the buffer (e.g., with ringbuf_write). 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | typedef struct ringbuf_t *ringbuf_t; 33 | 34 | /* 35 | * Create a new ring buffer with the given capacity (usable 36 | * bytes). Note that the actual internal buffer size may be one or 37 | * more bytes larger than the usable capacity, for bookkeeping. 38 | * 39 | * Returns the new ring buffer object, or 0 if there's not enough 40 | * memory to fulfill the request for the given capacity. 41 | */ 42 | ringbuf_t 43 | ringbuf_new(size_t capacity); 44 | 45 | /* 46 | * The size of the internal buffer, in bytes. One or more bytes may be 47 | * unusable in order to distinguish the "buffer full" state from the 48 | * "buffer empty" state. 49 | * 50 | * For the usable capacity of the ring buffer, use the 51 | * ringbuf_capacity function. 52 | */ 53 | size_t 54 | ringbuf_buffer_size(const struct ringbuf_t *rb); 55 | 56 | /* 57 | * Deallocate a ring buffer, and, as a side effect, set the pointer to 58 | * 0. 59 | */ 60 | void 61 | ringbuf_free(ringbuf_t *rb); 62 | 63 | /* 64 | * Reset a ring buffer to its initial state (empty). 65 | */ 66 | void 67 | ringbuf_reset(ringbuf_t rb); 68 | 69 | /* 70 | * The usable capacity of the ring buffer, in bytes. Note that this 71 | * value may be less than the ring buffer's internal buffer size, as 72 | * returned by ringbuf_buffer_size. 73 | */ 74 | size_t 75 | ringbuf_capacity(const struct ringbuf_t *rb); 76 | 77 | /* 78 | * The number of free/available bytes in the ring buffer. This value 79 | * is never larger than the ring buffer's usable capacity. 80 | */ 81 | size_t 82 | ringbuf_bytes_free(const struct ringbuf_t *rb); 83 | 84 | /* 85 | * The number of bytes currently being used in the ring buffer. This 86 | * value is never larger than the ring buffer's usable capacity. 87 | */ 88 | size_t 89 | ringbuf_bytes_used(const struct ringbuf_t *rb); 90 | 91 | int 92 | ringbuf_is_full(const struct ringbuf_t *rb); 93 | 94 | int 95 | ringbuf_is_empty(const struct ringbuf_t *rb); 96 | 97 | /* 98 | * Const access to the head and tail pointers of the ring buffer. 99 | */ 100 | const void * 101 | ringbuf_tail(const struct ringbuf_t *rb); 102 | 103 | const void * 104 | ringbuf_head(const struct ringbuf_t *rb); 105 | 106 | /* 107 | * Copy n bytes from a contiguous memory area src into the ring buffer 108 | * dst. Returns the ring buffer's new head pointer. 109 | * 110 | * It is possible to copy more data from src than is available in the 111 | * buffer; i.e., it's possible to overflow the ring buffer using this 112 | * function. When an overflow occurs, the state of the ring buffer is 113 | * guaranteed to be consistent, including the head and tail pointers; 114 | * old data will simply be overwritten in FIFO fashion, as 115 | * needed. However, note that, if calling the function results in an 116 | * overflow, the value of the ring buffer's tail pointer may be 117 | * different than it was before the function was called. 118 | */ 119 | void * 120 | ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count); 121 | 122 | /* 123 | * Copy n bytes from the ring buffer src, starting from its tail 124 | * pointer, into a contiguous memory area dst. Returns the value of 125 | * src's tail pointer after the copy is finished. 126 | * 127 | * Note that this copy is destructive with respect to the ring buffer: 128 | * the n bytes copied from the ring buffer are no longer available in 129 | * the ring buffer after the copy is complete, and the ring buffer 130 | * will have n more free bytes than it did before the function was 131 | * called. 132 | * 133 | * This function will *not* allow the ring buffer to underflow. If 134 | * count is greater than the number of bytes used in the ring buffer, 135 | * no bytes are copied, and the function will return 0. 136 | */ 137 | void * 138 | ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count); 139 | 140 | /* 141 | * Copy count bytes from ring buffer src, starting from its tail 142 | * pointer, into ring buffer dst. Returns dst's new head pointer after 143 | * the copy is finished. 144 | * 145 | * Note that this copy is destructive with respect to the ring buffer 146 | * src: any bytes copied from src into dst are no longer available in 147 | * src after the copy is complete, and src will have 'count' more free 148 | * bytes than it did before the function was called. 149 | * 150 | * It is possible to copy more data from src than is available in dst; 151 | * i.e., it's possible to overflow dst using this function. When an 152 | * overflow occurs, the state of dst is guaranteed to be consistent, 153 | * including the head and tail pointers; old data will simply be 154 | * overwritten in FIFO fashion, as needed. However, note that, if 155 | * calling the function results in an overflow, the value dst's tail 156 | * pointer may be different than it was before the function was 157 | * called. 158 | * 159 | * It is *not* possible to underflow src; if count is greater than the 160 | * number of bytes used in src, no bytes are copied, and the function 161 | * returns 0. 162 | */ 163 | void * 164 | ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count); 165 | 166 | #endif /* INCLUDED_RINGBUF_H */ 167 | 168 | -------------------------------------------------------------------------------- /user/rboot.h: -------------------------------------------------------------------------------- 1 | #ifndef __RBOOT_H__ 2 | #define __RBOOT_H__ 3 | 4 | ////////////////////////////////////////////////// 5 | // rBoot open source boot loader for ESP8266. 6 | // Copyright 2015 Richard A Burton 7 | // richardaburton@gmail.com 8 | // See license.txt for license terms. 9 | ////////////////////////////////////////////////// 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #include // uint* types 16 | 17 | #ifdef RBOOT_INTEGRATION 18 | #include 19 | #endif 20 | 21 | // uncomment to use only c code 22 | // if you aren't using gcc you may need to do this 23 | //#define BOOT_NO_ASM 24 | 25 | // uncomment to have a checksum on the boot config 26 | //#define BOOT_CONFIG_CHKSUM 27 | 28 | // uncomment to enable big flash support (>1MB) 29 | //#define BOOT_BIG_FLASH 30 | 31 | // uncomment to enable 2 way communication between 32 | // rBoot and the user app via the esp rtc data area 33 | //#define BOOT_RTC_ENABLED 34 | 35 | // uncomment to enable GPIO booting of specific rom 36 | // (specified in rBoot config block) 37 | // cannot be used at same time as BOOT_GPIO_SKIP_ENABLED 38 | //#define BOOT_GPIO_ENABLED 39 | 40 | // uncomment to enable GPIO rom skip mode, trigger 41 | // GPIO at boot time to skip to next rom 42 | // cannot be used at same time as BOOT_GPIO_ENABLED 43 | //#define BOOT_GPIO_SKIP_ENABLED 44 | 45 | // set the GPIO pin used by GPIO modes above (will default 46 | // to 16 if not manually set), only applicable when 47 | // BOOT_GPIO_ENABLED or BOOT_GPIO_SKIP_ENABLED is enabled 48 | //#define BOOT_GPIO_NUM 16 49 | 50 | // uncomment to include .irom0.text section in the checksum 51 | // roms must be built with esptool2 using -iromchksum option 52 | //#define BOOT_IROM_CHKSUM 53 | 54 | // uncomment to add a boot delay, allows you time to connect 55 | // a terminal before rBoot starts to run and output messages 56 | // value is in microseconds 57 | //#define BOOT_DELAY_MICROS 2000000 58 | 59 | // define your own default custom rBoot config, used on 60 | // first boot and in case of corruption, standard fields 61 | // (magic, version and chksum (if applicable) are included 62 | // for you automatically), see example at end of this file 63 | // and customise as required 64 | //#define BOOT_CUSTOM_DEFAULT_CONFIG 65 | 66 | // max number of roms in the config (defaults to 4), higher 67 | // values will use more ram at run time 68 | //#define MAX_ROMS 4 69 | 70 | 71 | // you should not need to modify anything below this line, 72 | // except default_config() right at the bottom of the file 73 | 74 | 75 | #define CHKSUM_INIT 0xef 76 | 77 | #define SECTOR_SIZE 0x1000 78 | #define BOOT_CONFIG_SECTOR 1 79 | 80 | #define BOOT_CONFIG_MAGIC 0xe1 81 | #define BOOT_CONFIG_VERSION 0x01 82 | 83 | #define MODE_STANDARD 0x00 84 | #define MODE_GPIO_ROM 0x01 85 | #define MODE_TEMP_ROM 0x02 86 | #define MODE_GPIO_ERASES_SDKCONFIG 0x04 87 | #define MODE_GPIO_SKIP 0x08 88 | 89 | #define RBOOT_RTC_MAGIC 0x2334ae68 90 | #define RBOOT_RTC_READ 1 91 | #define RBOOT_RTC_WRITE 0 92 | #define RBOOT_RTC_ADDR 64 93 | 94 | // defaults for unset user options 95 | #ifndef BOOT_GPIO_NUM 96 | #define BOOT_GPIO_NUM 16 97 | #endif 98 | 99 | #ifndef MAX_ROMS 100 | #define MAX_ROMS 4 101 | #endif 102 | 103 | /** @brief Structure containing rBoot configuration 104 | * @note ROM addresses must be multiples of 0x1000 (flash sector aligned). 105 | * Without BOOT_BIG_FLASH only the first 8Mbit (1MB) of the chip will 106 | * be memory mapped so ROM slots containing .irom0.text sections must 107 | * remain below 0x100000. Slots beyond this will only be accessible via 108 | * spi read calls, so use these for stored resources, not code. With 109 | * BOOT_BIG_FLASH the flash will be mapped in chunks of 8MBit (1MB), so 110 | * ROMs can be anywhere, but must not straddle two 8MBit (1MB) blocks. 111 | * @ingroup rboot 112 | */ 113 | typedef struct { 114 | uint8 magic; ///< Our magic, identifies rBoot configuration - should be BOOT_CONFIG_MAGIC 115 | uint8 version; ///< Version of configuration structure - should be BOOT_CONFIG_VERSION 116 | uint8 mode; ///< Boot loader mode (MODE_STANDARD | MODE_GPIO_ROM | MODE_GPIO_SKIP) 117 | uint8 current_rom; ///< Currently selected ROM (will be used for next standard boot) 118 | uint8 gpio_rom; ///< ROM to use for GPIO boot (hardware switch) with mode set to MODE_GPIO_ROM 119 | uint8 count; ///< Quantity of ROMs available to boot 120 | uint8 unused[2]; ///< Padding (not used) 121 | uint32 roms[MAX_ROMS]; ///< Flash addresses of each ROM 122 | #ifdef BOOT_CONFIG_CHKSUM 123 | uint8 chksum; ///< Checksum of this configuration structure (if BOOT_CONFIG_CHKSUM defined) 124 | #endif 125 | } rboot_config; 126 | 127 | #ifdef BOOT_RTC_ENABLED 128 | /** @brief Structure containing rBoot status/control data 129 | * @note This structure is used to, optionally, communicate between rBoot and 130 | * the user app. It is stored in the ESP RTC data area. 131 | * @ingroup rboot 132 | */ 133 | typedef struct { 134 | uint32 magic; ///< Magic, identifies rBoot RTC data - should be RBOOT_RTC_MAGIC 135 | uint8 next_mode; ///< The next boot mode, defaults to MODE_STANDARD - can be set to MODE_TEMP_ROM 136 | uint8 last_mode; ///< The last (this) boot mode - can be MODE_STANDARD, MODE_GPIO_ROM or MODE_TEMP_ROM 137 | uint8 last_rom; ///< The last (this) boot rom number 138 | uint8 temp_rom; ///< The next boot rom number when next_mode set to MODE_TEMP_ROM 139 | uint8 chksum; ///< Checksum of this structure this will be updated for you passed to the API 140 | } rboot_rtc_data; 141 | #endif 142 | 143 | // override function to create default config, must be placed after type 144 | // and constant defines as it uses some of them, flashsize is the used size 145 | // (may be smaller than actual flash size if big flash mode is not enabled, 146 | // or just plain wrong if the device has not been programmed correctly!) 147 | #ifdef BOOT_CUSTOM_DEFAULT_CONFIG 148 | static uint8 default_config(rboot_config *romconf, uint32 flashsize) { 149 | romconf->count = 2; 150 | romconf->roms[0] = SECTOR_SIZE * (BOOT_CONFIG_SECTOR + 1); 151 | romconf->roms[1] = (flashsize / 2) + (SECTOR_SIZE * (BOOT_CONFIG_SECTOR + 1)); 152 | } 153 | #endif 154 | 155 | #ifdef __cplusplus 156 | } 157 | #endif 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /user/rboot-api.h: -------------------------------------------------------------------------------- 1 | #ifndef __RBOOT_API_H__ 2 | #define __RBOOT_API_H__ 3 | 4 | /** @defgroup rboot rBoot API 5 | * @brief rBoot for ESP8266 API allows runtime code to access the rBoot configuration. 6 | * Configuration may be read to use within the main firmware or updated to 7 | * affect next boot behavior. 8 | * @copyright 2015 Richard A Burton 9 | * @author richardaburton@gmail.com 10 | * @author OTA code based on SDK sample from Espressif 11 | * @license See licence.txt for license terms. 12 | * @{ 13 | */ 14 | 15 | #include "rboot.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** @brief Structure defining flash write status 22 | * @note The user application should not modify the contents of this 23 | * structure. 24 | * @see rboot_write_flash 25 | */ 26 | typedef struct { 27 | uint32 start_addr; 28 | uint32 start_sector; 29 | //uint32 max_sector_count; 30 | int32 last_sector_erased; 31 | uint8 extra_count; 32 | uint8 extra_bytes[4]; 33 | } rboot_write_status; 34 | 35 | /** @brief Read rBoot configuration from flash 36 | * @retval rboot_config Copy of the rBoot configuration 37 | * @note Returns rboot_config (defined in rboot.h) allowing you to modify any values 38 | * in it, including the ROM layout. 39 | */ 40 | rboot_config ICACHE_FLASH_ATTR rboot_get_config(void); 41 | 42 | /** @brief Write rBoot configuration to flash memory 43 | * @param conf pointer to a rboot_config structure containing configuration to save 44 | * @retval bool True on success 45 | * @note Saves the rboot_config structure back to configuration sector (BOOT_CONFIG_SECTOR) 46 | * of the flash, while maintaining the contents of the rest of the sector. 47 | * You can use the rest of this sector for your app settings, as long as you 48 | * protect this structure when you do so. 49 | */ 50 | bool ICACHE_FLASH_ATTR rboot_set_config(rboot_config *conf); 51 | 52 | /** @brief Get index of current ROM 53 | * @retval uint8 Index of the current ROM 54 | * @note Get the currently selected boot ROM (this will be the currently 55 | * running ROM, as long as you haven't changed it since boot or rBoot 56 | * booted the rom in temporary boot mode, see rboot_get_last_boot_rom). 57 | */ 58 | uint8 ICACHE_FLASH_ATTR rboot_get_current_rom(void); 59 | 60 | /** @brief Set the index of current ROM 61 | * @param rom The index of the ROM to use on next boot 62 | * @retval bool True on success 63 | * @note Set the current boot ROM, which will be used when next restarted. 64 | * @note This function re-writes the whole configuration to flash memory (not just the current ROM index) 65 | */ 66 | bool ICACHE_FLASH_ATTR rboot_set_current_rom(uint8 rom); 67 | 68 | /** @brief Initialise flash write process 69 | * @param start_addr Address on the SPI flash to begin write to 70 | * @note Call once before starting to pass data to write to flash memory with rboot_write_flash function. 71 | * start_addr is the address on the SPI flash to write from. Returns a status structure which 72 | * must be passed back on each write. The contents of the structure should not 73 | * be modified by the calling code. 74 | */ 75 | rboot_write_status ICACHE_FLASH_ATTR rboot_write_init(uint32 start_addr); 76 | 77 | /** @brief Complete flash write process 78 | * @param status Pointer to rboot_write_status structure defining the write status 79 | * @note Call at the completion of flash writing. This ensures any 80 | * outstanding bytes are written (if data so far hasn't been a multiple 81 | * of 4 bytes there will be a few bytes unwritten, until you call 82 | * this function). 83 | */ 84 | bool ICACHE_FLASH_ATTR rboot_write_end(rboot_write_status *status); 85 | 86 | /** @brief Write data to flash memory 87 | * @param status Pointer to rboot_write_status structure defining the write status 88 | * @param data Pointer to a block of uint8 data elements to be written to flash 89 | * @param len Quantity of uint8 data elements to write to flash 90 | * @note Call repeatedly to write data to the flash, starting at the address 91 | * specified on the prior call to rboot_write_init. Current write position is 92 | * tracked automatically. This method is likely to be called each time a packet 93 | * of OTA data is received over the network. 94 | * @note Call rboot_write_init before calling this function to get the rboot_write_status structure 95 | */ 96 | bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len); 97 | 98 | #ifdef BOOT_RTC_ENABLED 99 | /** @brief Get rBoot status/control data from RTC data area 100 | * @param rtc Pointer to a rboot_rtc_data structure to be populated 101 | * @retval bool True on success, false if no data/invalid checksum (in which 102 | * case do not use the contents of the structure) 103 | */ 104 | bool ICACHE_FLASH_ATTR rboot_get_rtc_data(rboot_rtc_data *rtc); 105 | 106 | /** @brief Set rBoot status/control data in RTC data area 107 | * @param rtc pointer to a rboot_rtc_data structure 108 | * @retval bool True on success 109 | * @note The checksum will be calculated automatically for you. 110 | */ 111 | bool ICACHE_FLASH_ATTR rboot_set_rtc_data(rboot_rtc_data *rtc); 112 | 113 | /** @brief Set temporary rom for next boot 114 | * @param rom Rom slot number for next boot 115 | * @retval bool True on success 116 | * @note This call will tell rBoot to temporarily boot the specified rom on 117 | * the next boot. This is does not update the stored rBoot config on 118 | * the flash, so after another reset it will boot back to the original 119 | * rom. 120 | */ 121 | bool ICACHE_FLASH_ATTR rboot_set_temp_rom(uint8 rom); 122 | 123 | /** @brief Get the last booted rom slot number 124 | * @param rom Pointer to rom slot number variable to populate 125 | * @retval bool True on success, false if no data/invalid checksum 126 | * @note This will find the currently running rom, even if booted as a 127 | * temporary rom. 128 | */ 129 | bool ICACHE_FLASH_ATTR rboot_get_last_boot_rom(uint8 *rom); 130 | 131 | /** @brief Get the last boot mode 132 | * @param mode Pointer to mode variable to populate 133 | * @retval bool True on success, false if no data/invalid checksum 134 | * @note This will indicate the type of boot: MODE_STANDARD, MODE_GPIO_ROM or 135 | * MODE_TEMP_ROM. 136 | */ 137 | bool ICACHE_FLASH_ATTR rboot_get_last_boot_mode(uint8 *mode); 138 | #endif 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | /** @} */ 145 | #endif 146 | -------------------------------------------------------------------------------- /rom0.ld: -------------------------------------------------------------------------------- 1 | /* This linker script generated from xt-genldscripts.tpp for LSP . */ 2 | /* Linker Script for ld -N */ 3 | MEMORY 4 | { 5 | dport0_0_seg : org = 0x3FF00000, len = 0x10 6 | dram0_0_seg : org = 0x3FFE8000, len = 0x14000 7 | iram1_0_seg : org = 0x40100000, len = 0x8000 8 | irom0_0_seg : org = 0x40202010, len = 0x5C000 9 | } 10 | 11 | PHDRS 12 | { 13 | dport0_0_phdr PT_LOAD; 14 | dram0_0_phdr PT_LOAD; 15 | dram0_0_bss_phdr PT_LOAD; 16 | iram1_0_phdr PT_LOAD; 17 | irom0_0_phdr PT_LOAD; 18 | } 19 | 20 | 21 | /* Default entry point: */ 22 | ENTRY(call_user_start) 23 | EXTERN(_DebugExceptionVector) 24 | EXTERN(_DoubleExceptionVector) 25 | EXTERN(_KernelExceptionVector) 26 | EXTERN(_NMIExceptionVector) 27 | EXTERN(_UserExceptionVector) 28 | PROVIDE(_memmap_vecbase_reset = 0x40000000); 29 | /* Various memory-map dependent cache attribute settings: */ 30 | _memmap_cacheattr_wb_base = 0x00000110; 31 | _memmap_cacheattr_wt_base = 0x00000110; 32 | _memmap_cacheattr_bp_base = 0x00000220; 33 | _memmap_cacheattr_unused_mask = 0xFFFFF00F; 34 | _memmap_cacheattr_wb_trapnull = 0x2222211F; 35 | _memmap_cacheattr_wba_trapnull = 0x2222211F; 36 | _memmap_cacheattr_wbna_trapnull = 0x2222211F; 37 | _memmap_cacheattr_wt_trapnull = 0x2222211F; 38 | _memmap_cacheattr_bp_trapnull = 0x2222222F; 39 | _memmap_cacheattr_wb_strict = 0xFFFFF11F; 40 | _memmap_cacheattr_wt_strict = 0xFFFFF11F; 41 | _memmap_cacheattr_bp_strict = 0xFFFFF22F; 42 | _memmap_cacheattr_wb_allvalid = 0x22222112; 43 | _memmap_cacheattr_wt_allvalid = 0x22222112; 44 | _memmap_cacheattr_bp_allvalid = 0x22222222; 45 | PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); 46 | 47 | SECTIONS 48 | { 49 | 50 | .dport0.rodata : ALIGN(4) 51 | { 52 | _dport0_rodata_start = ABSOLUTE(.); 53 | *(.dport0.rodata) 54 | *(.dport.rodata) 55 | _dport0_rodata_end = ABSOLUTE(.); 56 | } >dport0_0_seg :dport0_0_phdr 57 | 58 | .dport0.literal : ALIGN(4) 59 | { 60 | _dport0_literal_start = ABSOLUTE(.); 61 | *(.dport0.literal) 62 | *(.dport.literal) 63 | _dport0_literal_end = ABSOLUTE(.); 64 | } >dport0_0_seg :dport0_0_phdr 65 | 66 | .dport0.data : ALIGN(4) 67 | { 68 | _dport0_data_start = ABSOLUTE(.); 69 | *(.dport0.data) 70 | *(.dport.data) 71 | _dport0_data_end = ABSOLUTE(.); 72 | } >dport0_0_seg :dport0_0_phdr 73 | 74 | .data : ALIGN(4) 75 | { 76 | _data_start = ABSOLUTE(.); 77 | *(.data) 78 | *(.data.*) 79 | *(.gnu.linkonce.d.*) 80 | *(.data1) 81 | *(.sdata) 82 | *(.sdata.*) 83 | *(.gnu.linkonce.s.*) 84 | *(.sdata2) 85 | *(.sdata2.*) 86 | *(.gnu.linkonce.s2.*) 87 | *(.jcr) 88 | _data_end = ABSOLUTE(.); 89 | } >dram0_0_seg :dram0_0_phdr 90 | 91 | .rodata : ALIGN(4) 92 | { 93 | _rodata_start = ABSOLUTE(.); 94 | *(.sdk.version) 95 | *(.rodata) 96 | *(.rodata.*) 97 | *(.gnu.linkonce.r.*) 98 | *(.rodata1) 99 | __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); 100 | *(.xt_except_table) 101 | *(.gcc_except_table) 102 | *(.gnu.linkonce.e.*) 103 | *(.gnu.version_r) 104 | *(.eh_frame) 105 | /* C++ constructor and destructor tables, properly ordered: */ 106 | KEEP (*crtbegin.o(.ctors)) 107 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 108 | KEEP (*(SORT(.ctors.*))) 109 | KEEP (*(.ctors)) 110 | KEEP (*crtbegin.o(.dtors)) 111 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 112 | KEEP (*(SORT(.dtors.*))) 113 | KEEP (*(.dtors)) 114 | /* C++ exception handlers table: */ 115 | __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); 116 | *(.xt_except_desc) 117 | *(.gnu.linkonce.h.*) 118 | __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); 119 | *(.xt_except_desc_end) 120 | *(.dynamic) 121 | *(.gnu.version_d) 122 | . = ALIGN(4); /* this table MUST be 4-byte aligned */ 123 | _bss_table_start = ABSOLUTE(.); 124 | LONG(_bss_start) 125 | LONG(_bss_end) 126 | _bss_table_end = ABSOLUTE(.); 127 | _rodata_end = ABSOLUTE(.); 128 | } >dram0_0_seg :dram0_0_phdr 129 | 130 | .bss ALIGN(8) (NOLOAD) : ALIGN(4) 131 | { 132 | . = ALIGN (8); 133 | _bss_start = ABSOLUTE(.); 134 | *(.dynsbss) 135 | *(.sbss) 136 | *(.sbss.*) 137 | *(.gnu.linkonce.sb.*) 138 | *(.scommon) 139 | *(.sbss2) 140 | *(.sbss2.*) 141 | *(.gnu.linkonce.sb2.*) 142 | *(.dynbss) 143 | *(.bss) 144 | *(.bss.*) 145 | *(.gnu.linkonce.b.*) 146 | *(COMMON) 147 | . = ALIGN (8); 148 | _bss_end = ABSOLUTE(.); 149 | _heap_start = ABSOLUTE(.); 150 | /* _stack_sentry = ALIGN(0x8); */ 151 | } >dram0_0_seg :dram0_0_bss_phdr 152 | /* __stack = 0x3ffc8000; */ 153 | 154 | .irom0.text : ALIGN(4) 155 | { 156 | _irom0_text_start = ABSOLUTE(.); 157 | 158 | *libat.a:(.literal.* .text.*) 159 | *libcrypto.a:(.literal.* .text.*) 160 | *libespnow.a:(.literal.* .text.*) 161 | *libjson.a:(.literal.* .text.*) 162 | *liblwip.a:(.literal.* .text.*) 163 | *libmesh.a:(.literal.* .text.*) 164 | *libnet80211.a:(.literal.* .text.*) 165 | *libsmartconfig.a:(.literal.* .text.*) 166 | *libssl.a:(.literal.* .text.*) 167 | *libupgrade.a:(.literal.* .text.*) 168 | *libwpa.a:(.literal.* .text.*) 169 | *libwpa2.a:(.literal.* .text.*) 170 | *libwps.a:(.literal.* .text.*) 171 | 172 | *libmbedtls.a:(.literal.* .text.*) 173 | 174 | *libm.a:(.literal .text .literal.* .text.*) 175 | 176 | *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) 177 | _irom0_text_end = ABSOLUTE(.); 178 | } >irom0_0_seg :irom0_0_phdr 179 | 180 | .text : ALIGN(4) 181 | { 182 | _stext = .; 183 | _text_start = ABSOLUTE(.); 184 | *(.UserEnter.text) 185 | . = ALIGN(16); 186 | *(.DebugExceptionVector.text) 187 | . = ALIGN(16); 188 | *(.NMIExceptionVector.text) 189 | . = ALIGN(16); 190 | *(.KernelExceptionVector.text) 191 | LONG(0) 192 | LONG(0) 193 | LONG(0) 194 | LONG(0) 195 | . = ALIGN(16); 196 | *(.UserExceptionVector.text) 197 | LONG(0) 198 | LONG(0) 199 | LONG(0) 200 | LONG(0) 201 | . = ALIGN(16); 202 | *(.DoubleExceptionVector.text) 203 | LONG(0) 204 | LONG(0) 205 | LONG(0) 206 | LONG(0) 207 | . = ALIGN (16); 208 | *(.entry.text) 209 | *(.init.literal) 210 | *(.init) 211 | *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) 212 | *(.fini.literal) 213 | *(.fini) 214 | *(.gnu.version) 215 | _text_end = ABSOLUTE(.); 216 | _etext = .; 217 | } >iram1_0_seg :iram1_0_phdr 218 | 219 | .lit4 : ALIGN(4) 220 | { 221 | _lit4_start = ABSOLUTE(.); 222 | *(*.lit4) 223 | *(.lit4.*) 224 | *(.gnu.linkonce.lit4.*) 225 | _lit4_end = ABSOLUTE(.); 226 | } >iram1_0_seg :iram1_0_phdr 227 | } 228 | 229 | /* get ROM code address */ 230 | INCLUDE "eagle.rom.addr.v6.ld" 231 | -------------------------------------------------------------------------------- /rom1.ld: -------------------------------------------------------------------------------- 1 | /* This linker script generated from xt-genldscripts.tpp for LSP . */ 2 | /* Linker Script for ld -N */ 3 | MEMORY 4 | { 5 | dport0_0_seg : org = 0x3FF00000, len = 0x10 6 | dram0_0_seg : org = 0x3FFE8000, len = 0x14000 7 | iram1_0_seg : org = 0x40100000, len = 0x8000 8 | irom0_0_seg : org = 0x40282010, len = 0x5C000 9 | } 10 | 11 | PHDRS 12 | { 13 | dport0_0_phdr PT_LOAD; 14 | dram0_0_phdr PT_LOAD; 15 | dram0_0_bss_phdr PT_LOAD; 16 | iram1_0_phdr PT_LOAD; 17 | irom0_0_phdr PT_LOAD; 18 | } 19 | 20 | 21 | /* Default entry point: */ 22 | ENTRY(call_user_start) 23 | EXTERN(_DebugExceptionVector) 24 | EXTERN(_DoubleExceptionVector) 25 | EXTERN(_KernelExceptionVector) 26 | EXTERN(_NMIExceptionVector) 27 | EXTERN(_UserExceptionVector) 28 | PROVIDE(_memmap_vecbase_reset = 0x40000000); 29 | /* Various memory-map dependent cache attribute settings: */ 30 | _memmap_cacheattr_wb_base = 0x00000110; 31 | _memmap_cacheattr_wt_base = 0x00000110; 32 | _memmap_cacheattr_bp_base = 0x00000220; 33 | _memmap_cacheattr_unused_mask = 0xFFFFF00F; 34 | _memmap_cacheattr_wb_trapnull = 0x2222211F; 35 | _memmap_cacheattr_wba_trapnull = 0x2222211F; 36 | _memmap_cacheattr_wbna_trapnull = 0x2222211F; 37 | _memmap_cacheattr_wt_trapnull = 0x2222211F; 38 | _memmap_cacheattr_bp_trapnull = 0x2222222F; 39 | _memmap_cacheattr_wb_strict = 0xFFFFF11F; 40 | _memmap_cacheattr_wt_strict = 0xFFFFF11F; 41 | _memmap_cacheattr_bp_strict = 0xFFFFF22F; 42 | _memmap_cacheattr_wb_allvalid = 0x22222112; 43 | _memmap_cacheattr_wt_allvalid = 0x22222112; 44 | _memmap_cacheattr_bp_allvalid = 0x22222222; 45 | PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); 46 | 47 | SECTIONS 48 | { 49 | 50 | .dport0.rodata : ALIGN(4) 51 | { 52 | _dport0_rodata_start = ABSOLUTE(.); 53 | *(.dport0.rodata) 54 | *(.dport.rodata) 55 | _dport0_rodata_end = ABSOLUTE(.); 56 | } >dport0_0_seg :dport0_0_phdr 57 | 58 | .dport0.literal : ALIGN(4) 59 | { 60 | _dport0_literal_start = ABSOLUTE(.); 61 | *(.dport0.literal) 62 | *(.dport.literal) 63 | _dport0_literal_end = ABSOLUTE(.); 64 | } >dport0_0_seg :dport0_0_phdr 65 | 66 | .dport0.data : ALIGN(4) 67 | { 68 | _dport0_data_start = ABSOLUTE(.); 69 | *(.dport0.data) 70 | *(.dport.data) 71 | _dport0_data_end = ABSOLUTE(.); 72 | } >dport0_0_seg :dport0_0_phdr 73 | 74 | .data : ALIGN(4) 75 | { 76 | _data_start = ABSOLUTE(.); 77 | *(.data) 78 | *(.data.*) 79 | *(.gnu.linkonce.d.*) 80 | *(.data1) 81 | *(.sdata) 82 | *(.sdata.*) 83 | *(.gnu.linkonce.s.*) 84 | *(.sdata2) 85 | *(.sdata2.*) 86 | *(.gnu.linkonce.s2.*) 87 | *(.jcr) 88 | _data_end = ABSOLUTE(.); 89 | } >dram0_0_seg :dram0_0_phdr 90 | 91 | .rodata : ALIGN(4) 92 | { 93 | _rodata_start = ABSOLUTE(.); 94 | *(.sdk.version) 95 | *(.rodata) 96 | *(.rodata.*) 97 | *(.gnu.linkonce.r.*) 98 | *(.rodata1) 99 | __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); 100 | *(.xt_except_table) 101 | *(.gcc_except_table) 102 | *(.gnu.linkonce.e.*) 103 | *(.gnu.version_r) 104 | *(.eh_frame) 105 | /* C++ constructor and destructor tables, properly ordered: */ 106 | KEEP (*crtbegin.o(.ctors)) 107 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 108 | KEEP (*(SORT(.ctors.*))) 109 | KEEP (*(.ctors)) 110 | KEEP (*crtbegin.o(.dtors)) 111 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 112 | KEEP (*(SORT(.dtors.*))) 113 | KEEP (*(.dtors)) 114 | /* C++ exception handlers table: */ 115 | __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); 116 | *(.xt_except_desc) 117 | *(.gnu.linkonce.h.*) 118 | __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); 119 | *(.xt_except_desc_end) 120 | *(.dynamic) 121 | *(.gnu.version_d) 122 | . = ALIGN(4); /* this table MUST be 4-byte aligned */ 123 | _bss_table_start = ABSOLUTE(.); 124 | LONG(_bss_start) 125 | LONG(_bss_end) 126 | _bss_table_end = ABSOLUTE(.); 127 | _rodata_end = ABSOLUTE(.); 128 | } >dram0_0_seg :dram0_0_phdr 129 | 130 | .bss ALIGN(8) (NOLOAD) : ALIGN(4) 131 | { 132 | . = ALIGN (8); 133 | _bss_start = ABSOLUTE(.); 134 | *(.dynsbss) 135 | *(.sbss) 136 | *(.sbss.*) 137 | *(.gnu.linkonce.sb.*) 138 | *(.scommon) 139 | *(.sbss2) 140 | *(.sbss2.*) 141 | *(.gnu.linkonce.sb2.*) 142 | *(.dynbss) 143 | *(.bss) 144 | *(.bss.*) 145 | *(.gnu.linkonce.b.*) 146 | *(COMMON) 147 | . = ALIGN (8); 148 | _bss_end = ABSOLUTE(.); 149 | _heap_start = ABSOLUTE(.); 150 | /* _stack_sentry = ALIGN(0x8); */ 151 | } >dram0_0_seg :dram0_0_bss_phdr 152 | /* __stack = 0x3ffc8000; */ 153 | 154 | .irom0.text : ALIGN(4) 155 | { 156 | _irom0_text_start = ABSOLUTE(.); 157 | 158 | *libat.a:(.literal.* .text.*) 159 | *libcrypto.a:(.literal.* .text.*) 160 | *libespnow.a:(.literal.* .text.*) 161 | *libjson.a:(.literal.* .text.*) 162 | *liblwip.a:(.literal.* .text.*) 163 | *libmesh.a:(.literal.* .text.*) 164 | *libnet80211.a:(.literal.* .text.*) 165 | *libsmartconfig.a:(.literal.* .text.*) 166 | *libssl.a:(.literal.* .text.*) 167 | *libupgrade.a:(.literal.* .text.*) 168 | *libwpa.a:(.literal.* .text.*) 169 | *libwpa2.a:(.literal.* .text.*) 170 | *libwps.a:(.literal.* .text.*) 171 | 172 | *libmbedtls.a:(.literal.* .text.*) 173 | 174 | *libm.a:(.literal .text .literal.* .text.*) 175 | 176 | *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) 177 | _irom0_text_end = ABSOLUTE(.); 178 | } >irom0_0_seg :irom0_0_phdr 179 | 180 | .text : ALIGN(4) 181 | { 182 | _stext = .; 183 | _text_start = ABSOLUTE(.); 184 | *(.UserEnter.text) 185 | . = ALIGN(16); 186 | *(.DebugExceptionVector.text) 187 | . = ALIGN(16); 188 | *(.NMIExceptionVector.text) 189 | . = ALIGN(16); 190 | *(.KernelExceptionVector.text) 191 | LONG(0) 192 | LONG(0) 193 | LONG(0) 194 | LONG(0) 195 | . = ALIGN(16); 196 | *(.UserExceptionVector.text) 197 | LONG(0) 198 | LONG(0) 199 | LONG(0) 200 | LONG(0) 201 | . = ALIGN(16); 202 | *(.DoubleExceptionVector.text) 203 | LONG(0) 204 | LONG(0) 205 | LONG(0) 206 | LONG(0) 207 | . = ALIGN (16); 208 | *(.entry.text) 209 | *(.init.literal) 210 | *(.init) 211 | *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) 212 | *(.fini.literal) 213 | *(.fini) 214 | *(.gnu.version) 215 | _text_end = ABSOLUTE(.); 216 | _etext = .; 217 | } >iram1_0_seg :iram1_0_phdr 218 | 219 | .lit4 : ALIGN(4) 220 | { 221 | _lit4_start = ABSOLUTE(.); 222 | *(*.lit4) 223 | *(.lit4.*) 224 | *(.gnu.linkonce.lit4.*) 225 | _lit4_end = ABSOLUTE(.); 226 | } >iram1_0_seg :iram1_0_phdr 227 | } 228 | 229 | /* get ROM code address */ 230 | INCLUDE "eagle.rom.addr.v6.ld" 231 | -------------------------------------------------------------------------------- /user/rboot-api.c: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // rBoot OTA and config API for ESP8266. 3 | // Copyright 2015 Richard A Burton 4 | // richardaburton@gmail.com 5 | // See license.txt for license terms. 6 | // OTA code based on SDK sample from Espressif. 7 | ////////////////////////////////////////////////// 8 | 9 | #include 10 | #include 11 | #include "osapi.h" 12 | #include 13 | 14 | // detect rtos sdk (not ideal method!) 15 | #ifdef IRAM_ATTR 16 | #define os_free(s) vPortFree(s) 17 | #define os_malloc(s) pvPortMalloc(s) 18 | #else 19 | #include 20 | #endif 21 | 22 | #include "rboot-api.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #if defined(BOOT_CONFIG_CHKSUM) || defined(BOOT_RTC_ENABLED) 29 | // calculate checksum for block of data 30 | // from start up to (but excluding) end 31 | static uint8 calc_chksum(uint8 *start, uint8 *end) { 32 | uint8 chksum = CHKSUM_INIT; 33 | while(start < end) { 34 | chksum ^= *start; 35 | start++; 36 | } 37 | return chksum; 38 | } 39 | #endif 40 | 41 | // get the rboot config 42 | rboot_config ICACHE_FLASH_ATTR rboot_get_config(void) { 43 | rboot_config conf; 44 | spi_flash_read(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)&conf, sizeof(rboot_config)); 45 | return conf; 46 | } 47 | 48 | // write the rboot config 49 | // preserves the contents of the rest of the sector, 50 | // so the rest of the sector can be used to store user data 51 | // updates checksum automatically (if enabled) 52 | bool ICACHE_FLASH_ATTR rboot_set_config(rboot_config *conf) { 53 | uint8 *buffer; 54 | buffer = (uint8*)os_malloc(SECTOR_SIZE); 55 | if (!buffer) { 56 | //os_printf("No ram!\r\n"); 57 | return false; 58 | } 59 | 60 | #ifdef BOOT_CONFIG_CHKSUM 61 | conf->chksum = calc_chksum((uint8*)conf, (uint8*)&conf->chksum); 62 | #endif 63 | 64 | spi_flash_read(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE); 65 | os_memcpy(buffer, conf, sizeof(rboot_config)); 66 | spi_flash_erase_sector(BOOT_CONFIG_SECTOR); 67 | //spi_flash_write(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE); 68 | spi_flash_write(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE); 69 | 70 | os_free(buffer); 71 | return true; 72 | } 73 | 74 | // get current boot rom 75 | uint8 ICACHE_FLASH_ATTR rboot_get_current_rom(void) { 76 | rboot_config conf; 77 | conf = rboot_get_config(); 78 | return conf.current_rom; 79 | } 80 | 81 | // set current boot rom 82 | bool ICACHE_FLASH_ATTR rboot_set_current_rom(uint8 rom) { 83 | rboot_config conf; 84 | conf = rboot_get_config(); 85 | if (rom >= conf.count) return false; 86 | conf.current_rom = rom; 87 | return rboot_set_config(&conf); 88 | } 89 | 90 | // create the write status struct, based on supplied start address 91 | rboot_write_status ICACHE_FLASH_ATTR rboot_write_init(uint32 start_addr) { 92 | rboot_write_status status = {0}; 93 | status.start_addr = start_addr; 94 | status.start_sector = start_addr / SECTOR_SIZE; 95 | status.last_sector_erased = status.start_sector - 1; 96 | //status.max_sector_count = 200; 97 | //os_printf("init addr: 0x%08x\r\n", start_addr); 98 | return status; 99 | } 100 | 101 | // ensure any remaning bytes get written (needed for files not a multiple of 4 bytes) 102 | bool ICACHE_FLASH_ATTR rboot_write_end(rboot_write_status *status) { 103 | uint8 i; 104 | if (status->extra_count != 0) { 105 | for (i = status->extra_count; i < 4; i++) { 106 | status->extra_bytes[i] = 0xff; 107 | } 108 | return rboot_write_flash(status, status->extra_bytes, 4); 109 | } 110 | return true; 111 | } 112 | 113 | // function to do the actual writing to flash 114 | // call repeatedly with more data (max len per write is the flash sector size (4k)) 115 | bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len) { 116 | 117 | bool ret = false; 118 | uint8 *buffer; 119 | int32 lastsect; 120 | 121 | if (data == NULL || len == 0) { 122 | return true; 123 | } 124 | 125 | // get a buffer 126 | buffer = (uint8 *)os_malloc(len + status->extra_count); 127 | if (!buffer) { 128 | //os_printf("No ram!\r\n"); 129 | return false; 130 | } 131 | 132 | // copy in any remaining bytes from last chunk 133 | if (status->extra_count != 0) { 134 | os_memcpy(buffer, status->extra_bytes, status->extra_count); 135 | } 136 | // copy in new data 137 | os_memcpy(buffer + status->extra_count, data, len); 138 | 139 | // calculate length, must be multiple of 4 140 | // save any remaining bytes for next go 141 | len += status->extra_count; 142 | status->extra_count = len % 4; 143 | len -= status->extra_count; 144 | os_memcpy(status->extra_bytes, buffer + len, status->extra_count); 145 | 146 | // check data will fit 147 | //if (status->start_addr + len < (status->start_sector + status->max_sector_count) * SECTOR_SIZE) { 148 | 149 | // erase any additional sectors needed by this chunk 150 | lastsect = ((status->start_addr + len) - 1) / SECTOR_SIZE; 151 | while (lastsect > status->last_sector_erased) { 152 | status->last_sector_erased++; 153 | spi_flash_erase_sector(status->last_sector_erased); 154 | } 155 | 156 | // write current chunk 157 | //os_printf("write addr: 0x%08x, len: 0x%04x\r\n", status->start_addr, len); 158 | if (spi_flash_write(status->start_addr, (uint32 *)((void*)buffer), len) == SPI_FLASH_RESULT_OK) { 159 | ret = true; 160 | status->start_addr += len; 161 | } 162 | //} 163 | 164 | os_free(buffer); 165 | return ret; 166 | } 167 | 168 | #ifdef BOOT_RTC_ENABLED 169 | bool ICACHE_FLASH_ATTR rboot_get_rtc_data(rboot_rtc_data *rtc) { 170 | if (system_rtc_mem_read(RBOOT_RTC_ADDR, rtc, sizeof(rboot_rtc_data))) { 171 | return (rtc->chksum == calc_chksum((uint8*)rtc, (uint8*)&rtc->chksum)); 172 | } 173 | return false; 174 | } 175 | 176 | bool ICACHE_FLASH_ATTR rboot_set_rtc_data(rboot_rtc_data *rtc) { 177 | // calculate checksum 178 | rtc->chksum = calc_chksum((uint8*)rtc, (uint8*)&rtc->chksum); 179 | return system_rtc_mem_write(RBOOT_RTC_ADDR, rtc, sizeof(rboot_rtc_data)); 180 | } 181 | 182 | bool ICACHE_FLASH_ATTR rboot_set_temp_rom(uint8 rom) { 183 | rboot_rtc_data rtc; 184 | // invalid data in rtc? 185 | if (!rboot_get_rtc_data(&rtc)) { 186 | // set basics 187 | rtc.magic = RBOOT_RTC_MAGIC; 188 | rtc.last_mode = MODE_STANDARD; 189 | rtc.last_rom = 0; 190 | } 191 | // set next boot to temp mode with specified rom 192 | rtc.next_mode = MODE_TEMP_ROM; 193 | rtc.temp_rom = rom; 194 | 195 | return rboot_set_rtc_data(&rtc); 196 | } 197 | 198 | bool ICACHE_FLASH_ATTR rboot_get_last_boot_rom(uint8 *rom) { 199 | rboot_rtc_data rtc; 200 | if (rboot_get_rtc_data(&rtc)) { 201 | *rom = rtc.last_rom; 202 | return true; 203 | } 204 | return false; 205 | } 206 | 207 | bool ICACHE_FLASH_ATTR rboot_get_last_boot_mode(uint8 *mode) { 208 | rboot_rtc_data rtc; 209 | if (rboot_get_rtc_data(&rtc)) { 210 | *mode = rtc.last_mode; 211 | return true; 212 | } 213 | return false; 214 | } 215 | #endif 216 | 217 | #ifdef __cplusplus 218 | } 219 | #endif 220 | -------------------------------------------------------------------------------- /user/ringbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ringbuf.c - C ring buffer (FIFO) implementation. 3 | * 4 | * Written in 2011 by Drew Hess . 5 | * 6 | * To the extent possible under law, the author(s) have dedicated all 7 | * copyright and related and neighboring rights to this software to 8 | * the public domain worldwide. This software is distributed without 9 | * any warranty. 10 | * 11 | * You should have received a copy of the CC0 Public Domain Dedication 12 | * along with this software. If not, see 13 | * . 14 | */ 15 | 16 | #include "ringbuf.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "osapi.h" 26 | #include "mem.h" 27 | 28 | #define assert(x) 29 | 30 | /* 31 | * The code is written for clarity, not cleverness or performance, and 32 | * contains many assert()s to enforce invariant assumptions and catch 33 | * bugs. Feel free to optimize the code and to remove asserts for use 34 | * in your own projects, once you're comfortable that it functions as 35 | * intended. 36 | */ 37 | 38 | struct ringbuf_t 39 | { 40 | uint8_t *buf; 41 | uint8_t *head, *tail; 42 | size_t size; 43 | }; 44 | 45 | ringbuf_t 46 | ringbuf_new(size_t capacity) 47 | { 48 | ringbuf_t rb = (ringbuf_t)os_malloc(sizeof(struct ringbuf_t)); 49 | if (rb) { 50 | 51 | /* One byte is used for detecting the full condition. */ 52 | rb->size = capacity + 1; 53 | rb->buf = (uint8_t *)os_malloc(rb->size); 54 | if (rb->buf) 55 | ringbuf_reset(rb); 56 | else { 57 | os_free(rb); 58 | return 0; 59 | } 60 | } 61 | return rb; 62 | } 63 | 64 | size_t 65 | ringbuf_buffer_size(const struct ringbuf_t *rb) 66 | { 67 | return rb->size; 68 | } 69 | 70 | void 71 | ringbuf_reset(ringbuf_t rb) 72 | { 73 | rb->head = rb->tail = rb->buf; 74 | } 75 | 76 | void 77 | ringbuf_free(ringbuf_t *rb) 78 | { 79 | assert(rb && *rb); 80 | os_free((*rb)->buf); 81 | os_free(*rb); 82 | *rb = 0; 83 | } 84 | 85 | size_t 86 | ringbuf_capacity(const struct ringbuf_t *rb) 87 | { 88 | return ringbuf_buffer_size(rb) - 1; 89 | } 90 | 91 | /* 92 | * Return a pointer to one-past-the-end of the ring buffer's 93 | * contiguous buffer. You shouldn't normally need to use this function 94 | * unless you're writing a new ringbuf_* function. 95 | */ 96 | static const uint8_t * 97 | ringbuf_end(const struct ringbuf_t *rb) 98 | { 99 | return rb->buf + ringbuf_buffer_size(rb); 100 | } 101 | 102 | size_t 103 | ringbuf_bytes_free(const struct ringbuf_t *rb) 104 | { 105 | if (rb->head >= rb->tail) 106 | return ringbuf_capacity(rb) - (rb->head - rb->tail); 107 | else 108 | return rb->tail - rb->head - 1; 109 | } 110 | 111 | size_t 112 | ringbuf_bytes_used(const struct ringbuf_t *rb) 113 | { 114 | return ringbuf_capacity(rb) - ringbuf_bytes_free(rb); 115 | } 116 | 117 | int 118 | ringbuf_is_full(const struct ringbuf_t *rb) 119 | { 120 | return ringbuf_bytes_free(rb) == 0; 121 | } 122 | 123 | int 124 | ringbuf_is_empty(const struct ringbuf_t *rb) 125 | { 126 | return ringbuf_bytes_free(rb) == ringbuf_capacity(rb); 127 | } 128 | 129 | const void * 130 | ringbuf_tail(const struct ringbuf_t *rb) 131 | { 132 | return rb->tail; 133 | } 134 | 135 | const void * 136 | ringbuf_head(const struct ringbuf_t *rb) 137 | { 138 | return rb->head; 139 | } 140 | 141 | /* 142 | * Given a ring buffer rb and a pointer to a location within its 143 | * contiguous buffer, return the a pointer to the next logical 144 | * location in the ring buffer. 145 | */ 146 | static uint8_t * 147 | ringbuf_nextp(ringbuf_t rb, const uint8_t *p) 148 | { 149 | /* 150 | * The assert guarantees the expression (++p - rb->buf) is 151 | * non-negative; therefore, the modulus operation is safe and 152 | * portable. 153 | */ 154 | assert((p >= rb->buf) && (p < ringbuf_end(rb))); 155 | return rb->buf + ((++p - rb->buf) % ringbuf_buffer_size(rb)); 156 | } 157 | 158 | void * 159 | ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count) 160 | { 161 | const uint8_t *u8src = src; 162 | const uint8_t *bufend = ringbuf_end(dst); 163 | int overflow = count > ringbuf_bytes_free(dst); 164 | size_t nread = 0; 165 | 166 | while (nread != count) { 167 | /* don't copy beyond the end of the buffer */ 168 | assert(bufend > dst->head); 169 | size_t n = MIN(bufend - dst->head, count - nread); 170 | os_memcpy(dst->head, u8src + nread, n); 171 | dst->head += n; 172 | nread += n; 173 | 174 | /* wrap? */ 175 | if (dst->head == bufend) 176 | dst->head = dst->buf; 177 | } 178 | 179 | if (overflow) { 180 | dst->tail = ringbuf_nextp(dst, dst->head); 181 | assert(ringbuf_is_full(dst)); 182 | } 183 | 184 | return dst->head; 185 | } 186 | 187 | void * 188 | ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count) 189 | { 190 | size_t bytes_used = ringbuf_bytes_used(src); 191 | if (count > bytes_used) 192 | return 0; 193 | 194 | uint8_t *u8dst = dst; 195 | const uint8_t *bufend = ringbuf_end(src); 196 | size_t nwritten = 0; 197 | while (nwritten != count) { 198 | assert(bufend > src->tail); 199 | size_t n = MIN(bufend - src->tail, count - nwritten); 200 | os_memcpy(u8dst + nwritten, src->tail, n); 201 | src->tail += n; 202 | nwritten += n; 203 | 204 | /* wrap ? */ 205 | if (src->tail == bufend) 206 | src->tail = src->buf; 207 | } 208 | 209 | assert(count + ringbuf_bytes_used(src) == bytes_used); 210 | return src->tail; 211 | } 212 | 213 | void * 214 | ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count) 215 | { 216 | size_t src_bytes_used = ringbuf_bytes_used(src); 217 | if (count > src_bytes_used) 218 | return 0; 219 | int overflow = count > ringbuf_bytes_free(dst); 220 | 221 | const uint8_t *src_bufend = ringbuf_end(src); 222 | const uint8_t *dst_bufend = ringbuf_end(dst); 223 | size_t ncopied = 0; 224 | while (ncopied != count) { 225 | assert(src_bufend > src->tail); 226 | size_t nsrc = MIN(src_bufend - src->tail, count - ncopied); 227 | assert(dst_bufend > dst->head); 228 | size_t n = MIN(dst_bufend - dst->head, nsrc); 229 | os_memcpy(dst->head, src->tail, n); 230 | src->tail += n; 231 | dst->head += n; 232 | ncopied += n; 233 | 234 | /* wrap ? */ 235 | if (src->tail == src_bufend) 236 | src->tail = src->buf; 237 | if (dst->head == dst_bufend) 238 | dst->head = dst->buf; 239 | } 240 | 241 | assert(count + ringbuf_bytes_used(src) == src_bytes_used); 242 | 243 | if (overflow) { 244 | dst->tail = ringbuf_nextp(dst, dst->head); 245 | assert(ringbuf_is_full(dst)); 246 | } 247 | 248 | return dst->head; 249 | } 250 | 251 | -------------------------------------------------------------------------------- /user/config_flash.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_FLASH_H_ 2 | #define _CONFIG_FLASH_H_ 3 | 4 | #include "c_types.h" 5 | #include "mem.h" 6 | #include "ets_sys.h" 7 | #include "osapi.h" 8 | #include "gpio.h" 9 | #include "os_type.h" 10 | #include "spi_flash.h" 11 | #include "lwip/app/dhcpserver.h" 12 | #include "lwip/ip_route.h" 13 | 14 | #include "user_config.h" 15 | #include "acl.h" 16 | 17 | #define FLASH_BLOCK_NO 0x60 18 | 19 | #define MAGIC_NUMBER 0x13f43dad 20 | 21 | typedef enum { 22 | AUTOMESH_OFF = 0, AUTOMESH_LEARNING, AUTOMESH_OPERATIONAL 23 | } automeshmode; 24 | 25 | #if GPIO_CMDS 26 | typedef enum { 27 | UNDEFINED = 0, OUT, IN, IN_PULLUP 28 | } gpio_mode; 29 | #endif 30 | 31 | typedef struct { 32 | // To check if the structure is initialized or not in flash 33 | uint32_t magic_number; 34 | 35 | // Length of the structure, since this is a evolving library, the variant may change 36 | // hence used for verification 37 | uint16_t length; 38 | 39 | /* Below variables are specific to my code */ 40 | uint8_t ssid[32]; // SSID of the AP to connect to 41 | uint8_t password[64]; // Password of the network 42 | uint8_t auto_connect; // Should we auto connect 43 | uint8_t bssid[6]; // Optional: BSSID the AP 44 | uint8_t sta_hostname[32]; // Name of the station 45 | 46 | uint8_t ap_ssid[32]; // SSID of the own AP 47 | uint8_t ap_password[64]; // Password of the own network 48 | uint8_t ap_open; // Should we use no WPA? 49 | uint8_t ap_on; // AP enabled? 50 | uint8_t ssid_hidden; // Hidden SSID? 51 | uint8_t max_clients; // Max number of STAs on the SoftAP 52 | #if WPA2_PEAP 53 | uint8_t use_PEAP; // WPA2 PEAP Authentication 54 | uint8_t PEAP_identity[64]; // PEAP enterprise outer identity 55 | uint8_t PEAP_username[64]; // PEAP enterprise username 56 | uint8_t PEAP_password[32]; // PEAP enterprise password 57 | #endif 58 | uint8_t lock_password[32]; // Password of config lock 59 | uint8_t locked; // Should we allow for config changes 60 | 61 | int32_t ap_watchdog; // Seconds without ap traffic will cause reset (-1 off, default) 62 | int32_t client_watchdog; // Seconds without client traffic will cause reset (-1 off, default) 63 | 64 | automeshmode automesh_mode; // The AutoMesh mode 65 | uint8_t automesh_checked; // Flag that it has worked once 66 | uint8_t automesh_tries; // Counter of disconnects 67 | int8_t automesh_threshold; // RSSI limit 68 | uint32_t am_scan_time; // Seconds for scanning 69 | uint32_t am_sleep_time; // Seconds for sleeping 70 | 71 | uint8_t nat_enable; // Enable NAT on the AP netif; 72 | uint32_t tcp_timeout; // NAT timeout of TCP connections 73 | uint32_t udp_timeout; // NAT timeout of UDO 'connections' 74 | 75 | ip_addr_t network_addr; // Address of the internal network 76 | ip_addr_t dns_addr; // Optional: address of the dns server 77 | 78 | ip_addr_t my_addr; // Optional (if not DHCP): IP address of the STA interface 79 | ip_addr_t my_netmask; // Optional (if not DHCP): IP netmask of the STA interface 80 | ip_addr_t my_gw; // Optional (if not DHCP): Gateway of the STA interface 81 | #if PHY_MODE 82 | uint16_t phy_mode; // WiFi PHY mode 83 | #endif 84 | uint16_t clock_speed; // Freq of the CPU 85 | uint16_t status_led; // GPIO pin os the status LED (>16 disabled) 86 | uint16_t hw_reset; // GPIO pin that issues a hw factory reset (>16 disabled) 87 | #if DAILY_LIMIT 88 | uint32_t daily_limit; // max KBytes per day (0 if no limit) 89 | int32_t ntp_timezone; // local timezone (to know when a day is over) 90 | #endif 91 | #if ALLOW_SLEEP 92 | int32_t Vmin; // Min voltage of battery 93 | int32_t Vmin_sleep; // Sleep time in sec when battery is low 94 | #endif 95 | #if REMOTE_CONFIG 96 | uint16_t config_port; // Port on which the concole listenes (0 if no access) 97 | #endif 98 | #if WEB_CONFIG 99 | uint16_t web_port; // Port on which the concole listenes (0 if no access) 100 | #endif 101 | uint8_t config_access; // Controls the interfaces that allow config access (default LOCAL_ACCESS | REMOTE_ACCESS) 102 | #if TOKENBUCKET 103 | uint32_t kbps_ds; // Average downstream bitrate (0 if no limit); 104 | uint32_t kbps_us; // Average upstream bitrate (0 if no limit); 105 | #endif 106 | #if MQTT_CLIENT 107 | uint8_t mqtt_host[32]; // IP or hostname of the MQTT broker, "none" if empty 108 | uint16_t mqtt_port; // Port of the MQTT broker 109 | 110 | uint8_t mqtt_user[32]; // Username for broker login, "none" if empty 111 | uint8_t mqtt_password[32]; // Password for broker login 112 | uint8_t mqtt_id[32]; // MQTT clientId 113 | uint8_t mqtt_prefix[64]; // Topic-prefix 114 | uint8_t mqtt_command_topic[64]; // Topic on which commands are received, "none" if not subscibed 115 | uint8_t mqtt_gpio_out_topic[64]; // Topic on which the status of the gpio_out pin can be set 116 | uint8_t mqtt_qos; 117 | bool gpio_out_status; // Initial status of the gpio_out pin 118 | 119 | uint32_t mqtt_interval; // Interval in secs for status messages, 0 means no messages 120 | uint16_t mqtt_topic_mask; // Mask for active topics 121 | #endif 122 | 123 | uint8_t AP_MAC_address[6]; // MAC address of the AP 124 | uint8_t STA_MAC_address[6]; // MAC address of the STA 125 | #if HAVE_ENC28J60 126 | ip_addr_t eth_addr; // Optional (if not DHCP): IP address of the ENC28J60 ETH interface 127 | ip_addr_t eth_netmask; // Optional (if not DHCP): IP netmask of the ENC28J60 ETH interface 128 | ip_addr_t eth_gw; // Optional (if not DHCP): Gateway of the ENC28J60 ETH interface 129 | uint8_t ETH_MAC_address[6]; // MAC address of the ENC28J60 ETH interface 130 | bool eth_enable; // Do we really have and use an ENC28J60 ETH interface 131 | #if DCHPSERVER_ENC28J60 132 | bool enc_DHCPserver; // run DHCP _server_ on ETH interface if static IP 133 | #endif 134 | #endif 135 | uint32_t no_routes; // Number of static routing entires 136 | struct route_entry rt_table[MAX_ROUTES]; // The routing entries 137 | 138 | uint16_t dhcps_entries; // number of allocated entries in the following table 139 | struct dhcps_pool dhcps_p[MAX_DHCP]; // DHCP entries 140 | #if ACLS 141 | acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES]; // ACL entries 142 | uint8_t acl_freep[MAX_NO_ACLS]; // ACL free pointers 143 | #endif 144 | #if OTAUPDATE 145 | uint8_t ota_host[64]; 146 | uint16_t ota_port; 147 | #endif 148 | #if GPIO_CMDS 149 | gpio_mode gpiomode[17]; 150 | #endif 151 | } sysconfig_t, *sysconfig_p; 152 | 153 | int config_load(sysconfig_p config); 154 | void config_load_default(sysconfig_p config); 155 | void config_save(sysconfig_p config); 156 | 157 | void blob_save(uint8_t blob_no, uint32_t *data, uint16_t len); 158 | void blob_load(uint8_t blob_no, uint32_t *data, uint16_t len); 159 | void blob_zero(uint8_t blob_no, uint16_t len); 160 | 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /user/acl.c: -------------------------------------------------------------------------------- 1 | #include "c_types.h" 2 | #include "mem.h" 3 | #include "ets_sys.h" 4 | #include "osapi.h" 5 | #include "os_type.h" 6 | #include "lwip/ip.h" 7 | #include "lwip/udp.h" 8 | #include "lwip/tcp_impl.h" 9 | #include "netif/etharp.h" 10 | 11 | #include "user_interface.h" 12 | #include "string.h" 13 | 14 | #include "acl.h" 15 | 16 | acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES]; 17 | uint8_t acl_freep[MAX_NO_ACLS]; 18 | uint32_t acl_allow_count; 19 | uint32_t acl_deny_count; 20 | static packet_deny_cb my_deny_cb; 21 | 22 | void ICACHE_FLASH_ATTR acl_init() 23 | { 24 | int i; 25 | acl_allow_count = acl_deny_count = 0;; 26 | my_deny_cb = NULL; 27 | for(i=0; i< MAX_NO_ACLS; i++) { 28 | acl_freep[i] = 0; 29 | acl_clear_stats(i); 30 | } 31 | } 32 | 33 | bool ICACHE_FLASH_ATTR acl_is_empty(uint8_t acl_no) 34 | { 35 | if (acl_no >= MAX_NO_ACLS) 36 | return true; 37 | return acl_freep[acl_no] == 0; 38 | } 39 | 40 | void ICACHE_FLASH_ATTR acl_clear(uint8_t acl_no) 41 | { 42 | if (acl_no >= MAX_NO_ACLS) 43 | return; 44 | acl_freep[acl_no] = 0; 45 | acl_clear_stats(acl_no); 46 | } 47 | 48 | void ICACHE_FLASH_ATTR acl_clear_stats(uint8_t acl_no) 49 | { 50 | int i; 51 | 52 | if (acl_no >= MAX_NO_ACLS) 53 | return; 54 | my_deny_cb = NULL; 55 | for(i=0; i< MAX_ACL_ENTRIES; i++) 56 | acl[acl_no][i].hit_count = 0; 57 | } 58 | 59 | bool ICACHE_FLASH_ATTR acl_add(uint8_t acl_no, 60 | uint32_t src, uint32_t s_mask, uint32_t dest, uint32_t d_mask, 61 | uint8_t proto, uint16_t s_port, uint16_t d_port, uint8_t allow) 62 | { 63 | acl_entry *my_entry; 64 | 65 | if (acl_no >= MAX_NO_ACLS || acl_freep[acl_no] >= MAX_ACL_ENTRIES) 66 | return false; 67 | 68 | my_entry = &acl[acl_no][acl_freep[acl_no]]; 69 | my_entry->src = src & s_mask; 70 | my_entry->s_mask = s_mask; 71 | my_entry->dest = dest & d_mask; 72 | my_entry->d_mask = d_mask; 73 | my_entry->proto = proto; 74 | my_entry->s_port = s_port; 75 | my_entry->d_port = d_port; 76 | my_entry->allow = allow; 77 | my_entry->hit_count = 0; 78 | 79 | acl_freep[acl_no]++; 80 | return true; 81 | } 82 | 83 | 84 | uint8_t ICACHE_FLASH_ATTR acl_check_packet(uint8_t acl_no, struct pbuf *p) 85 | { 86 | struct eth_hdr *mac_h; 87 | struct ip_hdr *ip_h; 88 | uint8_t proto; 89 | struct udp_hdr *udp_h; 90 | struct tcp_hdr *tcp_h; 91 | uint16_t src_port, dest_port; 92 | uint8_t *packet; 93 | int i; 94 | acl_entry *my_entry; 95 | uint8_t allow; 96 | 97 | if (acl_no >= MAX_NO_ACLS) 98 | return ACL_DENY; 99 | 100 | if (p->len < sizeof(struct eth_hdr)) 101 | return ACL_DENY; 102 | 103 | mac_h = (struct eth_hdr *)p->payload; 104 | 105 | // Allow ARP 106 | if (ntohs(mac_h->type) == ETHTYPE_ARP) { 107 | acl_allow_count++; 108 | return ACL_ALLOW; 109 | } 110 | 111 | // Drop anything else if not IPv4 112 | if (ntohs(mac_h->type) != ETHTYPE_IP) { 113 | acl_deny_count++; 114 | return ACL_DENY; 115 | } 116 | 117 | if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)) { 118 | acl_deny_count++; 119 | return ACL_DENY; 120 | } 121 | 122 | allow = ACL_DENY; 123 | packet = (uint8_t*)p->payload; 124 | ip_h = (struct ip_hdr *)&packet[sizeof(struct eth_hdr)]; 125 | proto = IPH_PROTO(ip_h); 126 | 127 | switch (proto) { 128 | case IP_PROTO_UDP: 129 | if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct udp_hdr)) 130 | return ACL_DENY; 131 | udp_h = (struct udp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)]; 132 | src_port = ntohs(udp_h->src); 133 | dest_port = ntohs(udp_h->dest); 134 | break; 135 | 136 | case IP_PROTO_TCP: 137 | if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct tcp_hdr)) 138 | return ACL_DENY; 139 | tcp_h = (struct tcp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)]; 140 | src_port = ntohs(tcp_h->src); 141 | dest_port = ntohs(tcp_h->dest); 142 | break; 143 | 144 | case IP_PROTO_ICMP: 145 | src_port = dest_port = 0; 146 | break; 147 | 148 | // Drop anything that is not UDP, TCP, or ICMP 149 | default: 150 | acl_deny_count++; 151 | return ACL_DENY; 152 | } 153 | 154 | // os_printf("Src: %d.%d.%d.%d Dst: %d.%d.%d.%d Proto: %s SP:%d DP:%d\n", 155 | // IP2STR(&ip_h->src), IP2STR(&ip_h->dest), 156 | // proto==IP_PROTO_TCP?"TCP":proto==IP_PROTO_UDP?"UDP":"IP4", src_port, dest_port); 157 | 158 | for(i=0; iproto == 0 || proto == my_entry->proto) && 161 | (my_entry->src == 0 || my_entry->src == (ip_h->src.addr&my_entry->s_mask)) && 162 | (my_entry->dest == 0 || my_entry->dest == (ip_h->dest.addr&my_entry->d_mask)) && 163 | (my_entry->s_port == 0 || my_entry->s_port == src_port) && 164 | (my_entry->d_port == 0 || my_entry->d_port == dest_port)) { 165 | allow = my_entry->allow; 166 | my_entry->hit_count++; 167 | goto done; 168 | } 169 | } 170 | 171 | done: 172 | if (!(allow & ACL_ALLOW) && my_deny_cb != NULL) 173 | allow = my_deny_cb(proto, ip_h->src.addr, src_port, ip_h->dest.addr, dest_port, allow); 174 | if (allow & ACL_ALLOW) acl_allow_count++; else acl_deny_count++; 175 | // os_printf(" allow: %d\r\n", allow); 176 | return allow; 177 | } 178 | 179 | void acl_set_deny_cb(packet_deny_cb cb) 180 | { 181 | my_deny_cb = cb; 182 | } 183 | 184 | void ICACHE_FLASH_ATTR addr2str(uint8_t *buf, uint32_t addr, uint32_t mask) 185 | { 186 | uint8_t clidr; 187 | 188 | if (addr == 0 && mask == 0) { 189 | os_sprintf(buf, "any"); 190 | return; 191 | } 192 | 193 | mask = ntohl(mask); 194 | for (clidr = 0; mask; mask <<= 1,clidr++); 195 | if (clidr < 32) 196 | os_sprintf(buf, "%d.%d.%d.%d/%d", IP2STR((ip_addr_t*)&addr), clidr); 197 | else 198 | os_sprintf(buf, "%d.%d.%d.%d", IP2STR((ip_addr_t*)&addr)); 199 | } 200 | 201 | void ICACHE_FLASH_ATTR port2str(uint8_t *buf, uint16_t port) 202 | { 203 | if (port == 0) 204 | os_sprintf(buf, "any"); 205 | else 206 | os_sprintf(buf, "%d", port); 207 | } 208 | 209 | void ICACHE_FLASH_ATTR acl_show(uint8_t acl_no, uint8_t *buf) 210 | { 211 | int i; 212 | acl_entry *my_entry; 213 | uint8_t line[80], addr1[21], addr2[21], port1[6], port2[6]; 214 | 215 | buf[0] = 0; 216 | 217 | if (acl_no >= MAX_NO_ACLS) 218 | return; 219 | 220 | for(i=0; isrc, my_entry->s_mask); 223 | port2str(port1, my_entry->s_port); 224 | addr2str(addr2, my_entry->dest, my_entry->d_mask); 225 | port2str(port2, my_entry->d_port); 226 | if (my_entry->proto != 0) 227 | os_sprintf(line, "%s %s:%s %s:%s %s%s (%d hits)\r\n", 228 | my_entry->proto==IP_PROTO_TCP?"TCP":"UDP", 229 | addr1, port1, addr2, port2, 230 | (my_entry->allow & ACL_ALLOW)?"allow":"deny", 231 | (my_entry->allow & ACL_MONITOR)?"_monitor":"", 232 | my_entry->hit_count); 233 | else 234 | os_sprintf(line, "IP %s %s %s%s (%d hits)\r\n", 235 | addr1, addr2, 236 | (my_entry->allow & ACL_ALLOW)?"allow":"deny", 237 | (my_entry->allow & ACL_MONITOR)?"_monitor":"", 238 | my_entry->hit_count); 239 | os_memcpy(&buf[os_strlen(buf)], line, os_strlen(line)+1); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /include/driver/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : uart.h 3 | * Copyright (C) 2013 - 2016, Espressif Systems 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of version 3 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program. If not, see . 16 | */ 17 | #ifndef UART_APP_H 18 | #define UART_APP_H 19 | 20 | #include "uart_register.h" 21 | #include "eagle_soc.h" 22 | #include "c_types.h" 23 | 24 | #define UART_TX_BUFFER_SIZE 256 //Ring buffer length of tx buffer 25 | #define UART_RX_BUFFER_SIZE 256 //Ring buffer length of rx buffer 26 | 27 | #define UART_BUFF_EN 0 //use uart buffer , FOR UART0 28 | #define UART_SELFTEST 0 //set 1:enable the loop test demo for uart buffer, FOR UART0 29 | 30 | #define UART_HW_RTS 0 //set 1: enable uart hw flow control RTS, PIN MTDO, FOR UART0 31 | #define UART_HW_CTS 0 //set1: enable uart hw flow contrl CTS , PIN MTCK, FOR UART0 32 | 33 | #define _ENABLE_CONSOLE_INTEGRATION 1 34 | #define _ENABLE_RING_BUFFER 1 35 | 36 | #ifdef _ENABLE_RING_BUFFER 37 | #include "ringbuf.h" 38 | #define RX_RING_BUFFER_SIZE 250 39 | #endif 40 | 41 | 42 | 43 | #define UART0 0 44 | #define UART1 1 45 | 46 | 47 | typedef enum { 48 | FIVE_BITS = 0x0, 49 | SIX_BITS = 0x1, 50 | SEVEN_BITS = 0x2, 51 | EIGHT_BITS = 0x3 52 | } UartBitsNum4Char; 53 | 54 | typedef enum { 55 | ONE_STOP_BIT = 0x1, 56 | ONE_HALF_STOP_BIT = 0x2, 57 | TWO_STOP_BIT = 0x3 58 | } UartStopBitsNum; 59 | 60 | typedef enum { 61 | NONE_BITS = 0x2, 62 | ODD_BITS = 1, 63 | EVEN_BITS = 0 64 | } UartParityMode; 65 | 66 | typedef enum { 67 | STICK_PARITY_DIS = 0, 68 | STICK_PARITY_EN = 1 69 | } UartExistParity; 70 | 71 | typedef enum { 72 | UART_None_Inverse = 0x0, 73 | UART_Rxd_Inverse = UART_RXD_INV, 74 | UART_CTS_Inverse = UART_CTS_INV, 75 | UART_Txd_Inverse = UART_TXD_INV, 76 | UART_RTS_Inverse = UART_RTS_INV, 77 | } UART_LineLevelInverse; 78 | 79 | 80 | typedef enum { 81 | BIT_RATE_300 = 300, 82 | BIT_RATE_600 = 600, 83 | BIT_RATE_1200 = 1200, 84 | BIT_RATE_2400 = 2400, 85 | BIT_RATE_4800 = 4800, 86 | BIT_RATE_9600 = 9600, 87 | BIT_RATE_19200 = 19200, 88 | BIT_RATE_38400 = 38400, 89 | BIT_RATE_57600 = 57600, 90 | BIT_RATE_74880 = 74880, 91 | BIT_RATE_115200 = 115200, 92 | BIT_RATE_230400 = 230400, 93 | BIT_RATE_460800 = 460800, 94 | BIT_RATE_921600 = 921600, 95 | BIT_RATE_1843200 = 1843200, 96 | BIT_RATE_3686400 = 3686400, 97 | } UartBautRate; 98 | 99 | typedef enum { 100 | NONE_CTRL, 101 | HARDWARE_CTRL, 102 | XON_XOFF_CTRL 103 | } UartFlowCtrl; 104 | 105 | typedef enum { 106 | USART_HardwareFlowControl_None = 0x0, 107 | USART_HardwareFlowControl_RTS = 0x1, 108 | USART_HardwareFlowControl_CTS = 0x2, 109 | USART_HardwareFlowControl_CTS_RTS = 0x3 110 | } UART_HwFlowCtrl; 111 | 112 | typedef enum { 113 | EMPTY, 114 | UNDER_WRITE, 115 | WRITE_OVER 116 | } RcvMsgBuffState; 117 | 118 | typedef struct { 119 | uint32 RcvBuffSize; 120 | uint8 *pRcvMsgBuff; 121 | uint8 *pWritePos; 122 | uint8 *pReadPos; 123 | uint8 TrigLvl; //JLU: may need to pad 124 | RcvMsgBuffState BuffState; 125 | } RcvMsgBuff; 126 | 127 | typedef struct { 128 | uint32 TrxBuffSize; 129 | uint8 *pTrxBuff; 130 | } TrxMsgBuff; 131 | 132 | typedef enum { 133 | BAUD_RATE_DET, 134 | WAIT_SYNC_FRM, 135 | SRCH_MSG_HEAD, 136 | RCV_MSG_BODY, 137 | RCV_ESC_CHAR, 138 | } RcvMsgState; 139 | 140 | typedef struct { 141 | UartBautRate baut_rate; 142 | UartBitsNum4Char data_bits; 143 | UartExistParity exist_parity; 144 | UartParityMode parity; 145 | UartStopBitsNum stop_bits; 146 | UartFlowCtrl flow_ctrl; 147 | RcvMsgBuff rcv_buff; 148 | TrxMsgBuff trx_buff; 149 | RcvMsgState rcv_state; 150 | int received; 151 | int buff_uart_no; //indicate which uart use tx/rx buffer 152 | } UartDevice; 153 | 154 | void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); 155 | void uart0_sendStr(const char *str); 156 | 157 | 158 | /////////////////////////////////////// 159 | #define UART_FIFO_LEN 128 //define the tx fifo length 160 | #define UART_TX_EMPTY_THRESH_VAL 0x10 161 | 162 | 163 | struct UartBuffer{ 164 | uint32 UartBuffSize; 165 | uint8 *pUartBuff; 166 | uint8 *pInPos; 167 | uint8 *pOutPos; 168 | STATUS BuffState; 169 | uint16 Space; //remanent space of the buffer 170 | uint8 TcpControl; 171 | struct UartBuffer * nextBuff; 172 | }; 173 | 174 | struct UartRxBuff{ 175 | uint32 UartRxBuffSize; 176 | uint8 *pUartRxBuff; 177 | uint8 *pWritePos; 178 | uint8 *pReadPos; 179 | STATUS RxBuffState; 180 | uint32 Space; //remanent space of the buffer 181 | } ; 182 | 183 | typedef enum { 184 | RUN = 0, 185 | BLOCK = 1, 186 | } TCPState; 187 | 188 | //void ICACHE_FLASH_ATTR uart_test_rx(); 189 | STATUS uart_tx_one_char(uint8 uart, uint8 TxChar); 190 | STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar); 191 | void uart1_sendStr_no_wait(const char *str); 192 | struct UartBuffer* Uart_Buf_Init(); 193 | 194 | 195 | #if UART_BUFF_EN 196 | LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len); 197 | void uart_buf_free(struct UartBuffer* pBuff); 198 | void tx_buff_enq(char* pdata, uint16 data_len ); 199 | LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no); 200 | void tx_start_uart_buffer(uint8 uart_no); 201 | uint16 rx_buff_deq(char* pdata, uint16 data_len ); 202 | void Uart_rx_buff_enq(); 203 | #endif 204 | void uart_rx_intr_enable(uint8 uart_no); 205 | void uart_rx_intr_disable(uint8 uart_no); 206 | void uart0_tx_buffer(uint8 *buf, uint16 len); 207 | 208 | //============================================== 209 | #define FUNC_UART0_CTS 4 210 | #define FUNC_U0CTS 4 211 | #define FUNC_U1TXD_BK 2 212 | #define UART_LINE_INV_MASK (0x3f<<19) 213 | void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len); 214 | void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num); 215 | void UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask); 216 | void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode); 217 | void UART_SetBaudrate(uint8 uart_no,uint32 baud_rate); 218 | void UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh); 219 | void UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us); //do not use if tx flow control enabled 220 | void UART_ResetFifo(uint8 uart_no); 221 | void UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask); 222 | void UART_SetIntrEna(uint8 uart_no,uint32 ena_mask); 223 | void UART_SetPrintPort(uint8 uart_no); 224 | bool UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us); 225 | //============================================== 226 | 227 | void UART_init_console(UartBautRate uart0_br, 228 | uint8 recv_task_priority, 229 | ringbuf_t rxbuffer, 230 | ringbuf_t txBuffer); 231 | 232 | #endif 233 | 234 | -------------------------------------------------------------------------------- /include/driver/uart_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : uart_register.h 3 | * Copyright (C) 2013 - 2016, Espressif Systems 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of version 3 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program. If not, see . 16 | */ 17 | /* 18 | * Copyright (c) 2010 - 2011 Espressif System 19 | * 20 | */ 21 | 22 | #ifndef UART_REGISTER_H_ 23 | #define UART_REGISTER_H_ 24 | 25 | #define REG_UART_BASE(i) (0x60000000 + (i)*0xf00) 26 | //version value:32'h062000 27 | 28 | #define UART_FIFO(i) (REG_UART_BASE(i) + 0x0) 29 | #define UART_RXFIFO_RD_BYTE 0x000000FF 30 | #define UART_RXFIFO_RD_BYTE_S 0 31 | 32 | #define UART_INT_RAW(i) (REG_UART_BASE(i) + 0x4) 33 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) 34 | #define UART_BRK_DET_INT_RAW (BIT(7)) 35 | #define UART_CTS_CHG_INT_RAW (BIT(6)) 36 | #define UART_DSR_CHG_INT_RAW (BIT(5)) 37 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) 38 | #define UART_FRM_ERR_INT_RAW (BIT(3)) 39 | #define UART_PARITY_ERR_INT_RAW (BIT(2)) 40 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) 41 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) 42 | 43 | #define UART_INT_ST(i) (REG_UART_BASE(i) + 0x8) 44 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) 45 | #define UART_BRK_DET_INT_ST (BIT(7)) 46 | #define UART_CTS_CHG_INT_ST (BIT(6)) 47 | #define UART_DSR_CHG_INT_ST (BIT(5)) 48 | #define UART_RXFIFO_OVF_INT_ST (BIT(4)) 49 | #define UART_FRM_ERR_INT_ST (BIT(3)) 50 | #define UART_PARITY_ERR_INT_ST (BIT(2)) 51 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) 52 | #define UART_RXFIFO_FULL_INT_ST (BIT(0)) 53 | 54 | #define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC) 55 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) 56 | #define UART_BRK_DET_INT_ENA (BIT(7)) 57 | #define UART_CTS_CHG_INT_ENA (BIT(6)) 58 | #define UART_DSR_CHG_INT_ENA (BIT(5)) 59 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) 60 | #define UART_FRM_ERR_INT_ENA (BIT(3)) 61 | #define UART_PARITY_ERR_INT_ENA (BIT(2)) 62 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) 63 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) 64 | 65 | #define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10) 66 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) 67 | #define UART_BRK_DET_INT_CLR (BIT(7)) 68 | #define UART_CTS_CHG_INT_CLR (BIT(6)) 69 | #define UART_DSR_CHG_INT_CLR (BIT(5)) 70 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) 71 | #define UART_FRM_ERR_INT_CLR (BIT(3)) 72 | #define UART_PARITY_ERR_INT_CLR (BIT(2)) 73 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) 74 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) 75 | 76 | #define UART_CLKDIV(i) (REG_UART_BASE(i) + 0x14) 77 | #define UART_CLKDIV_CNT 0x000FFFFF 78 | #define UART_CLKDIV_S 0 79 | 80 | #define UART_AUTOBAUD(i) (REG_UART_BASE(i) + 0x18) 81 | #define UART_GLITCH_FILT 0x000000FF 82 | #define UART_GLITCH_FILT_S 8 83 | #define UART_AUTOBAUD_EN (BIT(0)) 84 | 85 | #define UART_STATUS(i) (REG_UART_BASE(i) + 0x1C) 86 | #define UART_TXD (BIT(31)) 87 | #define UART_RTSN (BIT(30)) 88 | #define UART_DTRN (BIT(29)) 89 | #define UART_TXFIFO_CNT 0x000000FF 90 | #define UART_TXFIFO_CNT_S 16 91 | #define UART_RXD (BIT(15)) 92 | #define UART_CTSN (BIT(14)) 93 | #define UART_DSRN (BIT(13)) 94 | #define UART_RXFIFO_CNT 0x000000FF 95 | #define UART_RXFIFO_CNT_S 0 96 | 97 | #define UART_CONF0(i) (REG_UART_BASE(i) + 0x20) 98 | #define UART_DTR_INV (BIT(24)) 99 | #define UART_RTS_INV (BIT(23)) 100 | #define UART_TXD_INV (BIT(22)) 101 | #define UART_DSR_INV (BIT(21)) 102 | #define UART_CTS_INV (BIT(20)) 103 | #define UART_RXD_INV (BIT(19)) 104 | #define UART_TXFIFO_RST (BIT(18)) 105 | #define UART_RXFIFO_RST (BIT(17)) 106 | #define UART_IRDA_EN (BIT(16)) 107 | #define UART_TX_FLOW_EN (BIT(15)) 108 | #define UART_LOOPBACK (BIT(14)) 109 | #define UART_IRDA_RX_INV (BIT(13)) 110 | #define UART_IRDA_TX_INV (BIT(12)) 111 | #define UART_IRDA_WCTL (BIT(11)) 112 | #define UART_IRDA_TX_EN (BIT(10)) 113 | #define UART_IRDA_DPLX (BIT(9)) 114 | #define UART_TXD_BRK (BIT(8)) 115 | #define UART_SW_DTR (BIT(7)) 116 | #define UART_SW_RTS (BIT(6)) 117 | #define UART_STOP_BIT_NUM 0x00000003 118 | #define UART_STOP_BIT_NUM_S 4 119 | #define UART_BIT_NUM 0x00000003 120 | #define UART_BIT_NUM_S 2 121 | #define UART_PARITY_EN (BIT(1)) 122 | #define UART_PARITY_EN_M 0x00000001 123 | #define UART_PARITY_EN_S 1 124 | #define UART_PARITY (BIT(0)) 125 | #define UART_PARITY_M 0x00000001 126 | #define UART_PARITY_S 0 127 | 128 | #define UART_CONF1(i) (REG_UART_BASE(i) + 0x24) 129 | #define UART_RX_TOUT_EN (BIT(31)) 130 | #define UART_RX_TOUT_THRHD 0x0000007F 131 | #define UART_RX_TOUT_THRHD_S 24 132 | #define UART_RX_FLOW_EN (BIT(23)) 133 | #define UART_RX_FLOW_THRHD 0x0000007F 134 | #define UART_RX_FLOW_THRHD_S 16 135 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F 136 | #define UART_TXFIFO_EMPTY_THRHD_S 8 137 | #define UART_RXFIFO_FULL_THRHD 0x0000007F 138 | #define UART_RXFIFO_FULL_THRHD_S 0 139 | 140 | #define UART_LOWPULSE(i) (REG_UART_BASE(i) + 0x28) 141 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF 142 | #define UART_LOWPULSE_MIN_CNT_S 0 143 | 144 | #define UART_HIGHPULSE(i) (REG_UART_BASE(i) + 0x2C) 145 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF 146 | #define UART_HIGHPULSE_MIN_CNT_S 0 147 | 148 | #define UART_PULSE_NUM(i) (REG_UART_BASE(i) + 0x30) 149 | #define UART_PULSE_NUM_CNT 0x0003FF 150 | #define UART_PULSE_NUM_CNT_S 0 151 | 152 | #define UART_DATE(i) (REG_UART_BASE(i) + 0x78) 153 | #define UART_ID(i) (REG_UART_BASE(i) + 0x7C) 154 | 155 | #endif // UART_REGISTER_H_INCLUDED 156 | 157 | -------------------------------------------------------------------------------- /include/lwip/netif/espenc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ENC_SW_INTERRUPT 1 5 | 6 | err_t enc28j60_link_output(struct netif *netif, struct pbuf *p); 7 | err_t enc28j60_init(struct netif *netif); 8 | struct netif* espenc_init(uint8_t *mac_addr, ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw, bool dhcp); 9 | 10 | #define log(s, ...) 11 | //#define log(s, ...) os_printf ("[%s:%s:%d] " s "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) 12 | 13 | #define ESP_CS 15 14 | #define ESP_INT 5 15 | 16 | 17 | // ENC28J60 Control Registers 18 | // Control register definitions are a combination of address, 19 | // bank number, and Ethernet/MAC/PHY indicator bits. 20 | // - Register address (bits 0-4) 21 | // - Bank number (bits 5-6) 22 | // - MAC/PHY indicator (bit 7) 23 | #define ADDR_MASK 0x1F 24 | #define BANK_MASK 0x60 25 | #define SPRD_MASK 0x80 26 | // All-bank registers 27 | #define EIE 0x1B 28 | #define EIR 0x1C 29 | #define ESTAT 0x1D 30 | #define ECON2 0x1E 31 | #define ECON1 0x1F 32 | // Bank 0 registers 33 | #define ERDPT (0x00|0x00) 34 | #define EWRPT (0x02|0x00) 35 | #define ETXST (0x04|0x00) 36 | #define ETXND (0x06|0x00) 37 | #define ERXST (0x08|0x00) 38 | #define ERXND (0x0A|0x00) 39 | #define ERXRDPT (0x0C|0x00) 40 | // #define ERXWRPT (0x0E|0x00) 41 | #define EDMAST (0x10|0x00) 42 | #define EDMAND (0x12|0x00) 43 | // #define EDMADST (0x14|0x00) 44 | #define EDMACS (0x16|0x00) 45 | // Bank 1 registers 46 | #define EHT0 (0x00|0x20) 47 | #define EHT1 (0x01|0x20) 48 | #define EHT2 (0x02|0x20) 49 | #define EHT3 (0x03|0x20) 50 | #define EHT4 (0x04|0x20) 51 | #define EHT5 (0x05|0x20) 52 | #define EHT6 (0x06|0x20) 53 | #define EHT7 (0x07|0x20) 54 | #define EPMM0 (0x08|0x20) 55 | #define EPMM1 (0x09|0x20) 56 | #define EPMM2 (0x0A|0x20) 57 | #define EPMM3 (0x0B|0x20) 58 | #define EPMM4 (0x0C|0x20) 59 | #define EPMM5 (0x0D|0x20) 60 | #define EPMM6 (0x0E|0x20) 61 | #define EPMM7 (0x0F|0x20) 62 | #define EPMCS (0x10|0x20) 63 | // #define EPMO (0x14|0x20) 64 | #define EWOLIE (0x16|0x20) 65 | #define EWOLIR (0x17|0x20) 66 | #define ERXFCON (0x18|0x20) 67 | #define EPKTCNT (0x19|0x20) 68 | // Bank 2 registers 69 | #define MACON1 (0x00|0x40|0x80) 70 | #define MACON2 (0x01|0x40|0x80) 71 | #define MACON3 (0x02|0x40|0x80) 72 | #define MACON4 (0x03|0x40|0x80) 73 | #define MABBIPG (0x04|0x40|0x80) 74 | #define MAIPG (0x06|0x40|0x80) 75 | #define MACLCON1 (0x08|0x40|0x80) 76 | #define MACLCON2 (0x09|0x40|0x80) 77 | #define MAMXFL (0x0A|0x40|0x80) 78 | #define MAPHSUP (0x0D|0x40|0x80) 79 | #define MICON (0x11|0x40|0x80) 80 | #define MICMD (0x12|0x40|0x80) 81 | #define MIREGADR (0x14|0x40|0x80) 82 | #define MIWR (0x16|0x40|0x80) 83 | #define MIRD (0x18|0x40|0x80) 84 | // Bank 3 registers 85 | #define MAADR1 (0x00|0x60|0x80) 86 | #define MAADR0 (0x01|0x60|0x80) 87 | #define MAADR3 (0x02|0x60|0x80) 88 | #define MAADR2 (0x03|0x60|0x80) 89 | #define MAADR5 (0x04|0x60|0x80) 90 | #define MAADR4 (0x05|0x60|0x80) 91 | #define EBSTSD (0x06|0x60) 92 | #define EBSTCON (0x07|0x60) 93 | #define EBSTCS (0x08|0x60) 94 | #define MISTAT (0x0A|0x60|0x80) 95 | #define EREVID (0x12|0x60) 96 | #define ECOCON (0x15|0x60) 97 | #define EFLOCON (0x17|0x60) 98 | #define EPAUS (0x18|0x60) 99 | 100 | // ENC28J60 ERXFCON Register Bit Definitions 101 | #define ERXFCON_UCEN 0x80 102 | #define ERXFCON_ANDOR 0x40 103 | #define ERXFCON_CRCEN 0x20 104 | #define ERXFCON_PMEN 0x10 105 | #define ERXFCON_MPEN 0x08 106 | #define ERXFCON_HTEN 0x04 107 | #define ERXFCON_MCEN 0x02 108 | #define ERXFCON_BCEN 0x01 109 | // ENC28J60 EIE Register Bit Definitions 110 | #define EIE_INTIE 0x80 111 | #define EIE_PKTIE 0x40 112 | #define EIE_DMAIE 0x20 113 | #define EIE_LINKIE 0x10 114 | #define EIE_TXIE 0x08 115 | #define EIE_WOLIE 0x04 116 | #define EIE_TXERIE 0x02 117 | #define EIE_RXERIE 0x01 118 | // ENC28J60 EIR Register Bit Definitions 119 | #define EIR_PKTIF 0x40 120 | #define EIR_DMAIF 0x20 121 | #define EIR_LINKIF 0x10 122 | #define EIR_TXIF 0x08 123 | #define EIR_WOLIF 0x04 124 | #define EIR_TXERIF 0x02 125 | #define EIR_RXERIF 0x01 126 | // ENC28J60 ESTAT Register Bit Definitions 127 | #define ESTAT_INT 0x80 128 | #define ESTAT_LATECOL 0x10 129 | #define ESTAT_RXBUSY 0x04 130 | #define ESTAT_TXABRT 0x02 131 | #define ESTAT_CLKRDY 0x01 132 | // ENC28J60 ECON2 Register Bit Definitions 133 | #define ECON2_AUTOINC 0x80 134 | #define ECON2_PKTDEC 0x40 135 | #define ECON2_PWRSV 0x20 136 | #define ECON2_VRPS 0x08 137 | // ENC28J60 ECON1 Register Bit Definitions 138 | #define ECON1_TXRST 0x80 139 | #define ECON1_RXRST 0x40 140 | #define ECON1_DMAST 0x20 141 | #define ECON1_CSUMEN 0x10 142 | #define ECON1_TXRTS 0x08 143 | #define ECON1_RXEN 0x04 144 | #define ECON1_BSEL1 0x02 145 | #define ECON1_BSEL0 0x01 146 | // ENC28J60 MACON1 Register Bit Definitions 147 | #define MACON1_LOOPBK 0x10 148 | #define MACON1_TXPAUS 0x08 149 | #define MACON1_RXPAUS 0x04 150 | #define MACON1_PASSALL 0x02 151 | #define MACON1_MARXEN 0x01 152 | // ENC28J60 MACON2 Register Bit Definitions 153 | #define MACON2_MARST 0x80 154 | #define MACON2_RNDRST 0x40 155 | #define MACON2_MARXRST 0x08 156 | #define MACON2_RFUNRST 0x04 157 | #define MACON2_MATXRST 0x02 158 | #define MACON2_TFUNRST 0x01 159 | // ENC28J60 MACON3 Register Bit Definitions 160 | #define MACON3_PADCFG2 0x80 161 | #define MACON3_PADCFG1 0x40 162 | #define MACON3_PADCFG0 0x20 163 | #define MACON3_TXCRCEN 0x10 164 | #define MACON3_PHDRLEN 0x08 165 | #define MACON3_HFRMLEN 0x04 166 | #define MACON3_FRMLNEN 0x02 167 | #define MACON3_FULDPX 0x01 168 | // ENC28J60 MICMD Register Bit Definitions 169 | #define MICMD_MIISCAN 0x02 170 | #define MICMD_MIIRD 0x01 171 | // ENC28J60 MISTAT Register Bit Definitions 172 | #define MISTAT_NVALID 0x04 173 | #define MISTAT_SCAN 0x02 174 | #define MISTAT_BUSY 0x01 175 | 176 | // ENC28J60 EBSTCON Register Bit Definitions 177 | #define EBSTCON_PSV2 0x80 178 | #define EBSTCON_PSV1 0x40 179 | #define EBSTCON_PSV0 0x20 180 | #define EBSTCON_PSEL 0x10 181 | #define EBSTCON_TMSEL1 0x08 182 | #define EBSTCON_TMSEL0 0x04 183 | #define EBSTCON_TME 0x02 184 | #define EBSTCON_BISTST 0x01 185 | 186 | // PHY registers 187 | #define PHCON1 0x00 188 | #define PHSTAT1 0x01 189 | #define PHHID1 0x02 190 | #define PHHID2 0x03 191 | #define PHCON2 0x10 192 | #define PHSTAT2 0x11 193 | #define PHIE 0x12 194 | #define PHIR 0x13 195 | #define PHLCON 0x14 196 | 197 | // ENC28J60 PHY PHCON1 Register Bit Definitions 198 | #define PHCON1_PRST 0x8000 199 | #define PHCON1_PLOOPBK 0x4000 200 | #define PHCON1_PPWRSV 0x0800 201 | #define PHCON1_PDPXMD 0x0100 202 | // ENC28J60 PHY PHSTAT1 Register Bit Definitions 203 | #define PHSTAT1_PFDPX 0x1000 204 | #define PHSTAT1_PHDPX 0x0800 205 | #define PHSTAT1_LLSTAT 0x0004 206 | #define PHSTAT1_JBSTAT 0x0002 207 | // ENC28J60 PHY PHCON2 Register Bit Definitions 208 | #define PHCON2_FRCLINK 0x4000 209 | #define PHCON2_TXDIS 0x2000 210 | #define PHCON2_JABBER 0x0400 211 | #define PHCON2_HDLDIS 0x0100 212 | 213 | // ENC28J60 Packet Control Byte Bit Definitions 214 | #define PKTCTRL_PHUGEEN 0x08 215 | #define PKTCTRL_PPADEN 0x04 216 | #define PKTCTRL_PCRCEN 0x02 217 | #define PKTCTRL_POVERRIDE 0x01 218 | 219 | // SPI operation codes 220 | #define ENC28J60_READ_CTRL_REG 0x00 221 | #define ENC28J60_READ_BUF_MEM 0x3A 222 | #define ENC28J60_WRITE_CTRL_REG 0x40 223 | #define ENC28J60_WRITE_BUF_MEM 0x7A 224 | #define ENC28J60_BIT_FIELD_SET 0x80 225 | #define ENC28J60_BIT_FIELD_CLR 0xA0 226 | #define ENC28J60_SOFT_RESET 0xFF 227 | 228 | 229 | // max frame length which the controller will accept: 230 | // (note: maximum ethernet frame length would be 1518) 231 | #define MAX_FRAMELEN 1518 232 | 233 | #define FULL_SPEED 1 // switch to full-speed SPI for bulk transfers 234 | 235 | 236 | // buffer boundaries applied to internal 8K ram 237 | // the entire available packet buffer space is allocated 238 | 239 | #define RXSTART_INIT 0x0000 // start of RX buffer, (must be zero, Rev. B4 Errata point 5) 240 | #define RXSTOP_INIT 0x0BFF // end of RX buffer, room for 2 packets 241 | 242 | #define TXSTART_INIT 0x0C00 // start of TX buffer, room for 1 packet 243 | #define TXSTOP_INIT 0x11FF // end of TX buffer 244 | 245 | #define SCRATCH_START 0x1200 // start of scratch area 246 | #define SCRATCH_LIMIT 0x2000 // past end of area, i.e. 3 Kb 247 | #define SCRATCH_PAGE_SHIFT 6 // addressing is in pages of 64 bytes 248 | #define SCRATCH_PAGE_SIZE (1 << SCRATCH_PAGE_SHIFT) 249 | #define SCRATCH_PAGE_NUM ((SCRATCH_LIMIT-SCRATCH_START) >> SCRATCH_PAGE_SHIFT) 250 | #define SCRATCH_MAP_SIZE (((SCRATCH_PAGE_NUM % 8) == 0) ? (SCRATCH_PAGE_NUM / 8) : (SCRATCH_PAGE_NUM/8+1)) 251 | 252 | // area in the enc memory that can be used via enc_malloc; by default 0 bytes; decrease SCRATCH_LIMIT in order 253 | // to use this functionality 254 | #define ENC_HEAP_START SCRATCH_LIMIT 255 | #define ENC_HEAP_END 0x2000 256 | 257 | -------------------------------------------------------------------------------- /user/config_flash.c: -------------------------------------------------------------------------------- 1 | #include "user_interface.h" 2 | #include "lwip/ip.h" 3 | #include "config_flash.h" 4 | 5 | 6 | /* From the document 99A-SDK-Espressif IOT Flash RW Operation_v0.2 * 7 | * -------------------------------------------------------------------------* 8 | * Flash is erased sector by sector, which means it has to erase 4Kbytes one 9 | * time at least. When you want to change some data in flash, you have to 10 | * erase the whole sector, and then write it back with the new data. 11 | *--------------------------------------------------------------------------*/ 12 | void ICACHE_FLASH_ATTR config_load_default(sysconfig_p config) 13 | { 14 | uint8_t mac[6]; 15 | uint32_t reg0, reg1, reg3; 16 | 17 | os_memset(config, 0, sizeof(sysconfig_t)); 18 | os_printf("Loading default configuration\r\n"); 19 | config->magic_number = MAGIC_NUMBER; 20 | config->length = sizeof(sysconfig_t); 21 | 22 | reg0 = *(uint32*)(0x3ff00050); 23 | reg1 = *(uint32*)(0x3ff00054); 24 | reg3 = *(uint32*)(0x3ff0005c); 25 | 26 | if (reg3 != 0) { 27 | mac[0] = (reg3 >> 16) & 0xff; 28 | mac[1] = (reg3 >> 8) & 0xff; 29 | mac[2] = reg3 & 0xff; 30 | } else 31 | if (((reg1 >> 16) & 0xff) == 0) { 32 | mac[0] = 0x18; 33 | mac[1] = 0xfe; 34 | mac[2] = 0x34; 35 | } else 36 | if (((reg1 >> 16) & 0xff) == 1) { 37 | mac[0] = 0xac; 38 | mac[1] = 0xd0; 39 | mac[2] = 0x74; 40 | } else { 41 | os_printf("MAC read error\r\n"); 42 | } 43 | mac[3] = (reg1 >> 8) & 0xff; 44 | mac[4] = reg1 & 0xff; 45 | mac[5] = (reg0 >> 24) & 0xff; 46 | 47 | //os_printf("%02x:%02x:%02x\r\n", reg0, reg1, reg3); 48 | //os_printf("STA: %02x:%02x:%02x:%02x:%02x:%02x\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 49 | 50 | os_memcpy(config->STA_MAC_address, mac, 6); 51 | mac[0] |= 0x02; 52 | //os_printf("AP: %02x:%02x:%02x:%02x:%02x:%02x\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 53 | os_memcpy(config->AP_MAC_address, mac, 6); 54 | 55 | os_sprintf(config->ssid,"%s", WIFI_SSID); 56 | os_sprintf(config->password,"%s", WIFI_PASSWORD); 57 | config->auto_connect = 0; 58 | os_memset(config->bssid, 0, 6); 59 | os_sprintf(config->sta_hostname,"ESP_%02x%02x%02x", mac[3], mac[4], mac[5]); 60 | os_sprintf(config->ap_ssid,"%s", WIFI_AP_SSID); 61 | os_sprintf(config->ap_password,"%s",WIFI_AP_PASSWORD); 62 | config->ap_open = 1; 63 | config->ap_on = 1; 64 | config->ssid_hidden = 0; 65 | config->max_clients = MAX_CLIENTS; 66 | #if WPA2_PEAP 67 | config->use_PEAP = 0; 68 | config->PEAP_identity[0] = '\0'; 69 | config->PEAP_username[0] = '\0'; 70 | config->PEAP_password[0] = '\0'; 71 | #endif 72 | config->lock_password[0] = '\0'; 73 | config->locked = 0; 74 | 75 | config->ap_watchdog = -1; 76 | config->client_watchdog = -1; 77 | 78 | config->automesh_mode = 0; 79 | config->automesh_checked = 0; 80 | config->automesh_tries = 0; 81 | config->automesh_threshold = 85; 82 | config->am_scan_time = 0; 83 | config->am_sleep_time = 0; 84 | 85 | config->nat_enable = 1; 86 | config->tcp_timeout = 0; // use default 87 | config->udp_timeout = 0; // use default 88 | 89 | IP4_ADDR(&config->network_addr, 192, 168, 4, 1); 90 | config->dns_addr.addr = 0; // use DHCP 91 | config->my_addr.addr = 0; // use DHCP 92 | config->my_netmask.addr = 0; // use DHCP 93 | config->my_gw.addr = 0; // use DHCP 94 | #if PHY_MODE 95 | config->phy_mode = 3; // mode n 96 | #endif 97 | config->clock_speed = 80; 98 | config->status_led = STATUS_LED_GPIO; 99 | config->hw_reset = FACTORY_RESET_PIN; 100 | #if DAILY_LIMIT 101 | config->daily_limit = 0; 102 | config->ntp_timezone = 0; 103 | #endif 104 | #if ALLOW_SLEEP 105 | config->Vmin = 0; 106 | config->Vmin_sleep = 60; 107 | #endif 108 | #if REMOTE_CONFIG 109 | config->config_port = CONSOLE_SERVER_PORT; 110 | #endif 111 | #if WEB_CONFIG 112 | config->web_port = WEB_CONFIG_PORT; 113 | #endif 114 | config->config_access = LOCAL_ACCESS | REMOTE_ACCESS; 115 | #if TOKENBUCKET 116 | config->kbps_ds = 0; 117 | config->kbps_us = 0; 118 | #endif 119 | 120 | #if MQTT_CLIENT 121 | os_sprintf(config->mqtt_host,"%s", "none"); 122 | config->mqtt_port = 1883; 123 | os_sprintf(config->mqtt_user,"%s", "none"); 124 | config->mqtt_password[0] = 0; 125 | os_sprintf(config->mqtt_id,"%s_%02x%02x%02x", MQTT_ID, mac[3], mac[4], mac[5]); 126 | os_sprintf(config->mqtt_prefix,"%s/%s/system", MQTT_PREFIX, config->mqtt_id); 127 | os_sprintf(config->mqtt_command_topic,"%s/%s/%s", MQTT_PREFIX, config->mqtt_id, "command"); 128 | os_sprintf(config->mqtt_gpio_out_topic,"%s/%s/%s", MQTT_PREFIX, config->mqtt_id, "switch"); 129 | config->mqtt_qos = 0; 130 | config->gpio_out_status = 0; 131 | config->mqtt_interval = MQTT_REPORT_INTERVAL; 132 | config->mqtt_topic_mask = 0xffff; 133 | #endif 134 | 135 | #if HAVE_ENC28J60 136 | mac[0] ^= 0x04; 137 | os_memcpy(config->ETH_MAC_address, mac, 6); 138 | #if DCHPSERVER_ENC28J60 139 | IP4_ADDR(&config->eth_addr, 192, 168, 5, 1); 140 | IP4_ADDR(&config->eth_netmask, 255, 255, 255, 0); 141 | config->eth_gw.addr = 0; // Just use ARP 142 | config->eth_enable = 0; // 0 = off 143 | config->enc_DHCPserver = 0; 144 | #else 145 | //config->eth_addr.addr = 0; // use DHCP 146 | //config->eth_netmask.addr = 0; // use DHCP 147 | config->eth_gw.addr = 0; // use DHCP 148 | config->eth_enable = 0; // 0 = off 149 | #endif 150 | 151 | #endif 152 | 153 | config->no_routes = 0; 154 | 155 | config->dhcps_entries = 0; 156 | #if ACLS 157 | acl_init(); // initializes the ACLs, written in config during save 158 | #endif 159 | #if OTAUPDATE 160 | os_sprintf(config->ota_host,"%s", "none"); 161 | config->ota_port = 80; 162 | #endif 163 | #if GPIO_CMDS 164 | int i; 165 | for (i=0; i<17; i++) 166 | config->gpiomode[1] = UNDEFINED; 167 | #endif 168 | } 169 | 170 | int ICACHE_FLASH_ATTR config_load(sysconfig_p config) 171 | { 172 | if (config == NULL) return -1; 173 | uint16_t base_address = FLASH_BLOCK_NO; 174 | 175 | spi_flash_read(base_address* SPI_FLASH_SEC_SIZE, &config->magic_number, 4); 176 | 177 | if((config->magic_number != MAGIC_NUMBER)) 178 | { 179 | os_printf("\r\nNo config found, saving default in flash\r\n"); 180 | config_load_default(config); 181 | config_save(config); 182 | return -1; 183 | } 184 | 185 | os_printf("\r\nConfig found and loaded\r\n"); 186 | spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, (uint32 *) config, sizeof(sysconfig_t)); 187 | if (config->length != sizeof(sysconfig_t)) 188 | { 189 | os_printf("Length Mismatch, probably old version of config, loading defaults\r\n"); 190 | config_load_default(config); 191 | config_save(config); 192 | return -1; 193 | } 194 | 195 | ip_route_max = config->no_routes; 196 | os_memcpy(ip_rt_table, config->rt_table, sizeof(ip_rt_table)); 197 | 198 | #if ACLS 199 | os_memcpy(&acl, &(config->acl), sizeof(acl)); 200 | os_memcpy(&acl_freep, &(config->acl_freep), sizeof(acl_freep)); 201 | #endif 202 | return 0; 203 | } 204 | 205 | void ICACHE_FLASH_ATTR config_save(sysconfig_p config) 206 | { 207 | uint16_t base_address = FLASH_BLOCK_NO; 208 | config->no_routes = ip_route_max; 209 | os_memcpy(config->rt_table, ip_rt_table, sizeof(ip_rt_table)); 210 | 211 | #if ACLS 212 | os_memcpy(&(config->acl), &acl, sizeof(acl)); 213 | os_memcpy(&(config->acl_freep), &acl_freep, sizeof(acl_freep)); 214 | #endif 215 | os_printf("Saving configuration\r\n"); 216 | spi_flash_erase_sector(base_address); 217 | spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32 *)config, sizeof(sysconfig_t)); 218 | } 219 | 220 | void ICACHE_FLASH_ATTR blob_save(uint8_t blob_no, uint32_t *data, uint16_t len) 221 | { 222 | uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no; 223 | spi_flash_erase_sector(base_address); 224 | spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, data, len); 225 | } 226 | 227 | void ICACHE_FLASH_ATTR blob_load(uint8_t blob_no, uint32_t *data, uint16_t len) 228 | { 229 | uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no; 230 | spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, data, len); 231 | } 232 | 233 | void ICACHE_FLASH_ATTR blob_zero(uint8_t blob_no, uint16_t len) 234 | { 235 | int i; 236 | uint8_t z[len]; 237 | os_memset(z, 0,len); 238 | uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no; 239 | spi_flash_erase_sector(base_address); 240 | spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32_t *)z, len); 241 | } 242 | 243 | const uint8_t esp_init_data_default[] = { 244 | "\x05\x08\x04\x02\x05\x05\x05\x02\x05\x00\x04\x05\x05\x04\x05\x05" 245 | "\x04\xFE\xFD\xFF\xF0\xF0\xF0\xE0\xE0\xE0\xE1\x0A\xFF\xFF\xF8\x00" 246 | "\xF8\xF8\x4E\x4A\x46\x40\x3C\x38\x00\x00\x01\x01\x02\x03\x04\x05" 247 | "\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00" 248 | "\xE1\x0A\x00\x00\x00\x00\x00\x00\x00\x00\x01\x93\x43\x00\x00\x00" 249 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 250 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00" 251 | "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}; 252 | 253 | void user_rf_pre_init() { 254 | uint8_t esp_init_data_current[sizeof(esp_init_data_default)]; 255 | 256 | enum flash_size_map size_map = system_get_flash_size_map(); 257 | uint32 rf_cal_sec = 0, addr, i; 258 | //os_printf("\nUser preinit: "); 259 | switch (size_map) { 260 | case FLASH_SIZE_4M_MAP_256_256: 261 | rf_cal_sec = 128 - 5; 262 | break; 263 | 264 | case FLASH_SIZE_8M_MAP_512_512: 265 | rf_cal_sec = 256 - 5; 266 | break; 267 | 268 | case FLASH_SIZE_16M_MAP_512_512: 269 | case FLASH_SIZE_16M_MAP_1024_1024: 270 | rf_cal_sec = 512 - 5; 271 | break; 272 | 273 | case FLASH_SIZE_32M_MAP_512_512: 274 | case FLASH_SIZE_32M_MAP_1024_1024: 275 | rf_cal_sec = 1024 - 5; 276 | break; 277 | 278 | default: 279 | rf_cal_sec = 0; 280 | break; 281 | } 282 | 283 | addr = ((rf_cal_sec) * SPI_FLASH_SEC_SIZE)+SPI_FLASH_SEC_SIZE; 284 | spi_flash_read(addr, (uint32_t *)esp_init_data_current, sizeof(esp_init_data_current)); 285 | 286 | for (i=0; i= 17) { 84 | os_printf("easygpio_getGPIONameFunc Error: There is no GPIO%d, check your code\n", gpio_pin); 85 | return false; 86 | } 87 | if (gpio_pin == 16) { 88 | os_printf("easygpio_getGPIONameFunc Error: GPIO16 does not have gpio_name and gpio_func\n"); 89 | return false; 90 | } 91 | switch ( gpio_pin ) { 92 | case 0: 93 | *gpio_func = FUNC_GPIO0; 94 | *gpio_name = PERIPHS_IO_MUX_GPIO0_U; 95 | return true; 96 | case 1: 97 | *gpio_func = FUNC_GPIO1; 98 | *gpio_name = PERIPHS_IO_MUX_U0TXD_U; 99 | return true; 100 | case 2: 101 | *gpio_func = FUNC_GPIO2; 102 | *gpio_name = PERIPHS_IO_MUX_GPIO2_U; 103 | return true; 104 | case 3: 105 | *gpio_func = FUNC_GPIO3; 106 | *gpio_name = PERIPHS_IO_MUX_U0RXD_U; 107 | return true; 108 | case 4: 109 | *gpio_func = FUNC_GPIO4; 110 | *gpio_name = PERIPHS_IO_MUX_GPIO4_U; 111 | return true; 112 | case 5: 113 | *gpio_func = FUNC_GPIO5; 114 | *gpio_name = PERIPHS_IO_MUX_GPIO5_U; 115 | return true; 116 | case 9: 117 | *gpio_func = FUNC_GPIO9; 118 | *gpio_name = PERIPHS_IO_MUX_SD_DATA2_U; 119 | return true; 120 | case 10: 121 | *gpio_func = FUNC_GPIO10; 122 | *gpio_name = PERIPHS_IO_MUX_SD_DATA3_U; 123 | return true; 124 | case 12: 125 | *gpio_func = FUNC_GPIO12; 126 | *gpio_name = PERIPHS_IO_MUX_MTDI_U; 127 | return true; 128 | case 13: 129 | *gpio_func = FUNC_GPIO13; 130 | *gpio_name = PERIPHS_IO_MUX_MTCK_U; 131 | return true; 132 | case 14: 133 | *gpio_func = FUNC_GPIO14; 134 | *gpio_name = PERIPHS_IO_MUX_MTMS_U; 135 | return true; 136 | case 15: 137 | *gpio_func = FUNC_GPIO15; 138 | *gpio_name = PERIPHS_IO_MUX_MTDO_U; 139 | return true; 140 | default: 141 | return false; 142 | } 143 | return true; 144 | } 145 | 146 | /** 147 | * Sets the pull up registers for a pin. 148 | */ 149 | static void ICACHE_FLASH_ATTR 150 | easygpio_setupPullsByName(uint32_t gpio_name, EasyGPIO_PullStatus pullStatus) { 151 | 152 | if (EASYGPIO_PULLUP == pullStatus) { 153 | PIN_PULLUP_EN(gpio_name); 154 | } else { 155 | PIN_PULLUP_DIS(gpio_name); 156 | } 157 | } 158 | 159 | /** 160 | * Sets the pull registers for a pin. 161 | */ 162 | bool ICACHE_FLASH_ATTR 163 | easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus) { 164 | uint32_t gpio_name; 165 | uint8_t gpio_func; 166 | 167 | if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) { 168 | return false; 169 | } 170 | 171 | easygpio_setupPullsByName(gpio_name, pullStatus); 172 | return true; 173 | } 174 | 175 | /** 176 | * Sets the 'gpio_pin' pin as a GPIO and sets the pull register for that pin. 177 | * 'pullStatus' has no effect on output pins or GPIO16 178 | */ 179 | bool ICACHE_FLASH_ATTR 180 | easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode) { 181 | uint32_t gpio_name; 182 | uint8_t gpio_func; 183 | 184 | if (16==gpio_pin) { 185 | // ignoring pull status on GPIO16 for now 186 | if (EASYGPIO_OUTPUT == pinMode) { 187 | gpio16_output_conf(); 188 | } else { 189 | gpio16_input_conf(); 190 | } 191 | return true; 192 | } else if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) { 193 | return false; 194 | } 195 | 196 | PIN_FUNC_SELECT(gpio_name, gpio_func); 197 | easygpio_setupPullsByName(gpio_name, pullStatus); 198 | 199 | if (EASYGPIO_OUTPUT != pinMode) { 200 | GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin)); 201 | } else { 202 | // must enable the pin or else the WRITE_PERI_REG won't work 203 | gpio_output_set(0, 0, BIT(GPIO_ID_PIN(gpio_pin)),0); 204 | } 205 | return true; 206 | } 207 | 208 | /** 209 | * Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin. 210 | * The 'interruptArg' is the function argument that will be sent to your interruptHandler 211 | */ 212 | bool ICACHE_FLASH_ATTR 213 | easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg) { 214 | uint32_t gpio_name; 215 | uint8_t gpio_func; 216 | 217 | if (gpio_pin == 16) { 218 | os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n"); 219 | return false; 220 | } 221 | if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) { 222 | return false; 223 | } 224 | 225 | ETS_GPIO_INTR_ATTACH(interruptHandler, interruptArg); 226 | ETS_GPIO_INTR_DISABLE(); 227 | 228 | PIN_FUNC_SELECT(gpio_name, gpio_func); 229 | 230 | easygpio_setupPullsByName(gpio_name, pullStatus); 231 | 232 | // disable output 233 | GPIO_DIS_OUTPUT(gpio_pin); 234 | 235 | gpio_register_set(GPIO_PIN_ADDR(gpio_pin), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE) 236 | | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE) 237 | | GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE)); 238 | 239 | //clear gpio14 status 240 | GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(gpio_pin)); 241 | ETS_GPIO_INTR_ENABLE(); 242 | 243 | return true; 244 | } 245 | 246 | /** 247 | * Detach the interrupt handler from the 'gpio_pin' pin. 248 | */ 249 | bool ICACHE_FLASH_ATTR 250 | easygpio_detachInterrupt(uint8_t gpio_pin) { 251 | 252 | if (gpio_pin == 16) { 253 | os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n"); 254 | return false; 255 | } 256 | 257 | // Don't know how to detach interrupt, yet. 258 | // Quick and dirty fix - just disable the interrupt 259 | gpio_pin_intr_state_set(GPIO_ID_PIN(gpio_pin), GPIO_PIN_INTR_DISABLE); 260 | return true; 261 | } 262 | 263 | /** 264 | * Uniform way of setting GPIO output value. Handles GPIO 0-16. 265 | * 266 | * You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does. 267 | * Use easygpio_outputEnable() to change an input gpio to output mode. 268 | */ 269 | void 270 | easygpio_outputSet(uint8_t gpio_pin, uint8_t value) { 271 | if (16==gpio_pin) { 272 | WRITE_PERI_REG(RTC_GPIO_OUT, 273 | (READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value)); 274 | } else { 275 | #ifdef EASYGPIO_USE_GPIO_OUTPUT_SET 276 | GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value); 277 | #else 278 | if (value&1){ 279 | WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) | BIT(gpio_pin)); 280 | } else { 281 | WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) & ~BIT(gpio_pin)); 282 | } 283 | #endif 284 | } 285 | } 286 | 287 | /** 288 | * Uniform way of getting GPIO input value. Handles GPIO 0-16. 289 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 290 | * If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET(). 291 | */ 292 | uint8_t 293 | easygpio_inputGet(uint8_t gpio_pin) { 294 | if (16==gpio_pin) { 295 | return (READ_PERI_REG(RTC_GPIO_IN_DATA) & 1UL); 296 | } else { 297 | #ifdef EASYGPIO_USE_GPIO_INPUT_GET 298 | return GPIO_INPUT_GET(GPIO_ID_PIN(gpio_pin)); 299 | #else 300 | // this does *not* work, maybe GPIO_IN_ADDRESS is the wrong address 301 | return ((GPIO_REG_READ(GPIO_IN_ADDRESS) > gpio_pin) & 1UL); 302 | #endif 303 | } 304 | } 305 | 306 | /** 307 | * Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16. 308 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 309 | * This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too. 310 | */ 311 | void easygpio_outputDisable(uint8_t gpio_pin) { 312 | if (16==gpio_pin) { 313 | WRITE_PERI_REG(RTC_GPIO_ENABLE, 314 | READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL); //out disable 315 | } else { 316 | GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin)); 317 | } 318 | } 319 | 320 | /** 321 | * Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16. 322 | * The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place. 323 | * 324 | * This function: 325 | * - should only be used to convert a input pin into an output pin. 326 | * - is a little bit slower than easygpio_outputSet() so you should use that 327 | * function to just change output value. 328 | * - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too. 329 | */ 330 | void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value) { 331 | if (16==gpio_pin) { 332 | // write the value before flipping to output 333 | // - so we don't flash previous value for a few ns. 334 | WRITE_PERI_REG(RTC_GPIO_OUT, 335 | (READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value)); 336 | 337 | WRITE_PERI_REG(RTC_GPIO_ENABLE, 338 | (READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL) | 0x1UL); //out enable 339 | 340 | } else { 341 | GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value); 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /user/rboot-ota.c: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////// 2 | // rBoot OTA sample code for ESP8266 C API. 3 | // Copyright 2015 Richard A Burton 4 | // richardaburton@gmail.com 5 | // See license.txt for license terms. 6 | // OTA code based on SDK sample from Espressif. 7 | ////////////////////////////////////////////////// 8 | 9 | #include "user_config.h" 10 | #if OTAUPDATE == 1 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "rboot-ota.h" 19 | 20 | #include "config_flash.h" 21 | 22 | extern sysconfig_t config; 23 | extern struct espconn *currentconn; 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #define UPGRADE_FLAG_IDLE 0x00 30 | #define UPGRADE_FLAG_START 0x01 31 | #define UPGRADE_FLAG_FINISH 0x02 32 | 33 | typedef struct { 34 | uint8 rom_slot; // rom slot to update, or FLASH_BY_ADDR 35 | ota_callback callback; // user callback when completed 36 | uint32 total_len; 37 | uint32 content_len; 38 | bool ok; 39 | struct espconn *conn; 40 | ip_addr_t ip; 41 | rboot_write_status write_status; 42 | } upgrade_status; 43 | 44 | static upgrade_status *upgrade; 45 | static os_timer_t ota_timer; 46 | 47 | // clean up at the end of the update 48 | // will call the user call back to indicate completion 49 | void ICACHE_FLASH_ATTR rboot_ota_deinit() { 50 | 51 | bool result; 52 | uint8 rom_slot; 53 | ota_callback callback; 54 | struct espconn *conn; 55 | 56 | os_timer_disarm(&ota_timer); 57 | 58 | // save only remaining bits of interest from upgrade struct 59 | // then we can clean it up early, so disconnect callback 60 | // can distinguish between us calling it after update finished 61 | // or being called earlier in the update process 62 | conn = upgrade->conn; 63 | rom_slot = upgrade->rom_slot; 64 | callback = upgrade->callback; 65 | 66 | // clean up 67 | os_free(upgrade); 68 | upgrade = 0; 69 | 70 | // if connected, disconnect and clean up connection 71 | if (conn) espconn_disconnect(conn); 72 | 73 | // check for completion 74 | if (system_upgrade_flag_check() == UPGRADE_FLAG_FINISH) { 75 | result = true; 76 | } else { 77 | system_upgrade_flag_set(UPGRADE_FLAG_IDLE); 78 | result = false; 79 | } 80 | 81 | // call user call back 82 | if (callback) { 83 | callback(result, rom_slot); 84 | } 85 | 86 | } 87 | 88 | // called when connection receives data (hopefully the rom) 89 | static void ICACHE_FLASH_ATTR upgrade_recvcb(void *arg, char *pusrdata, unsigned short length) { 90 | 91 | char *ptrData, *ptrLen, *ptr; 92 | char response[128]; 93 | 94 | // disarm the timer 95 | os_timer_disarm(&ota_timer); 96 | 97 | if (!upgrade->ok && length < 12) { 98 | to_console("HTTP error - response too short\r\n"); 99 | system_os_post(0, SIG_CONSOLE_TX_RAW, (ETSParam) currentconn); 100 | 101 | rboot_ota_deinit(); 102 | return; 103 | } 104 | 105 | // Still in header? 106 | if (upgrade->content_len == 0) { 107 | // http response 200 ok? 108 | if (!upgrade->ok) { 109 | os_sprintf(response, "HTTP %c%c%c\r\n", pusrdata[9], pusrdata[10], pusrdata[11]); 110 | to_console(response); 111 | system_os_post(0, SIG_CONSOLE_TX_RAW, (ETSParam) currentconn); 112 | 113 | if (os_strncmp(pusrdata + 9, "200", 3) == 0) { 114 | upgrade->ok = true; 115 | } else { 116 | // fail, not a 200 response 117 | rboot_ota_deinit(); 118 | return; 119 | } 120 | } 121 | 122 | if ((ptrLen = (char*)os_strstr(pusrdata, "Content-Length: ")) 123 | && (ptrData = (char*)os_strstr(ptrLen, "\r\n\r\n"))) { 124 | 125 | // end of header/start of data 126 | ptrData += 4; 127 | // length of data after header in this chunk 128 | length -= (ptrData - pusrdata); 129 | // running total of download length 130 | upgrade->total_len += length; 131 | // process current chunk 132 | if (!rboot_write_flash(&upgrade->write_status, (uint8*)ptrData, length)) { 133 | // write error 134 | rboot_ota_deinit(); 135 | return; 136 | } 137 | // work out total download size 138 | ptrLen += 16; 139 | ptr = (char *)os_strstr(ptrLen, "\r\n"); 140 | *ptr = '\0'; // destructive 141 | upgrade->content_len = atoi(ptrLen); 142 | 143 | os_sprintf(response, "Binary length: %d\r\n", upgrade->content_len); 144 | to_console(response); 145 | system_os_post(0, SIG_CONSOLE_TX_RAW, (ETSParam) currentconn); 146 | } else { 147 | return; 148 | } 149 | } else { 150 | // not the first chunk, process it 151 | os_sprintf(response, " %d KB \r", upgrade->total_len/1024); 152 | to_console(response); 153 | system_os_post(0, SIG_CONSOLE_TX_RAW, (ETSParam) currentconn); 154 | 155 | upgrade->total_len += length; 156 | if (!rboot_write_flash(&upgrade->write_status, (uint8*)pusrdata, length)) { 157 | // write error 158 | rboot_ota_deinit(); 159 | return; 160 | } 161 | } 162 | 163 | // check if we are finished 164 | if (upgrade->total_len == upgrade->content_len) { 165 | system_upgrade_flag_set(UPGRADE_FLAG_FINISH); 166 | // clean up and call user callback 167 | rboot_ota_deinit(); 168 | } else if (upgrade->conn->state != ESPCONN_READ) { 169 | // fail, but how do we get here? premature end of stream? 170 | rboot_ota_deinit(); 171 | } else { 172 | // timer for next recv 173 | os_timer_setfn(&ota_timer, (os_timer_func_t *)rboot_ota_deinit, 0); 174 | os_timer_arm(&ota_timer, OTA_NETWORK_TIMEOUT, 0); 175 | } 176 | } 177 | 178 | // disconnect callback, clean up the connection 179 | // we also call this ourselves 180 | static void ICACHE_FLASH_ATTR upgrade_disconcb(void *arg) { 181 | // use passed ptr, as upgrade struct may have gone by now 182 | struct espconn *conn = (struct espconn*)arg; 183 | 184 | os_timer_disarm(&ota_timer); 185 | if (conn) { 186 | if (conn->proto.tcp) { 187 | os_free(conn->proto.tcp); 188 | } 189 | os_free(conn); 190 | } 191 | 192 | // is upgrade struct still around? 193 | // if so disconnect was from remote end, or we called 194 | // ourselves to cleanup a failed connection attempt 195 | // must ensure disconnect was for this upgrade attempt, 196 | // not a previous one! this call back is async so another 197 | // upgrade struct may have been created already 198 | if (upgrade && (upgrade->conn == conn)) { 199 | // mark connection as gone 200 | upgrade->conn = 0; 201 | // end the update process 202 | rboot_ota_deinit(); 203 | } 204 | } 205 | 206 | // successfully connected to update server, send the request 207 | static void ICACHE_FLASH_ATTR upgrade_connect_cb(void *arg) { 208 | 209 | uint8 *request; 210 | 211 | // disable the timeout 212 | os_timer_disarm(&ota_timer); 213 | 214 | // register connection callbacks 215 | espconn_regist_disconcb(upgrade->conn, upgrade_disconcb); 216 | espconn_regist_recvcb(upgrade->conn, upgrade_recvcb); 217 | 218 | // http request string 219 | request = (uint8 *)os_malloc(512); 220 | if (!request) { 221 | os_printf("No ram!\r\n"); 222 | rboot_ota_deinit(); 223 | return; 224 | } 225 | os_sprintf((char*)request, 226 | "GET /%s HTTP/1.0\r\nHost: %s\r\n%s", 227 | (upgrade->rom_slot == FLASH_BY_ADDR ? OTA_FILE : (upgrade->rom_slot == 0 ? OTA_ROM0 : OTA_ROM1)), 228 | config.ota_host, HTTP_HEADER); 229 | 230 | // send the http request, with timeout for reply 231 | os_timer_setfn(&ota_timer, (os_timer_func_t *)rboot_ota_deinit, 0); 232 | os_timer_arm(&ota_timer, OTA_NETWORK_TIMEOUT, 0); 233 | espconn_sent(upgrade->conn, request, os_strlen((char*)request)); 234 | os_free(request); 235 | } 236 | 237 | // connection attempt timed out 238 | static void ICACHE_FLASH_ATTR connect_timeout_cb() { 239 | os_printf("Connect timeout.\r\n"); 240 | // not connected so don't call disconnect on the connection 241 | // but call our own disconnect callback to do the cleanup 242 | upgrade_disconcb(upgrade->conn); 243 | } 244 | 245 | static const char* ICACHE_FLASH_ATTR esp_errstr(sint8 err) { 246 | switch(err) { 247 | case ESPCONN_OK: 248 | return "No error, everything OK."; 249 | case ESPCONN_MEM: 250 | return "Out of memory error."; 251 | case ESPCONN_TIMEOUT: 252 | return "Timeout."; 253 | case ESPCONN_RTE: 254 | return "Routing problem."; 255 | case ESPCONN_INPROGRESS: 256 | return "Operation in progress."; 257 | case ESPCONN_ABRT: 258 | return "Connection aborted."; 259 | case ESPCONN_RST: 260 | return "Connection reset."; 261 | case ESPCONN_CLSD: 262 | return "Connection closed."; 263 | case ESPCONN_CONN: 264 | return "Not connected."; 265 | case ESPCONN_ARG: 266 | return "Illegal argument."; 267 | case ESPCONN_ISCONN: 268 | return "Already connected."; 269 | } 270 | } 271 | 272 | // call back for lost connection 273 | static void ICACHE_FLASH_ATTR upgrade_recon_cb(void *arg, sint8 errType) { 274 | os_printf("Connection error: %s\r\n", esp_errstr(errType)); 275 | //os_printf(esp_errstr(errType)); 276 | //os_printf("\r\n"); 277 | // not connected so don't call disconnect on the connection 278 | // but call our own disconnect callback to do the cleanup 279 | upgrade_disconcb(upgrade->conn); 280 | } 281 | 282 | // call back for dns lookup 283 | static void ICACHE_FLASH_ATTR upgrade_resolved(const char *name, ip_addr_t *ip, void *arg) { 284 | 285 | if (ip == 0) { 286 | os_printf("DNS lookup failed for: %s\r\n", config.ota_host); 287 | //os_printf(config.ota_host); 288 | //os_printf("\r\n"); 289 | // not connected so don't call disconnect on the connection 290 | // but call our own disconnect callback to do the cleanup 291 | upgrade_disconcb(upgrade->conn); 292 | return; 293 | } 294 | 295 | // set up connection 296 | upgrade->conn->type = ESPCONN_TCP; 297 | upgrade->conn->state = ESPCONN_NONE; 298 | upgrade->conn->proto.tcp->local_port = espconn_port(); 299 | upgrade->conn->proto.tcp->remote_port = config.ota_port; 300 | *(ip_addr_t*)upgrade->conn->proto.tcp->remote_ip = *ip; 301 | // set connection call backs 302 | espconn_regist_connectcb(upgrade->conn, upgrade_connect_cb); 303 | espconn_regist_reconcb(upgrade->conn, upgrade_recon_cb); 304 | 305 | // try to connect 306 | espconn_connect(upgrade->conn); 307 | 308 | // set connection timeout timer 309 | os_timer_disarm(&ota_timer); 310 | os_timer_setfn(&ota_timer, (os_timer_func_t *)connect_timeout_cb, 0); 311 | os_timer_arm(&ota_timer, OTA_NETWORK_TIMEOUT, 0); 312 | } 313 | 314 | // start the ota process, with user supplied options 315 | bool ICACHE_FLASH_ATTR rboot_ota_start(ota_callback callback) { 316 | 317 | uint8 slot; 318 | rboot_config bootconf; 319 | err_t result; 320 | 321 | // check not already updating 322 | if (system_upgrade_flag_check() == UPGRADE_FLAG_START) { 323 | return false; 324 | } 325 | 326 | // create upgrade status structure 327 | upgrade = (upgrade_status*)os_zalloc(sizeof(upgrade_status)); 328 | if (!upgrade) { 329 | os_printf("No ram!\r\n"); 330 | return false; 331 | } 332 | 333 | // store the callback 334 | upgrade->callback = callback; 335 | 336 | // get details of rom slot to update 337 | bootconf = rboot_get_config(); 338 | slot = bootconf.current_rom; 339 | if (slot == 0) slot = 1; else slot = 0; 340 | upgrade->rom_slot = slot; 341 | 342 | // flash to rom slot 343 | upgrade->write_status = rboot_write_init(bootconf.roms[upgrade->rom_slot]); 344 | // to flash a file (e.g. containing a filesystem) to an arbitrary location 345 | // (e.g. 0x40000 bytes after the start of the rom) use code this like instead: 346 | // Note: address must be start of a sector (multiple of 4k)! 347 | //upgrade->write_status = rboot_write_init(bootconf.roms[upgrade->rom_slot] + 0x40000); 348 | //upgrade->rom_slot = FLASH_BY_ADDR; 349 | 350 | // create connection 351 | upgrade->conn = (struct espconn *)os_zalloc(sizeof(struct espconn)); 352 | if (!upgrade->conn) { 353 | os_printf("No ram!\r\n"); 354 | os_free(upgrade); 355 | return false; 356 | } 357 | upgrade->conn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); 358 | if (!upgrade->conn->proto.tcp) { 359 | os_printf("No ram!\r\n"); 360 | os_free(upgrade->conn); 361 | os_free(upgrade); 362 | return false; 363 | } 364 | 365 | // set update flag 366 | system_upgrade_flag_set(UPGRADE_FLAG_START); 367 | 368 | // dns lookup 369 | result = espconn_gethostbyname(upgrade->conn, config.ota_host, &upgrade->ip, upgrade_resolved); 370 | if (result == ESPCONN_OK) { 371 | // hostname is already cached or is actually a dotted decimal ip address 372 | upgrade_resolved(0, &upgrade->ip, upgrade->conn); 373 | } else if (result == ESPCONN_INPROGRESS) { 374 | // lookup taking place, will call upgrade_resolved on completion 375 | } else { 376 | os_printf("DNS error!\r\n"); 377 | os_free(upgrade->conn->proto.tcp); 378 | os_free(upgrade->conn); 379 | os_free(upgrade); 380 | return false; 381 | } 382 | 383 | return true; 384 | } 385 | 386 | #ifdef __cplusplus 387 | } 388 | #endif 389 | 390 | #endif -------------------------------------------------------------------------------- /include/driver/spi_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 - 2011 Espressif System 3 | * Modified by David Ogilvy (MetalPhreak) 4 | * Based on original file included in SDK 1.0.0 5 | * 6 | * Missing defines from previous SDK versions have 7 | * been added and are noted with comments. The 8 | * names of these defines are likely to change. 9 | */ 10 | 11 | #ifndef SPI_REGISTER_H_INCLUDED 12 | #define SPI_REGISTER_H_INCLUDED 13 | 14 | #define REG_SPI_BASE(i) (0x60000200-i*0x100) 15 | 16 | #define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) 17 | #define SPI_FLASH_READ (BIT(31)) //From previous SDK 18 | #define SPI_FLASH_WREN (BIT(30)) //From previous SDK 19 | #define SPI_FLASH_WRDI (BIT(29)) //From previous SDK 20 | #define SPI_FLASH_RDID (BIT(28)) //From previous SDK 21 | #define SPI_FLASH_RDSR (BIT(27)) //From previous SDK 22 | #define SPI_FLASH_WRSR (BIT(26)) //From previous SDK 23 | #define SPI_FLASH_PP (BIT(25)) //From previous SDK 24 | #define SPI_FLASH_SE (BIT(24)) //From previous SDK 25 | #define SPI_FLASH_BE (BIT(23)) //From previous SDK 26 | #define SPI_FLASH_CE (BIT(22)) //From previous SDK 27 | #define SPI_FLASH_DP (BIT(21)) //From previous SDK 28 | #define SPI_FLASH_RES (BIT(20)) //From previous SDK 29 | #define SPI_FLASH_HPM (BIT(19)) //From previous SDK 30 | #define SPI_USR (BIT(18)) 31 | 32 | #define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) 33 | 34 | #define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) 35 | #define SPI_WR_BIT_ORDER (BIT(26)) 36 | #define SPI_RD_BIT_ORDER (BIT(25)) 37 | #define SPI_QIO_MODE (BIT(24)) 38 | #define SPI_DIO_MODE (BIT(23)) 39 | #define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK 40 | #define SPI_WP_REG (BIT(21)) //From previous SDK 41 | #define SPI_QOUT_MODE (BIT(20)) 42 | #define SPI_SHARE_BUS (BIT(19)) //From previous SDK 43 | #define SPI_HOLD_MODE (BIT(18)) //From previous SDK 44 | #define SPI_ENABLE_AHB (BIT(17)) //From previous SDK 45 | #define SPI_SST_AAI (BIT(16)) //From previous SDK 46 | #define SPI_RESANDRES (BIT(15)) //From previous SDK 47 | #define SPI_DOUT_MODE (BIT(14)) 48 | #define SPI_FASTRD_MODE (BIT(13)) 49 | 50 | #define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers. 51 | #define SPI_CS_HOLD_DELAY 0x0000000F //Espressif BBS 52 | #define SPI_CS_HOLD_DELAY_S 28 //Espressif BBS 53 | #define SPI_CS_HOLD_DELAY_RES 0x00000FFF //Espressif BBS 54 | #define SPI_CS_HOLD_DELAY_RES_S 16 //Espressif BBS 55 | #define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK 56 | #define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK 57 | 58 | 59 | #define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) 60 | #define SPI_STATUS_EXT 0x000000FF //From previous SDK 61 | #define SPI_STATUS_EXT_S 24 //From previous SDK 62 | #define SPI_WB_MODE 0x000000FF //From previous SDK 63 | #define SPI_WB_MODE_S 16 //From previous SDK 64 | #define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK 65 | #define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK 66 | #define SPI_FLASH_BP2 (BIT(4)) //From previous SDK 67 | #define SPI_FLASH_BP1 (BIT(3)) //From previous SDK 68 | #define SPI_FLASH_BP0 (BIT(2)) //From previous SDK 69 | #define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK 70 | #define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK 71 | 72 | #define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) 73 | #define SPI_CS_DELAY_NUM 0x0000000F 74 | #define SPI_CS_DELAY_NUM_S 28 75 | #define SPI_CS_DELAY_MODE 0x00000003 76 | #define SPI_CS_DELAY_MODE_S 26 77 | #define SPI_MOSI_DELAY_NUM 0x00000007 78 | #define SPI_MOSI_DELAY_NUM_S 23 79 | #define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk 80 | //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk 81 | //mode 2 : Do not use this mode. 82 | #define SPI_MOSI_DELAY_MODE_S 21 83 | #define SPI_MISO_DELAY_NUM 0x00000007 84 | #define SPI_MISO_DELAY_NUM_S 18 85 | #define SPI_MISO_DELAY_MODE 0x00000003 86 | #define SPI_MISO_DELAY_MODE_S 16 87 | #define SPI_CK_OUT_HIGH_MODE 0x0000000F 88 | #define SPI_CK_OUT_HIGH_MODE_S 12 89 | #define SPI_CK_OUT_LOW_MODE 0x0000000F 90 | #define SPI_CK_OUT_LOW_MODE_S 8 91 | #define SPI_HOLD_TIME 0x0000000F 92 | #define SPI_HOLD_TIME_S 4 93 | #define SPI_SETUP_TIME 0x0000000F 94 | #define SPI_SETUP_TIME_S 0 95 | 96 | #define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) 97 | #define SPI_CLK_EQU_SYSCLK (BIT(31)) 98 | #define SPI_CLKDIV_PRE 0x00001FFF 99 | #define SPI_CLKDIV_PRE_S 18 100 | #define SPI_CLKCNT_N 0x0000003F 101 | #define SPI_CLKCNT_N_S 12 102 | #define SPI_CLKCNT_H 0x0000003F 103 | #define SPI_CLKCNT_H_S 6 104 | #define SPI_CLKCNT_L 0x0000003F 105 | #define SPI_CLKCNT_L_S 0 106 | 107 | #define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) 108 | #define SPI_USR_COMMAND (BIT(31)) 109 | #define SPI_USR_ADDR (BIT(30)) 110 | #define SPI_USR_DUMMY (BIT(29)) 111 | #define SPI_USR_MISO (BIT(28)) 112 | #define SPI_USR_MOSI (BIT(27)) 113 | #define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK 114 | #define SPI_USR_MOSI_HIGHPART (BIT(25)) 115 | #define SPI_USR_MISO_HIGHPART (BIT(24)) 116 | #define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK 117 | #define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK 118 | #define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK 119 | #define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK 120 | #define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK 121 | #define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK 122 | #define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK 123 | #define SPI_SIO (BIT(16)) 124 | #define SPI_FWRITE_QIO (BIT(15)) 125 | #define SPI_FWRITE_DIO (BIT(14)) 126 | #define SPI_FWRITE_QUAD (BIT(13)) 127 | #define SPI_FWRITE_DUAL (BIT(12)) 128 | #define SPI_WR_BYTE_ORDER (BIT(11)) 129 | #define SPI_RD_BYTE_ORDER (BIT(10)) 130 | #define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK 131 | #define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK 132 | #define SPI_CK_OUT_EDGE (BIT(7)) 133 | #define SPI_CK_I_EDGE (BIT(6)) 134 | #define SPI_CS_SETUP (BIT(5)) 135 | #define SPI_CS_HOLD (BIT(4)) 136 | #define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK 137 | #define SPI_FLASH_MODE (BIT(2)) 138 | #define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK 139 | #define SPI_DOUTDIN (BIT(0)) //From previous SDK 140 | 141 | //AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ? 142 | 143 | 144 | #define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) 145 | #define SPI_USR_ADDR_BITLEN 0x0000003F 146 | #define SPI_USR_ADDR_BITLEN_S 26 147 | #define SPI_USR_MOSI_BITLEN 0x000001FF 148 | #define SPI_USR_MOSI_BITLEN_S 17 149 | #define SPI_USR_MISO_BITLEN 0x000001FF 150 | #define SPI_USR_MISO_BITLEN_S 8 151 | #define SPI_USR_DUMMY_CYCLELEN 0x000000FF 152 | #define SPI_USR_DUMMY_CYCLELEN_S 0 153 | 154 | #define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) 155 | #define SPI_USR_COMMAND_BITLEN 0x0000000F 156 | #define SPI_USR_COMMAND_BITLEN_S 28 157 | #define SPI_USR_COMMAND_VALUE 0x0000FFFF 158 | #define SPI_USR_COMMAND_VALUE_S 0 159 | 160 | #define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) 161 | //previously defined as SPI_FLASH_USER3. No further info available. 162 | 163 | #define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) 164 | #define SPI_IDLE_EDGE (BIT(29)) 165 | #define SPI_CS2_DIS (BIT(2)) 166 | #define SPI_CS1_DIS (BIT(1)) 167 | #define SPI_CS0_DIS (BIT(0)) 168 | 169 | #define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) 170 | #define SPI_SYNC_RESET (BIT(31)) 171 | #define SPI_SLAVE_MODE (BIT(30)) 172 | #define SPI_SLV_WR_RD_BUF_EN (BIT(29)) 173 | #define SPI_SLV_WR_RD_STA_EN (BIT(28)) 174 | #define SPI_SLV_CMD_DEFINE (BIT(27)) 175 | #define SPI_TRANS_CNT 0x0000000F 176 | #define SPI_TRANS_CNT_S 23 177 | #define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK 178 | #define SPI_SLV_LAST_STATE_S 20 //From previous SDK 179 | #define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK 180 | #define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK 181 | #define SPI_CS_I_MODE 0x00000003 //From previous SDK 182 | #define SPI_CS_I_MODE_S 10 //From previous SDK 183 | #define SPI_TRANS_DONE_EN (BIT(9)) 184 | #define SPI_SLV_WR_STA_DONE_EN (BIT(8)) 185 | #define SPI_SLV_RD_STA_DONE_EN (BIT(7)) 186 | #define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) 187 | #define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) 188 | #define SLV_SPI_INT_EN 0x0000001f 189 | #define SLV_SPI_INT_EN_S 5 190 | #define SPI_TRANS_DONE (BIT(4)) 191 | #define SPI_SLV_WR_STA_DONE (BIT(3)) 192 | #define SPI_SLV_RD_STA_DONE (BIT(2)) 193 | #define SPI_SLV_WR_BUF_DONE (BIT(1)) 194 | #define SPI_SLV_RD_BUF_DONE (BIT(0)) 195 | 196 | #define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) 197 | #define SPI_SLV_STATUS_BITLEN 0x0000001F 198 | #define SPI_SLV_STATUS_BITLEN_S 27 199 | #define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK 200 | #define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK 201 | #define SPI_SLV_BUF_BITLEN 0x000001FF 202 | #define SPI_SLV_BUF_BITLEN_S 16 203 | #define SPI_SLV_RD_ADDR_BITLEN 0x0000003F 204 | #define SPI_SLV_RD_ADDR_BITLEN_S 10 205 | #define SPI_SLV_WR_ADDR_BITLEN 0x0000003F 206 | #define SPI_SLV_WR_ADDR_BITLEN_S 4 207 | #define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) 208 | #define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) 209 | #define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) 210 | #define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) 211 | 212 | 213 | 214 | #define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) 215 | #define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF 216 | #define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 217 | #define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF 218 | #define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 219 | #define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF 220 | #define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 221 | #define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF 222 | #define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 223 | 224 | #define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) 225 | #define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF 226 | #define SPI_SLV_WRSTA_CMD_VALUE_S 24 227 | #define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF 228 | #define SPI_SLV_RDSTA_CMD_VALUE_S 16 229 | #define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF 230 | #define SPI_SLV_WRBUF_CMD_VALUE_S 8 231 | #define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF 232 | #define SPI_SLV_RDBUF_CMD_VALUE_S 0 233 | 234 | //Previous SDKs referred to these following registers as SPI_C0 etc. 235 | 236 | #define SPI_W0(i) (REG_SPI_BASE(i) +0x40) 237 | #define SPI_W1(i) (REG_SPI_BASE(i) +0x44) 238 | #define SPI_W2(i) (REG_SPI_BASE(i) +0x48) 239 | #define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) 240 | #define SPI_W4(i) (REG_SPI_BASE(i) +0x50) 241 | #define SPI_W5(i) (REG_SPI_BASE(i) +0x54) 242 | #define SPI_W6(i) (REG_SPI_BASE(i) +0x58) 243 | #define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) 244 | #define SPI_W8(i) (REG_SPI_BASE(i) +0x60) 245 | #define SPI_W9(i) (REG_SPI_BASE(i) +0x64) 246 | #define SPI_W10(i) (REG_SPI_BASE(i) +0x68) 247 | #define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) 248 | #define SPI_W12(i) (REG_SPI_BASE(i) +0x70) 249 | #define SPI_W13(i) (REG_SPI_BASE(i) +0x74) 250 | #define SPI_W14(i) (REG_SPI_BASE(i) +0x78) 251 | #define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) 252 | 253 | // +0x80 to +0xBC could be SPI_W16 through SPI_W31? 254 | 255 | // +0xC0 to +0xEC not currently defined. 256 | 257 | #define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers. 258 | #define SPI_T_PP_ENA (BIT(31)) //From previous SDK 259 | #define SPI_T_PP_SHIFT 0x0000000F //From previous SDK 260 | #define SPI_T_PP_SHIFT_S 16 //From previous SDK 261 | #define SPI_T_PP_TIME 0x00000FFF //From previous SDK 262 | #define SPI_T_PP_TIME_S 0 //From previous SDK 263 | 264 | #define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers. 265 | #define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK 266 | #define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK 267 | #define SPI_T_ERASE_SHIFT_S 16 //From previous SDK 268 | #define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK 269 | #define SPI_T_ERASE_TIME_S 0 //From previous SDK 270 | 271 | #define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers. 272 | #define SPI_ST 0x00000007 //From previous SDK 273 | #define SPI_ST_S 0 //From previous SDK 274 | 275 | #define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) 276 | #define SPI_INT_HOLD_ENA 0x00000003 277 | #define SPI_INT_HOLD_ENA_S 0 278 | #endif // SPI_REGISTER_H_INCLUDED 279 | -------------------------------------------------------------------------------- /driver/spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | #include "driver/spi.h" 27 | 28 | 29 | //////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // Function Name: spi_init 32 | // Description: Wrapper to setup HSPI/SPI GPIO pins and default SPI clock 33 | // Parameters: spi_no - SPI (0) or HSPI (1) 34 | // 35 | //////////////////////////////////////////////////////////////////////////////// 36 | 37 | void spi_init(uint8 spi_no){ 38 | 39 | if(spi_no > 1) return; //Only SPI and HSPI are valid spi modules. 40 | 41 | spi_init_gpio(spi_no, SPI_CLK_USE_DIV); 42 | spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV); 43 | spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); 44 | spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); 45 | 46 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD); 47 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); 48 | 49 | } 50 | 51 | //////////////////////////////////////////////////////////////////////////////// 52 | 53 | //////////////////////////////////////////////////////////////////////////////// 54 | // 55 | // Function Name: spi_mode 56 | // Description: Configures SPI mode parameters for clock edge and clock polarity. 57 | // Parameters: spi_no - SPI (0) or HSPI (1) 58 | // spi_cpha - (0) Data is valid on clock leading edge 59 | // (1) Data is valid on clock trailing edge 60 | // spi_cpol - (0) Clock is low when inactive 61 | // (1) Clock is high when inactive 62 | // 63 | //////////////////////////////////////////////////////////////////////////////// 64 | 65 | void spi_mode(uint8 spi_no, uint8 spi_cpha,uint8 spi_cpol){ 66 | if(!spi_cpha == !spi_cpol) { 67 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE); 68 | } else { 69 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE); 70 | } 71 | 72 | if (spi_cpol) { 73 | SET_PERI_REG_MASK(SPI_PIN(spi_no), SPI_IDLE_EDGE); 74 | } else { 75 | CLEAR_PERI_REG_MASK(SPI_PIN(spi_no), SPI_IDLE_EDGE); 76 | } 77 | } 78 | 79 | 80 | //////////////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////////////// 83 | // 84 | // Function Name: spi_init_gpio 85 | // Description: Initialises the GPIO pins for use as SPI pins. 86 | // Parameters: spi_no - SPI (0) or HSPI (1) 87 | // sysclk_as_spiclk - SPI_CLK_80MHZ_NODIV (1) if using 80MHz 88 | // sysclock for SPI clock. 89 | // SPI_CLK_USE_DIV (0) if using divider to 90 | // get lower SPI clock speed. 91 | // 92 | //////////////////////////////////////////////////////////////////////////////// 93 | 94 | void spi_init_gpio(uint8 spi_no, uint8 sysclk_as_spiclk){ 95 | 96 | // if(spi_no > 1) return; //Not required. Valid spi_no is checked with if/elif below. 97 | 98 | uint32 clock_div_flag = 0; 99 | if(sysclk_as_spiclk){ 100 | clock_div_flag = 0x0001; 101 | } 102 | 103 | if(spi_no==SPI){ 104 | WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005|(clock_div_flag<<8)); //Set bit 8 if 80MHz sysclock required 105 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1); 106 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1); 107 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1); 108 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1); 109 | }else if(spi_no==HSPI){ 110 | WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105|(clock_div_flag<<9)); //Set bit 9 if 80MHz sysclock required 111 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); //GPIO12 is HSPI MISO pin (Master Data In) 112 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); //GPIO13 is HSPI MOSI pin (Master Data Out) 113 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); //GPIO14 is HSPI CLK pin (Clock) 114 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); //GPIO15 is HSPI CS pin (Chip Select / Slave Select) 115 | } 116 | 117 | } 118 | 119 | //////////////////////////////////////////////////////////////////////////////// 120 | 121 | //////////////////////////////////////////////////////////////////////////////// 122 | // 123 | // Function Name: spi_clock 124 | // Description: sets up the control registers for the SPI clock 125 | // Parameters: spi_no - SPI (0) or HSPI (1) 126 | // prediv - predivider value (actual division value) 127 | // cntdiv - postdivider value (actual division value) 128 | // Set either divider to 0 to disable all division (80MHz sysclock) 129 | // 130 | //////////////////////////////////////////////////////////////////////////////// 131 | 132 | void spi_clock(uint8 spi_no, uint16 prediv, uint8 cntdiv){ 133 | 134 | if(spi_no > 1) return; 135 | 136 | if((prediv==0)|(cntdiv==0)){ 137 | 138 | WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK); 139 | 140 | } else { 141 | 142 | WRITE_PERI_REG(SPI_CLOCK(spi_no), 143 | (((prediv-1)&SPI_CLKDIV_PRE)<>1)&SPI_CLKCNT_H)< 1) return; 174 | 175 | if(byte_order){ 176 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); 177 | } else { 178 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); 179 | } 180 | } 181 | //////////////////////////////////////////////////////////////////////////////// 182 | 183 | //////////////////////////////////////////////////////////////////////////////// 184 | // 185 | // Function Name: spi_rx_byte_order 186 | // Description: Setup the byte order for shifting data into buffer 187 | // Parameters: spi_no - SPI (0) or HSPI (1) 188 | // byte_order - SPI_BYTE_ORDER_HIGH_TO_LOW (1) 189 | // Data is read in starting with Bit31 and down to Bit0 190 | // 191 | // SPI_BYTE_ORDER_LOW_TO_HIGH (0) 192 | // Data is read in starting with the lowest BYTE, from 193 | // MSB to LSB, followed by the second lowest BYTE, from 194 | // MSB to LSB, followed by the second highest BYTE, from 195 | // MSB to LSB, followed by the highest BYTE, from MSB to LSB 196 | // 0xABCDEFGH would be read as 0xGHEFCDAB 197 | // 198 | // 199 | //////////////////////////////////////////////////////////////////////////////// 200 | 201 | void spi_rx_byte_order(uint8 spi_no, uint8 byte_order){ 202 | 203 | if(spi_no > 1) return; 204 | 205 | if(byte_order){ 206 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); 207 | } else { 208 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); 209 | } 210 | } 211 | //////////////////////////////////////////////////////////////////////////////// 212 | 213 | //////////////////////////////////////////////////////////////////////////////// 214 | // 215 | // Function Name: spi_transaction 216 | // Description: SPI transaction function 217 | // Parameters: spi_no - SPI (0) or HSPI (1) 218 | // cmd_bits - actual number of bits to transmit 219 | // cmd_data - command data 220 | // addr_bits - actual number of bits to transmit 221 | // addr_data - address data 222 | // dout_bits - actual number of bits to transmit 223 | // dout_data - output data 224 | // din_bits - actual number of bits to receive 225 | // 226 | // Returns: read data - uint32 containing read in data only if RX was set 227 | // 0 - something went wrong (or actual read data was 0) 228 | // 1 - data sent ok (or actual read data is 1) 229 | // Note: all data is assumed to be stored in the lower bits of 230 | // the data variables (for anything <32 bits). 231 | // 232 | //////////////////////////////////////////////////////////////////////////////// 233 | 234 | uint32 spi_transaction(uint8 spi_no, uint8 cmd_bits, uint16 cmd_data, uint32 addr_bits, uint32 addr_data, uint32 dout_bits, uint32 dout_data, 235 | uint32 din_bits, uint32 dummy_bits){ 236 | 237 | if(spi_no > 1) return 0; //Check for a valid SPI 238 | 239 | //code for custom Chip Select as GPIO PIN here 240 | 241 | while(spi_busy(spi_no)); //wait for SPI to be ready 242 | 243 | //########## Enable SPI Functions ##########// 244 | //disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. 245 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_MISO|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_DUMMY); 246 | 247 | //enable functions based on number of bits. 0 bits = disabled. 248 | //This is rather inefficient but allows for a very generic function. 249 | //CMD ADDR and MOSI are set below to save on an extra if statement. 250 | // if(cmd_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);} 251 | // if(addr_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);} 252 | if(din_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);} 253 | if(dummy_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);} 254 | //########## END SECTION ##########// 255 | 256 | //########## Setup Bitlengths ##########// 257 | WRITE_PERI_REG(SPI_USER1(spi_no), ((addr_bits-1)&SPI_USR_ADDR_BITLEN)<>8)&0xff) | ((command<<8)&0xff00); //swap byte order 268 | WRITE_PERI_REG(SPI_USER2(spi_no), ((((cmd_bits-1)&SPI_USR_COMMAND_BITLEN)<>(32-(dout_bits - dout_extra_bits)))&dout_data)); 298 | } else { 299 | WRITE_PERI_REG(SPI_W0(spi_no), dout_data); 300 | } 301 | } 302 | } 303 | //########## END SECTION ##########// 304 | 305 | //########## Begin SPI Transaction ##########// 306 | SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); 307 | //########## END SECTION ##########// 308 | 309 | //########## Return DIN data ##########// 310 | if(din_bits) { 311 | while(spi_busy(spi_no)); //wait for SPI transaction to complete 312 | 313 | if(READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) { 314 | return READ_PERI_REG(SPI_W0(spi_no)) >> (32-din_bits); //Assuming data in is written to MSB. TBC 315 | } else { 316 | return READ_PERI_REG(SPI_W0(spi_no)); //Read in the same way as DOUT is sent. Note existing contents of SPI_W0 remain unless overwritten! 317 | } 318 | 319 | return 0; //something went wrong 320 | } 321 | //########## END SECTION ##########// 322 | 323 | //Transaction completed 324 | return 1; //success 325 | } 326 | 327 | //////////////////////////////////////////////////////////////////////////////// 328 | 329 | /*/////////////////////////////////////////////////////////////////////////////// 330 | // 331 | // Function Name: func 332 | // Description: 333 | // Parameters: 334 | // 335 | //////////////////////////////////////////////////////////////////////////////// 336 | 337 | void func(params){ 338 | 339 | } 340 | 341 | ///////////////////////////////////////////////////////////////////////////////*/ 342 | 343 | 344 | --------------------------------------------------------------------------------