├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── driver ├── espenc.c ├── espenc.h ├── spi.c ├── spi.h └── spi_register.h ├── include ├── driver └── lwip │ └── ip_addr.h └── user ├── user_config.h └── user_main.c /.gitignore: -------------------------------------------------------------------------------- 1 | firmware/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ESP8266_SPI_Driver"] 2 | path = ESP8266_SPI_Driver 3 | url = https://github.com/MetalPhreak/ESP8266_SPI_Driver 4 | -------------------------------------------------------------------------------- /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 | # Output directors to store intermediate compiled files 16 | # relative to the project directory 17 | BUILD_BASE = build 18 | FW_BASE = firmware 19 | 20 | # base directory for the compiler 21 | XTENSA_TOOLS_ROOT ?= /home/rbattles/nas/work/esp-open-sdk/xtensa-lx106-elf/bin 22 | 23 | # base directory of the ESP8266 SDK package, absolute 24 | SDK_BASE ?= /home/rbattles/nas/work/esp-open-sdk/esp_iot_sdk_v1.2.0 25 | 26 | # esptool.py path and port 27 | ESPTOOL ?= esptool.py 28 | ESPPORT ?= /dev/ttyUSB0 29 | 30 | # name for the target project 31 | TARGET = dweet 32 | 33 | # which modules (subdirectories) of the project to include in compiling 34 | MODULES = driver user 35 | EXTRA_INCDIR = include 36 | 37 | # libraries used in this project, mainly provided by the SDK 38 | LIBS = c gcc hal pp phy net80211 lwip wpa main 39 | 40 | # compiler flags using during compilation of source files 41 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 42 | 43 | # linker flags used to generate the main object file 44 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 45 | 46 | # linker script used for the above linkier step 47 | LD_SCRIPT = eagle.app.v6.ld 48 | 49 | # various paths from the SDK used in this project 50 | SDK_LIBDIR = lib 51 | SDK_LDDIR = ld 52 | SDK_INCDIR = include include/json 53 | 54 | # we create two different files for uploading into the flash 55 | # these are the names and options to generate them 56 | FW_FILE_1_ADDR = 0x00000 57 | FW_FILE_2_ADDR = 0x40000 58 | 59 | # select which tools to use as compiler, librarian and linker 60 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 61 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 62 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 63 | 64 | 65 | 66 | #### 67 | #### no user configurable options below here 68 | #### 69 | SRC_DIR := $(MODULES) 70 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 71 | 72 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 73 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 74 | 75 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 76 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 77 | LIBS := $(addprefix -l,$(LIBS)) 78 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 79 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 80 | 81 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 82 | 83 | INCDIR := $(addprefix -I,$(SRC_DIR)) 84 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 85 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 86 | 87 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 88 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 89 | 90 | V ?= $(VERBOSE) 91 | ifeq ("$(V)","1") 92 | Q := 93 | vecho := @true 94 | else 95 | Q := @ 96 | vecho := @echo 97 | endif 98 | 99 | vpath %.c $(SRC_DIR) 100 | 101 | define compile-objects 102 | $1/%.o: %.c 103 | $(vecho) "CC $$<" 104 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 105 | endef 106 | 107 | .PHONY: all checkdirs flash clean 108 | 109 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 110 | 111 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 112 | $(vecho) "FW $(FW_BASE)/" 113 | $(Q) $(ESPTOOL) elf2image -o $(FW_BASE)/ $(TARGET_OUT) 114 | 115 | $(TARGET_OUT): $(APP_AR) 116 | $(vecho) "LD $@" 117 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 118 | 119 | $(APP_AR): $(OBJ) 120 | $(vecho) "AR $@" 121 | $(Q) $(AR) cru $@ $^ 122 | 123 | checkdirs: $(BUILD_DIR) $(FW_BASE) 124 | 125 | $(BUILD_DIR): 126 | $(Q) mkdir -p $@ 127 | 128 | $(FW_BASE): 129 | $(Q) mkdir -p $@ 130 | 131 | flash: $(FW_FILE_1) $(FW_FILE_2) 132 | $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 133 | 134 | clean: 135 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 136 | 137 | serial: 138 | $(Q) screen $(ESPPORT) 115200 139 | 140 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | espenc 2 | ====== 3 | 4 | This is a (relatively) proper implementation of enc28j60 driver for LWIP on 5 | ESP8266. 6 | 7 | Both receive and transmit works properly now, but it hasn't been tested much 8 | yet. Code needs some major refactoring. 9 | 10 | Usage 11 | ----- 12 | 1. Copy or symlink `driver/espenc.c`, `driver/espenc.h`, `driver/spi.c`, 13 | `driver/spi_register.h` and `driver/spi.h` somewhere to your project. 14 | 2. Add `espenc_init()` in your `user_init()` 15 | 4. Connect ENC28J60 to ESP's SPI, connect INT pin to GPIO5 (or change it for 16 | anything you like in `driver/spi.h`. 17 | 3. PROFIT. 18 | 19 | TODO 20 | ---- 21 | * Move any framework specific code to separate headers 22 | * Port & test on esp8266-arduino 23 | * Port & test on Sming 24 | * Check latency (70ms?!) 25 | * Make it a little bit more stable 26 | * Support for hardware RESET 27 | * Does not work when wifi mode is set to `NULL_MODE` 28 | 29 | 30 | License 31 | ------- 32 | 33 | As enc28j60 handling code is mostly based on Ethercard, this shall be GPLv2. 34 | -------------------------------------------------------------------------------- /driver/espenc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "espenc.h" 3 | #include "driver/spi.h" 4 | #include "gpio.h" 5 | #include "mem.h" 6 | 7 | struct netif enc_netif; 8 | ip_addr_t ipaddr; 9 | 10 | static uint8_t Enc28j60Bank; 11 | static uint16_t NextPacketPtr; 12 | 13 | void chipEnable() { 14 | // Force CS pin low (FIXME) 15 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); 16 | GPIO_OUTPUT_SET(ESP_CS, 0); 17 | } 18 | 19 | void chipDisable() { 20 | // Return to default CS function 21 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); //GPIO15 is HSPI CS pin (Chip Select / Slave Select) 22 | } 23 | 24 | 25 | uint8_t readOp(uint8_t op, uint8_t addr) { 26 | if(addr & 0x80) 27 | return (uint8_t) spi_transaction(HSPI, 3, op >> 5, 5, addr, 0, 0, 16, 0) & 0xff; // Ignore dummy first byte 28 | else 29 | return (uint8_t) spi_transaction(HSPI, 3, op >> 5, 5, addr, 0, 0, 8, 0); 30 | } 31 | 32 | void writeOp(uint8_t op, uint8_t addr, uint8_t data) { 33 | spi_transaction(HSPI, 3, op >> 5, 5, addr, 8, data, 0, 0); 34 | } 35 | 36 | static void SetBank (uint8_t address) { 37 | if ((address & BANK_MASK) != Enc28j60Bank) { 38 | writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_BSEL1|ECON1_BSEL0); 39 | Enc28j60Bank = address & BANK_MASK; 40 | writeOp(ENC28J60_BIT_FIELD_SET, ECON1, Enc28j60Bank>>5); 41 | } 42 | } 43 | 44 | static uint8_t readRegByte (uint8_t address) { 45 | SetBank(address); 46 | return readOp(ENC28J60_READ_CTRL_REG, address); 47 | } 48 | 49 | static uint16_t readReg(uint8_t address) { 50 | return readRegByte(address) + (readRegByte(address+1) << 8); 51 | } 52 | 53 | static void writeRegByte (uint8_t address, uint8_t data) { 54 | SetBank(address); 55 | writeOp(ENC28J60_WRITE_CTRL_REG, address, data); 56 | } 57 | 58 | static void writeReg(uint8_t address, uint16_t data) { 59 | writeRegByte(address, data); 60 | writeRegByte(address + 1, data >> 8); 61 | } 62 | 63 | static uint16_t readPhyByte (uint8_t address) { 64 | writeRegByte(MIREGADR, address); 65 | writeRegByte(MICMD, MICMD_MIIRD); 66 | while (readRegByte(MISTAT) & MISTAT_BUSY) 67 | ; 68 | writeRegByte(MICMD, 0x00); 69 | return readRegByte(MIRD+1); 70 | } 71 | 72 | static void writePhy (uint8_t address, uint16_t data) { 73 | writeRegByte(MIREGADR, address); 74 | writeReg(MIWR, data); 75 | while (readRegByte(MISTAT) & MISTAT_BUSY) 76 | ; 77 | } 78 | 79 | static void readBuf(uint16_t len, uint8_t* data) { 80 | // force CS pin here, as it requires multiple bytes to be sent 81 | log("readBuf()"); 82 | chipEnable(); 83 | if (len != 0) { 84 | spi_transaction(HSPI, 8, ENC28J60_READ_BUF_MEM, 0, 0, 0, 0, 0, 0); 85 | while (len--) { 86 | uint8_t nextbyte; 87 | 88 | while(spi_busy(HSPI)); //wait for SPI transaction to complete 89 | nextbyte = spi_transaction(HSPI, 0, 0, 0, 0, 0, 0, 8, 0); 90 | *data++ = nextbyte; 91 | }; 92 | while(spi_busy(HSPI)); //wait for SPI transaction to complete 93 | } 94 | chipDisable(); 95 | } 96 | 97 | static void writeBuf(uint16_t len, const uint8_t* data) { 98 | // force CS pin here, as it requires multiple bytes to be sent 99 | chipEnable(); 100 | if (len != 0) { 101 | spi_transaction(HSPI, 8, ENC28J60_WRITE_BUF_MEM, 0, 0, 8, 0, 0, 0); 102 | while (len--) { 103 | uint8_t nextbyte = *data++; 104 | 105 | while(spi_busy(HSPI)); //wait for SPI transaction to complete 106 | spi_transaction(HSPI, 0, 0, 0, 0, 8, nextbyte, 0, 0); 107 | }; 108 | while(spi_busy(HSPI)); //wait for SPI transaction to complete 109 | } 110 | chipDisable(); 111 | } 112 | 113 | uint8_t enc28j60_int_disable() { 114 | uint8_t interrupts = 0; 115 | SetBank(EIE); 116 | interrupts = readRegByte(EIE); 117 | writeOp(ENC28J60_BIT_FIELD_CLR, EIE, interrupts); 118 | return interrupts; 119 | } 120 | 121 | void enc28j60_int_enable(uint8_t interrupts) { 122 | SetBank(EIE); 123 | writeOp(ENC28J60_BIT_FIELD_SET, EIE, interrupts); 124 | } 125 | 126 | err_t enc28j60_link_output(struct netif *netif, struct pbuf *p) { 127 | uint8_t retry = 0; 128 | uint16_t len = p->tot_len; 129 | 130 | uint8_t interrupts = enc28j60_int_disable(); 131 | 132 | log("output, tot_len: %d", p->tot_len); 133 | uint8_t isUp = (readPhyByte(PHSTAT2) >> 2) & 1; 134 | log("link is up: %d", isUp); 135 | log("pktcnt: %d", readRegByte(EPKTCNT)); 136 | 137 | SetBank(ECON1); 138 | writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); 139 | writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); 140 | SetBank(EIR); 141 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF|EIR_TXIF); 142 | 143 | if(retry == 0) { 144 | writeReg(EWRPT, TXSTART_INIT); 145 | writeReg(ETXND, TXSTART_INIT+len); 146 | //writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); 147 | uint8_t* buffer = (uint8_t*) os_malloc(len); 148 | pbuf_copy_partial(p, buffer, p->tot_len, 0); 149 | writeBuf(len, buffer); 150 | os_free(buffer); 151 | } 152 | 153 | SetBank(EIR); 154 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF|EIR_TXIF); 155 | log("before transmission: %02x", readRegByte(EIR)); 156 | SetBank(ECON1); 157 | writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); 158 | 159 | uint16_t count = 0; 160 | uint16_t eir = 0; 161 | while (((eir = readRegByte(EIR)) & (EIR_TXIF | EIR_TXERIF)) == 0 && ++count < 1000U) 162 | ; 163 | 164 | if (!(eir & EIR_TXERIF) && count < 1000U) { 165 | // no error; start new transmission 166 | log("transmission success"); 167 | } else { 168 | log("transmission failed (%d - %02x)", count, eir); 169 | } 170 | 171 | SetBank(ECON1); 172 | writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); 173 | 174 | enc28j60_int_enable(interrupts); 175 | } 176 | 177 | static uint32_t interrupt_reg = 0; 178 | 179 | void enc28j60_handle_packets(void) { 180 | log("reading ptr: %04x", NextPacketPtr); 181 | writeReg(ERDPT, NextPacketPtr); 182 | uint16_t packetLen = 0; 183 | uint16_t rxStatus = 0; 184 | 185 | readBuf(2, (uint8_t*) &NextPacketPtr); 186 | readBuf(2, (uint8_t*) &packetLen); 187 | readBuf(2, (uint8_t*) &rxStatus); 188 | 189 | // Ignore packet checksum TODO 190 | packetLen -= 4; 191 | 192 | log("next ptr: %04x", NextPacketPtr); 193 | log("packet len: %d (%x)", packetLen, packetLen); 194 | log("rx status: %02x", rxStatus); 195 | 196 | if(rxStatus & 0x80 == 0) { 197 | log("RECEIVE FAILED"); 198 | } else { 199 | uint16_t len = packetLen; 200 | struct pbuf* p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM); 201 | if(p != 0) { 202 | uint8_t* data; 203 | struct pbuf* q; 204 | 205 | for(q = p; q != 0; q= q->next) { 206 | data = q->payload; 207 | len = q->len; 208 | 209 | log("reading %d to %x", len, data); 210 | readBuf(len, data); 211 | } 212 | 213 | log("packet received, passing to netif->input"); 214 | enc_netif.input(p, &enc_netif); 215 | } else { 216 | log("pbuf_alloc failed!"); 217 | } 218 | } 219 | 220 | SetBank(ECON2); 221 | writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); 222 | 223 | writeReg(ERXRDPT, NextPacketPtr); 224 | } 225 | 226 | void interrupt_handler(void *arg) { 227 | ETS_GPIO_INTR_DISABLE(); 228 | GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, GPIO_REG_READ(GPIO_STATUS_ADDRESS)); 229 | 230 | uint8_t interrupt = readRegByte(EIR); 231 | uint8_t pktCnt = readRegByte(EPKTCNT); 232 | 233 | log(" *** INTERRUPT (%02X / %d) ***", interrupt, pktCnt); 234 | 235 | if(pktCnt > 0) { 236 | log("pktCnt > 0"); 237 | 238 | while(readRegByte(EPKTCNT) > 0) 239 | enc28j60_handle_packets(); 240 | 241 | //SetBank(EIE); 242 | //writeOp(ENC28J60_BIT_FIELD_CLR, EIE, EIE_PKTIE); 243 | } 244 | 245 | if(interrupt & EIR_PKTIF) { 246 | log("PKTIF interrupt"); 247 | SetBank(EIR); 248 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF); 249 | } 250 | 251 | if(interrupt & EIR_TXIF) { 252 | log("TXIF interrupt"); 253 | 254 | SetBank(EIR); 255 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXIF); 256 | } 257 | 258 | if(interrupt & EIR_TXERIF) { 259 | log("TXERIF int"); 260 | SetBank(EIR); 261 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF); 262 | } 263 | 264 | ETS_GPIO_INTR_ENABLE(); 265 | } 266 | 267 | // http://lwip.wikia.com/wiki/Writing_a_device_driver 268 | err_t enc28j60_init(struct netif *netif) { 269 | ETS_GPIO_INTR_ATTACH(interrupt_handler, &interrupt_reg); 270 | ETS_GPIO_INTR_ENABLE(); 271 | 272 | gpio_register_set(GPIO_PIN_ADDR(ESP_INT), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE) 273 | | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE) 274 | | GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE)); 275 | 276 | GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << ESP_INT); 277 | gpio_pin_intr_state_set(GPIO_ID_PIN(ESP_INT), GPIO_PIN_INTR_NEGEDGE); 278 | 279 | log("interrupts enabled"); 280 | 281 | log("initializing"); 282 | netif->linkoutput = enc28j60_link_output; 283 | netif->name[0] = 'e'; 284 | netif->name[1] = 'n'; 285 | netif->mtu = 1500; 286 | netif->hwaddr_len = 6; 287 | netif->hwaddr[0] = 0x00; 288 | netif->hwaddr[1] = 0x11; 289 | netif->hwaddr[2] = 0x22; 290 | netif->hwaddr[3] = 0x33; 291 | netif->hwaddr[4] = 0x44; 292 | netif->hwaddr[5] = 0x55; 293 | 294 | netif->output = etharp_output; 295 | netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; 296 | 297 | log("initializing hardware"); 298 | spi_init(HSPI); 299 | spi_mode(HSPI, 0, 0); 300 | writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); 301 | 302 | uint8_t estat; 303 | while(!(estat = readOp(ENC28J60_READ_CTRL_REG, ESTAT)) & ESTAT_CLKRDY) { 304 | log("estat: %02x", estat); 305 | os_delay_us(2000); // errata B7/2 306 | } 307 | NextPacketPtr = RXSTART_INIT; 308 | writeReg(ERXST, RXSTART_INIT); 309 | writeReg(ERXRDPT, RXSTART_INIT); 310 | writeReg(ERXND, RXSTOP_INIT); 311 | writeReg(ETXST, TXSTART_INIT); 312 | writeReg(ETXND, TXSTOP_INIT); 313 | 314 | writeRegByte(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); 315 | writeReg(EPMM0, 0x303f); 316 | writeReg(EPMCS, 0xf7f9); 317 | writeRegByte(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); 318 | writeRegByte(MACON2, 0x00); 319 | writeOp(ENC28J60_BIT_FIELD_SET, MACON3, 320 | MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); 321 | writeReg(MAIPG, 0x0C12); 322 | writeRegByte(MABBIPG, 0x12); 323 | writeReg(MAMXFL, MAX_FRAMELEN); 324 | writeRegByte(MAADR5, netif->hwaddr[0]); 325 | writeRegByte(MAADR4, netif->hwaddr[1]); 326 | writeRegByte(MAADR3, netif->hwaddr[2]); 327 | writeRegByte(MAADR2, netif->hwaddr[3]); 328 | writeRegByte(MAADR1, netif->hwaddr[4]); 329 | writeRegByte(MAADR0, netif->hwaddr[5]); 330 | writePhy(PHCON2, PHCON2_HDLDIS); 331 | SetBank(EIE); 332 | writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); 333 | 334 | SetBank(EIR); 335 | writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF); 336 | 337 | SetBank(ECON1); 338 | writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); 339 | 340 | uint8_t rev = readRegByte(EREVID); 341 | // microchip forgot to step the number on the silcon when they 342 | // released the revision B7. 6 is now rev B7. We still have 343 | // to see what they do when they release B8. At the moment 344 | // there is no B8 out yet 345 | if (rev > 5) ++rev; 346 | log("hardware ready, rev: %d", rev); 347 | 348 | return ERR_OK; 349 | } 350 | 351 | void espenc_init() { 352 | 353 | IP4_ADDR(&ipaddr, 0, 0, 0, 0); 354 | 355 | struct netif* new_netif = netif_add(&enc_netif, &ipaddr, &ipaddr, &ipaddr, NULL, enc28j60_init, 356 | ethernet_input); 357 | log("new_netif: %d", new_netif); 358 | 359 | if(new_netif == NULL) { 360 | // failed? 361 | return; 362 | } 363 | 364 | struct netif* n = netif_list; 365 | while(n) { 366 | log("network: %d %d; up: %d", n->name[0], n->name[1], netif_is_up(n)); 367 | n = n->next; 368 | } 369 | 370 | log("etharp: %d", (new_netif->flags & NETIF_FLAG_ETHARP)); 371 | log("dhcp_start(): %d", dhcp_start(new_netif)); 372 | } 373 | -------------------------------------------------------------------------------- /driver/espenc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | err_t enc28j60_link_output(struct netif *netif, struct pbuf *p); 6 | err_t enc28j60_init(struct netif *netif); 7 | void espenc_init(); 8 | 9 | #define log(s, ...) os_printf ("[%s:%s:%d] " s "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) 10 | 11 | #define ESP_CS 15 12 | #define ESP_INT 5 13 | 14 | 15 | // ENC28J60 Control Registers 16 | // Control register definitions are a combination of address, 17 | // bank number, and Ethernet/MAC/PHY indicator bits. 18 | // - Register address (bits 0-4) 19 | // - Bank number (bits 5-6) 20 | // - MAC/PHY indicator (bit 7) 21 | #define ADDR_MASK 0x1F 22 | #define BANK_MASK 0x60 23 | #define SPRD_MASK 0x80 24 | // All-bank registers 25 | #define EIE 0x1B 26 | #define EIR 0x1C 27 | #define ESTAT 0x1D 28 | #define ECON2 0x1E 29 | #define ECON1 0x1F 30 | // Bank 0 registers 31 | #define ERDPT (0x00|0x00) 32 | #define EWRPT (0x02|0x00) 33 | #define ETXST (0x04|0x00) 34 | #define ETXND (0x06|0x00) 35 | #define ERXST (0x08|0x00) 36 | #define ERXND (0x0A|0x00) 37 | #define ERXRDPT (0x0C|0x00) 38 | // #define ERXWRPT (0x0E|0x00) 39 | #define EDMAST (0x10|0x00) 40 | #define EDMAND (0x12|0x00) 41 | // #define EDMADST (0x14|0x00) 42 | #define EDMACS (0x16|0x00) 43 | // Bank 1 registers 44 | #define EHT0 (0x00|0x20) 45 | #define EHT1 (0x01|0x20) 46 | #define EHT2 (0x02|0x20) 47 | #define EHT3 (0x03|0x20) 48 | #define EHT4 (0x04|0x20) 49 | #define EHT5 (0x05|0x20) 50 | #define EHT6 (0x06|0x20) 51 | #define EHT7 (0x07|0x20) 52 | #define EPMM0 (0x08|0x20) 53 | #define EPMM1 (0x09|0x20) 54 | #define EPMM2 (0x0A|0x20) 55 | #define EPMM3 (0x0B|0x20) 56 | #define EPMM4 (0x0C|0x20) 57 | #define EPMM5 (0x0D|0x20) 58 | #define EPMM6 (0x0E|0x20) 59 | #define EPMM7 (0x0F|0x20) 60 | #define EPMCS (0x10|0x20) 61 | // #define EPMO (0x14|0x20) 62 | #define EWOLIE (0x16|0x20) 63 | #define EWOLIR (0x17|0x20) 64 | #define ERXFCON (0x18|0x20) 65 | #define EPKTCNT (0x19|0x20) 66 | // Bank 2 registers 67 | #define MACON1 (0x00|0x40|0x80) 68 | #define MACON2 (0x01|0x40|0x80) 69 | #define MACON3 (0x02|0x40|0x80) 70 | #define MACON4 (0x03|0x40|0x80) 71 | #define MABBIPG (0x04|0x40|0x80) 72 | #define MAIPG (0x06|0x40|0x80) 73 | #define MACLCON1 (0x08|0x40|0x80) 74 | #define MACLCON2 (0x09|0x40|0x80) 75 | #define MAMXFL (0x0A|0x40|0x80) 76 | #define MAPHSUP (0x0D|0x40|0x80) 77 | #define MICON (0x11|0x40|0x80) 78 | #define MICMD (0x12|0x40|0x80) 79 | #define MIREGADR (0x14|0x40|0x80) 80 | #define MIWR (0x16|0x40|0x80) 81 | #define MIRD (0x18|0x40|0x80) 82 | // Bank 3 registers 83 | #define MAADR1 (0x00|0x60|0x80) 84 | #define MAADR0 (0x01|0x60|0x80) 85 | #define MAADR3 (0x02|0x60|0x80) 86 | #define MAADR2 (0x03|0x60|0x80) 87 | #define MAADR5 (0x04|0x60|0x80) 88 | #define MAADR4 (0x05|0x60|0x80) 89 | #define EBSTSD (0x06|0x60) 90 | #define EBSTCON (0x07|0x60) 91 | #define EBSTCS (0x08|0x60) 92 | #define MISTAT (0x0A|0x60|0x80) 93 | #define EREVID (0x12|0x60) 94 | #define ECOCON (0x15|0x60) 95 | #define EFLOCON (0x17|0x60) 96 | #define EPAUS (0x18|0x60) 97 | 98 | // ENC28J60 ERXFCON Register Bit Definitions 99 | #define ERXFCON_UCEN 0x80 100 | #define ERXFCON_ANDOR 0x40 101 | #define ERXFCON_CRCEN 0x20 102 | #define ERXFCON_PMEN 0x10 103 | #define ERXFCON_MPEN 0x08 104 | #define ERXFCON_HTEN 0x04 105 | #define ERXFCON_MCEN 0x02 106 | #define ERXFCON_BCEN 0x01 107 | // ENC28J60 EIE Register Bit Definitions 108 | #define EIE_INTIE 0x80 109 | #define EIE_PKTIE 0x40 110 | #define EIE_DMAIE 0x20 111 | #define EIE_LINKIE 0x10 112 | #define EIE_TXIE 0x08 113 | #define EIE_WOLIE 0x04 114 | #define EIE_TXERIE 0x02 115 | #define EIE_RXERIE 0x01 116 | // ENC28J60 EIR Register Bit Definitions 117 | #define EIR_PKTIF 0x40 118 | #define EIR_DMAIF 0x20 119 | #define EIR_LINKIF 0x10 120 | #define EIR_TXIF 0x08 121 | #define EIR_WOLIF 0x04 122 | #define EIR_TXERIF 0x02 123 | #define EIR_RXERIF 0x01 124 | // ENC28J60 ESTAT Register Bit Definitions 125 | #define ESTAT_INT 0x80 126 | #define ESTAT_LATECOL 0x10 127 | #define ESTAT_RXBUSY 0x04 128 | #define ESTAT_TXABRT 0x02 129 | #define ESTAT_CLKRDY 0x01 130 | // ENC28J60 ECON2 Register Bit Definitions 131 | #define ECON2_AUTOINC 0x80 132 | #define ECON2_PKTDEC 0x40 133 | #define ECON2_PWRSV 0x20 134 | #define ECON2_VRPS 0x08 135 | // ENC28J60 ECON1 Register Bit Definitions 136 | #define ECON1_TXRST 0x80 137 | #define ECON1_RXRST 0x40 138 | #define ECON1_DMAST 0x20 139 | #define ECON1_CSUMEN 0x10 140 | #define ECON1_TXRTS 0x08 141 | #define ECON1_RXEN 0x04 142 | #define ECON1_BSEL1 0x02 143 | #define ECON1_BSEL0 0x01 144 | // ENC28J60 MACON1 Register Bit Definitions 145 | #define MACON1_LOOPBK 0x10 146 | #define MACON1_TXPAUS 0x08 147 | #define MACON1_RXPAUS 0x04 148 | #define MACON1_PASSALL 0x02 149 | #define MACON1_MARXEN 0x01 150 | // ENC28J60 MACON2 Register Bit Definitions 151 | #define MACON2_MARST 0x80 152 | #define MACON2_RNDRST 0x40 153 | #define MACON2_MARXRST 0x08 154 | #define MACON2_RFUNRST 0x04 155 | #define MACON2_MATXRST 0x02 156 | #define MACON2_TFUNRST 0x01 157 | // ENC28J60 MACON3 Register Bit Definitions 158 | #define MACON3_PADCFG2 0x80 159 | #define MACON3_PADCFG1 0x40 160 | #define MACON3_PADCFG0 0x20 161 | #define MACON3_TXCRCEN 0x10 162 | #define MACON3_PHDRLEN 0x08 163 | #define MACON3_HFRMLEN 0x04 164 | #define MACON3_FRMLNEN 0x02 165 | #define MACON3_FULDPX 0x01 166 | // ENC28J60 MICMD Register Bit Definitions 167 | #define MICMD_MIISCAN 0x02 168 | #define MICMD_MIIRD 0x01 169 | // ENC28J60 MISTAT Register Bit Definitions 170 | #define MISTAT_NVALID 0x04 171 | #define MISTAT_SCAN 0x02 172 | #define MISTAT_BUSY 0x01 173 | 174 | // ENC28J60 EBSTCON Register Bit Definitions 175 | #define EBSTCON_PSV2 0x80 176 | #define EBSTCON_PSV1 0x40 177 | #define EBSTCON_PSV0 0x20 178 | #define EBSTCON_PSEL 0x10 179 | #define EBSTCON_TMSEL1 0x08 180 | #define EBSTCON_TMSEL0 0x04 181 | #define EBSTCON_TME 0x02 182 | #define EBSTCON_BISTST 0x01 183 | 184 | // PHY registers 185 | #define PHCON1 0x00 186 | #define PHSTAT1 0x01 187 | #define PHHID1 0x02 188 | #define PHHID2 0x03 189 | #define PHCON2 0x10 190 | #define PHSTAT2 0x11 191 | #define PHIE 0x12 192 | #define PHIR 0x13 193 | #define PHLCON 0x14 194 | 195 | // ENC28J60 PHY PHCON1 Register Bit Definitions 196 | #define PHCON1_PRST 0x8000 197 | #define PHCON1_PLOOPBK 0x4000 198 | #define PHCON1_PPWRSV 0x0800 199 | #define PHCON1_PDPXMD 0x0100 200 | // ENC28J60 PHY PHSTAT1 Register Bit Definitions 201 | #define PHSTAT1_PFDPX 0x1000 202 | #define PHSTAT1_PHDPX 0x0800 203 | #define PHSTAT1_LLSTAT 0x0004 204 | #define PHSTAT1_JBSTAT 0x0002 205 | // ENC28J60 PHY PHCON2 Register Bit Definitions 206 | #define PHCON2_FRCLINK 0x4000 207 | #define PHCON2_TXDIS 0x2000 208 | #define PHCON2_JABBER 0x0400 209 | #define PHCON2_HDLDIS 0x0100 210 | 211 | // ENC28J60 Packet Control Byte Bit Definitions 212 | #define PKTCTRL_PHUGEEN 0x08 213 | #define PKTCTRL_PPADEN 0x04 214 | #define PKTCTRL_PCRCEN 0x02 215 | #define PKTCTRL_POVERRIDE 0x01 216 | 217 | // SPI operation codes 218 | #define ENC28J60_READ_CTRL_REG 0x00 219 | #define ENC28J60_READ_BUF_MEM 0x3A 220 | #define ENC28J60_WRITE_CTRL_REG 0x40 221 | #define ENC28J60_WRITE_BUF_MEM 0x7A 222 | #define ENC28J60_BIT_FIELD_SET 0x80 223 | #define ENC28J60_BIT_FIELD_CLR 0xA0 224 | #define ENC28J60_SOFT_RESET 0xFF 225 | 226 | 227 | // max frame length which the controller will accept: 228 | // (note: maximum ethernet frame length would be 1518) 229 | #define MAX_FRAMELEN 1500 230 | 231 | #define FULL_SPEED 1 // switch to full-speed SPI for bulk transfers 232 | 233 | 234 | // buffer boundaries applied to internal 8K ram 235 | // the entire available packet buffer space is allocated 236 | 237 | #define RXSTART_INIT 0x0000 // start of RX buffer, (must be zero, Rev. B4 Errata point 5) 238 | #define RXSTOP_INIT 0x0BFF // end of RX buffer, room for 2 packets 239 | 240 | #define TXSTART_INIT 0x0C00 // start of TX buffer, room for 1 packet 241 | #define TXSTOP_INIT 0x11FF // end of TX buffer 242 | 243 | #define SCRATCH_START 0x1200 // start of scratch area 244 | #define SCRATCH_LIMIT 0x2000 // past end of area, i.e. 3 Kb 245 | #define SCRATCH_PAGE_SHIFT 6 // addressing is in pages of 64 bytes 246 | #define SCRATCH_PAGE_SIZE (1 << SCRATCH_PAGE_SHIFT) 247 | #define SCRATCH_PAGE_NUM ((SCRATCH_LIMIT-SCRATCH_START) >> SCRATCH_PAGE_SHIFT) 248 | #define SCRATCH_MAP_SIZE (((SCRATCH_PAGE_NUM % 8) == 0) ? (SCRATCH_PAGE_NUM / 8) : (SCRATCH_PAGE_NUM/8+1)) 249 | 250 | // area in the enc memory that can be used via enc_malloc; by default 0 bytes; decrease SCRATCH_LIMIT in order 251 | // to use this functionality 252 | #define ENC_HEAP_START SCRATCH_LIMIT 253 | #define ENC_HEAP_END 0x2000 254 | -------------------------------------------------------------------------------- /driver/spi.c: -------------------------------------------------------------------------------- 1 | ../ESP8266_SPI_Driver/driver/spi.c -------------------------------------------------------------------------------- /driver/spi.h: -------------------------------------------------------------------------------- 1 | ../ESP8266_SPI_Driver/include/driver/spi.h -------------------------------------------------------------------------------- /driver/spi_register.h: -------------------------------------------------------------------------------- 1 | ../ESP8266_SPI_Driver/include/driver/spi_register.h -------------------------------------------------------------------------------- /include/driver: -------------------------------------------------------------------------------- 1 | ../ESP8266_SPI_Driver/include/driver/ -------------------------------------------------------------------------------- /include/lwip/ip_addr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * esp-enc28j60 NOTE 3 | * ================ 4 | * This file is patched lwip/ip_addr.h with some of structs and macros defined 5 | * in user_interface.h removed. This might only be an issue on esp-open-lwip, 6 | * but it's still included in the esp-open-sdk, which is quite common. 7 | * 8 | * 9 | * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 10 | * All rights reserved. 11 | * 12 | * Redistribution and use in source and binary forms, with or without modification, 13 | * are permitted provided that the following conditions are met: 14 | * 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. The name of the author may not be used to endorse or promote products 21 | * derived from this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 24 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 28 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 | * OF SUCH DAMAGE. 33 | * 34 | * This file is part of the lwIP TCP/IP stack. 35 | * 36 | * Author: Adam Dunkels 37 | * 38 | */ 39 | #ifndef __LWIP_IP_ADDR_H__ 40 | #define __LWIP_IP_ADDR_H__ 41 | 42 | #include "lwip/opt.h" 43 | #include "lwip/def.h" 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | #include "user_interface.h" 50 | /* This is the aligned version of ip_addr_t, 51 | used as local variable, on the stack, etc. */ 52 | //struct ip_addr { 53 | // u32_t addr; 54 | //}; 55 | 56 | /* This is the packed version of ip_addr_t, 57 | used in network headers that are itself packed */ 58 | #ifdef PACK_STRUCT_USE_INCLUDES 59 | # include "arch/bpstruct.h" 60 | #endif 61 | PACK_STRUCT_BEGIN 62 | struct ip_addr_packed { 63 | PACK_STRUCT_FIELD(u32_t addr); 64 | } PACK_STRUCT_STRUCT; 65 | PACK_STRUCT_END 66 | #ifdef PACK_STRUCT_USE_INCLUDES 67 | # include "arch/epstruct.h" 68 | #endif 69 | 70 | /** ip_addr_t uses a struct for convenience only, so that the same defines can 71 | * operate both on ip_addr_t as well as on ip_addr_p_t. */ 72 | typedef struct ip_addr ip_addr_t; 73 | typedef struct ip_addr_packed ip_addr_p_t; 74 | 75 | /* 76 | * struct ipaddr2 is used in the definition of the ARP packet format in 77 | * order to support compilers that don't have structure packing. 78 | */ 79 | #ifdef PACK_STRUCT_USE_INCLUDES 80 | # include "arch/bpstruct.h" 81 | #endif 82 | PACK_STRUCT_BEGIN 83 | struct ip_addr2 { 84 | PACK_STRUCT_FIELD(u16_t addrw[2]); 85 | } PACK_STRUCT_STRUCT; 86 | PACK_STRUCT_END 87 | #ifdef PACK_STRUCT_USE_INCLUDES 88 | # include "arch/epstruct.h" 89 | #endif 90 | 91 | /* Forward declaration to not include netif.h */ 92 | struct netif; 93 | 94 | extern const ip_addr_t ip_addr_any; 95 | extern const ip_addr_t ip_addr_broadcast; 96 | 97 | /** IP_ADDR_ can be used as a fixed IP address 98 | * for the wildcard and the broadcast address 99 | */ 100 | #define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) 101 | #define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) 102 | 103 | /* Definitions of the bits in an Internet address integer. 104 | 105 | On subnets, host and network parts are found according to 106 | the subnet mask, not these masks. */ 107 | #define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) 108 | #define IP_CLASSA_NET 0xff000000 109 | #define IP_CLASSA_NSHIFT 24 110 | #define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) 111 | #define IP_CLASSA_MAX 128 112 | 113 | #define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) 114 | #define IP_CLASSB_NET 0xffff0000 115 | #define IP_CLASSB_NSHIFT 16 116 | #define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) 117 | #define IP_CLASSB_MAX 65536 118 | 119 | #define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) 120 | #define IP_CLASSC_NET 0xffffff00 121 | #define IP_CLASSC_NSHIFT 8 122 | #define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) 123 | 124 | #define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) 125 | #define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ 126 | #define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ 127 | #define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ 128 | #define IP_MULTICAST(a) IP_CLASSD(a) 129 | 130 | #define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) 131 | #define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) 132 | 133 | #define IP_LOOPBACKNET 127 /* official! */ 134 | 135 | 136 | 137 | /** MEMCPY-like copying of IP addresses where addresses are known to be 138 | * 16-bit-aligned if the port is correctly configured (so a port could define 139 | * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ 140 | #ifndef IPADDR2_COPY 141 | #define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) 142 | #endif 143 | 144 | /** Copy IP address - faster than ip_addr_set: no NULL check */ 145 | #define ip_addr_copy(dest, src) ((dest).addr = (src).addr) 146 | /** Safely copy one IP address to another (src may be NULL) */ 147 | #define ip_addr_set(dest, src) ((dest)->addr = \ 148 | ((src) == NULL ? 0 : \ 149 | (src)->addr)) 150 | /** Set complete address to zero */ 151 | #define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) 152 | /** Set address to IPADDR_ANY (no need for htonl()) */ 153 | #define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) 154 | /** Set address to loopback address */ 155 | #define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) 156 | /** Safely copy one IP address to another and change byte order 157 | * from host- to network-order. */ 158 | #define ip_addr_set_hton(dest, src) ((dest)->addr = \ 159 | ((src) == NULL ? 0:\ 160 | htonl((src)->addr))) 161 | /** IPv4 only: set the IP address given as an u32_t */ 162 | #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) 163 | /** IPv4 only: get the IP address as an u32_t */ 164 | #define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) 165 | 166 | /** Get the network address by combining host address with netmask */ 167 | #define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) 168 | 169 | /** 170 | * Determine if two address are on the same network. 171 | * 172 | * @arg addr1 IP address 1 173 | * @arg addr2 IP address 2 174 | * @arg mask network identifier mask 175 | * @return !0 if the network identifiers of both address match 176 | */ 177 | #define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ 178 | (mask)->addr) == \ 179 | ((addr2)->addr & \ 180 | (mask)->addr)) 181 | #define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) 182 | 183 | #define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) 184 | 185 | #define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) 186 | u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)ICACHE_FLASH_ATTR; 187 | 188 | #define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) 189 | u8_t ip4_addr_netmask_valid(u32_t netmask)ICACHE_FLASH_ATTR; 190 | 191 | #define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) 192 | 193 | #define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) 194 | 195 | #define ip_addr_debug_print(debug, ipaddr) \ 196 | LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ 197 | ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ 198 | ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ 199 | ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ 200 | ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) 201 | 202 | /** For backwards compatibility */ 203 | #define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) 204 | 205 | //u32_t ipaddr_addr(const char *cp)ICACHE_FLASH_ATTR; 206 | int ipaddr_aton(const char *cp, ip_addr_t *addr)ICACHE_FLASH_ATTR; 207 | /** returns ptr to static buffer; not reentrant! */ 208 | char *ipaddr_ntoa(const ip_addr_t *addr)ICACHE_FLASH_ATTR; 209 | char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)ICACHE_FLASH_ATTR; 210 | 211 | #define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ 212 | ip4_addr2_16(ipaddr), \ 213 | ip4_addr3_16(ipaddr), \ 214 | ip4_addr4_16(ipaddr) 215 | 216 | #define IPSTR "%d.%d.%d.%d" 217 | 218 | //struct ip_info { 219 | // struct ip_addr ip; 220 | // struct ip_addr netmask; 221 | // struct ip_addr gw; 222 | //}; 223 | #ifdef __cplusplus 224 | } 225 | #endif 226 | 227 | #endif /* __LWIP_IP_ADDR_H__ */ 228 | -------------------------------------------------------------------------------- /user/user_config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Informatic/espenc/0e24611da7c5c3ae11cd8117789154e0ff8bbe23/user/user_config.h -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "ets_sys.h" 2 | #include "osapi.h" 3 | #include "gpio.h" 4 | #include "os_type.h" 5 | #include "ip_addr.h" 6 | #include "espconn.h" 7 | #include "user_interface.h" 8 | #include "user_config.h" 9 | #include "espenc.h" 10 | 11 | 12 | void user_rf_pre_init( void ) { } 13 | 14 | void user_init( void ) 15 | { 16 | static struct station_config config; 17 | 18 | uart_div_modify( 0, UART_CLK_FREQ / ( 115200 ) ); 19 | log("hey?"); 20 | 21 | espenc_init(); 22 | 23 | //wifi_station_set_hostname( "dweet" ); 24 | wifi_set_opmode_current( STATION_MODE ); 25 | } 26 | 27 | --------------------------------------------------------------------------------