HTTPESP8266ConnectionData* ICACHE_FLASH_ATTR esp8266_createConnection(NetConnection* conn) { if(conn->driverData) esp8266_destroyConnection(conn); HTTPESP8266ConnectionData* driver = os_zalloc(sizeof(HTTPESP8266ConnectionData)); ets_memset(driver, 0, sizeof(HTTPESP8266ConnectionData)); conn->driverData = driver; driver->connection.reverse = conn; driver->connection.type = ESPCONN_TCP; driver->connection.proto.tcp = (esp_tcp*)os_zalloc(sizeof(esp_tcp)); ets_memset(driver->connection.proto.tcp, 0, sizeof(esp_tcp)); driver->connection.proto.tcp->local_port = espconn_port(); return driver; }
//print exception log to Flash void ICACHE_FLASH_ATTR stack_dump(struct rst_info *info, uint32 sp) { uint32 i; uint8 log_buf[200]; const char* pad = " "; int len; if(info->reason == REASON_WDT_RST || info->reason == REASON_SOFT_WDT_RST || info->reason == REASON_EXCEPTION_RST) { ets_memset(log_buf,0,sizeof(log_buf)); ets_sprintf(log_buf,"stack sp is %08x\n",sp); len = os_strlen(log_buf); if(len%4!=0) ets_memcpy(log_buf+len,pad, 4 - (len%4)); ESP_DBG("Stack sp is %08x\n",sp); debug_DumpToFlash(log_buf,os_strlen(log_buf)); ets_memset(log_buf,0,sizeof(log_buf)); ets_sprintf(log_buf,"*** stack dump start ***\n"); len = os_strlen(log_buf); if(len%4!=0) os_memcpy(log_buf+len,pad, 4 - (len%4)); debug_DumpToFlash(log_buf,os_strlen(log_buf)); ESP_DBG("*** Stack dump start ***\n"); ets_memset(log_buf,0,sizeof(log_buf)); ets_sprintf(log_buf,"PC = 0x%08x\n",info->epc1); len = os_strlen(log_buf); if(len%4!=0) os_memcpy(log_buf+len,pad, 4 - (len%4)); debug_DumpToFlash(log_buf,os_strlen(log_buf)); ESP_DBG("DBG PC = 0x%08x\n",info->epc1); for (i = sp; i < 0x40000000; i+=16) { uint32 *val = (uint32 *)i; ets_memset(log_buf,0,sizeof(log_buf)); ets_sprintf(log_buf,"%08x: %08x %08x %08x %08x\n", i, *val, *(val + 1), *(val + 2), *(val + 3)); len = os_strlen(log_buf); if(len%4!=0) os_memcpy(log_buf+len,pad, 4 - (len%4)); debug_DumpToFlash(log_buf,os_strlen(log_buf)); ESP_DBG("%08x: %08x %08x %08x %08x\n", i, *val, *(val + 1), *(val + 2), *(val + 3)); } ets_memset(log_buf,0,sizeof(log_buf)); ets_sprintf(log_buf,"*** stack dump end ***\n"); len = os_strlen(log_buf); if(len%4!=0) os_memcpy(log_buf+len,pad, 4 - (len%4)); debug_DumpToFlash(log_buf,os_strlen(log_buf)); ESP_DBG("*** Stack dump end ***\n"); }
TcpServer::TcpServer(uint16_t port) : Tcp() { LOGF("this : %X ", this); _local_port = port; _conn->proto.tcp->local_port = _local_port; setType(SERVER); _conn = new (struct espconn); ets_memset(_conn, 0, sizeof(_conn)); _conn->type = ESPCONN_TCP; _conn->state = ESPCONN_NONE; _conn->proto.tcp = (esp_tcp *) malloc(sizeof(esp_tcp)); ets_memset(_conn->proto.tcp, 0, sizeof(esp_tcp)); _local_port = 23; _conn->reverse = (Tcp*) this; _connected = true; // to allocate TCP instance }
TcpClient::TcpClient(const char* host, uint16_t port) : Tcp() { LOGF("ctor : %X ", this); strncpy(_host, host, sizeof(_host)); _remote_port = port; setType(CLIENT); _conn = new (struct espconn); _remote_ip.addr = 0; // should be zero for dns callback to work _connected = false; ets_memset(_conn, 0, sizeof(_conn)); _conn->type = ESPCONN_TCP; _conn->state = ESPCONN_NONE; _conn->proto.tcp = (esp_tcp *) malloc(sizeof(esp_tcp)); ets_memset(_conn->proto.tcp, 0, sizeof(esp_tcp)); _connected = true; // don't reallocate master client }
void ICACHE_FLASH_ATTR SetupMDNS() { MDNSNames[0] = strdupcaselower( &SETTINGS.DeviceName[0] ); pMDNSServer = (struct espconn *)os_zalloc(sizeof(struct espconn)); ets_memset( pMDNSServer, 0, sizeof( struct espconn ) ); pMDNSServer->type = ESPCONN_UDP; pMDNSServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); pMDNSServer->proto.udp->local_port = 5353; espconn_regist_recvcb(pMDNSServer, got_mdns_packet); espconn_create( pMDNSServer ); }
void *pvPortCalloc(size_t count, size_t size) { void *p; /* allocate 'count' objects of size 'size' */ p = pvPortMalloc(count * size); if (p) { /* zero the memory */ ets_memset(p, 0, count * size); } return p; }
void user_init(void) { uart_init(BIT_RATE_115200, BIT_RATE_115200); uart0_sendStr("\r\nesp8266 ws2812 driver\r\n"); // int opm = wifi_get_opmode(); // if( opm == 1 ) need_to_switch_opmode = 120; // wifi_set_opmode_current(2); //Uncomment this to force a system restore. // system_restore(); CSSettingsLoad( 0 ); CSPreInit(); pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn)); ets_memset( pUdpServer, 0, sizeof( struct espconn ) ); espconn_create( pUdpServer ); pUdpServer->type = ESPCONN_UDP; pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); pUdpServer->proto.udp->local_port = 7777; espconn_regist_recvcb(pUdpServer, udpserver_recv); if( espconn_create( pUdpServer ) ) { while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); } } CSInit(); SetServiceName( "ws2812" ); AddMDNSName( "cn8266" ); AddMDNSName( "ws2812" ); AddMDNSService( "_http._tcp", "An ESP8266 Webserver", 80 ); AddMDNSService( "_ws2812._udp", "WS2812 Driver", 7777 ); AddMDNSService( "_cn8266._udp", "ESP8266 Backend", 7878 ); //Add a process system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); //Timer example os_timer_disarm(&some_timer); os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL); os_timer_arm(&some_timer, 100, 1); ws2812_init(); uint8_t ledout[] = { 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00 }; ws2812_push( ledout, sizeof( ledout ) ); system_os_post(procTaskPrio, 0, 0 ); }
//_____________________________________________________________ // TcpServer::TcpServer(ActorRef wifi, uint16_t port) : Tcp() { _wifi = wifi; _wifi.listener(self()); _state = TCP_SERVER_DISCONNECTED; LOGF("this : %X ", this); _local_port = port; setType(SERVER); _conn = new (struct espconn); ets_memset(_conn, 0, sizeof(_conn)); _conn->type = ESPCONN_TCP; _conn->state = ESPCONN_NONE; _conn->proto.tcp = (esp_tcp *) malloc(sizeof(esp_tcp)); ets_memset(_conn->proto.tcp, 0, sizeof(esp_tcp)); _conn->proto.tcp->local_port = _local_port; _conn->reverse = (Tcp*) this; _connected = true; // to allocate TCP instance }
void ICACHE_FLASH_ATTR ssServerInit() { struct espconn * pSimpleServer; pSimpleServer = (struct espconn *)os_zalloc(sizeof(struct espconn)); ets_memset( pSimpleServer, 0, sizeof( struct espconn ) ); espconn_create( pSimpleServer ); pSimpleServer->type = ESPCONN_TCP; pSimpleServer->state = ESPCONN_NONE; pSimpleServer->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); pSimpleServer->proto.tcp->local_port = 80; //espconn_set_opt(pSimpleServer, ESPCONN_REUSEADDR); espconn_regist_connectcb(pSimpleServer, ssConnCb); espconn_accept(pSimpleServer); espconn_regist_time(pSimpleServer, 0, 0); }
void ICACHE_FLASH_ATTR tfp_open_connection(void) { // Common initialisations. ringbuffer_init(&tfp_rb, tfp_rb_buffer, TFP_RING_BUFFER_SIZE); brickd_init(); com_init(); for(uint8_t i = 0; i < TFP_MAX_CONNECTIONS; i++) { tfp_init_con(i); } /* * When mesh mode is enabled all the socket setup is done from mesh specific * callbacks. Existing TFP socket callbacks and implementation are used but as * a layer underneath the mesh layer. */ if(!configuration_current.mesh_enable) { ets_memset(&tfp_con_listen, 0, sizeof(struct espconn)); // Initialize the ESPConn espconn_create(&tfp_con_listen); tfp_con_listen.type = ESPCONN_TCP; tfp_con_listen.state = ESPCONN_NONE; // Make it a TCP connection tfp_con_listen.proto.tcp = &tfp_con_listen_tcp; tfp_con_listen.proto.tcp->local_port = configuration_current.general_port; espconn_regist_reconcb(&tfp_con_listen, tfp_reconnect_callback); espconn_regist_connectcb(&tfp_con_listen, tfp_connect_callback); // Start listening espconn_accept(&tfp_con_listen); // Set server timeout (in seconds) espconn_regist_time(&tfp_con_listen, 7200, 0); } else { logi("MSH:TFP init\n"); } }
//____________________________________________________________ // Tcp::connect //____________________________________________________________ void TcpClient::connect() { //LOGF(" Connecting "); // ets_memset(_conn, 0, sizeof(_conn)); _conn->type = ESPCONN_TCP; _conn->state = ESPCONN_NONE; // _conn->proto.tcp = (esp_tcp *) malloc(sizeof(esp_tcp)); ets_memset(_conn->proto.tcp, 0, sizeof(esp_tcp)); _conn->proto.tcp->local_port = espconn_port(); _conn->proto.tcp->remote_port = _remote_port; _conn->reverse = this; //registerCb(_conn); espconn_regist_connectcb(_conn, connectCb); if (StrToIP(_host, _conn->proto.tcp->remote_ip)) { LOGF("TCP: Connect to ip %s:%d", _host, _remote_port); espconn_connect(_conn); } else { LOGF("TCP: Connect to domain %s:%d", _host, _remote_port); espconn_gethostbyname(_conn, _host, &_remote_ip.ipAddr, Tcp::dnsFoundCb); } }
void ICACHE_FLASH_ATTR ClearMDNSNames() { int i; for( i = 0; i < MAX_MDNS_NAMES; i++ ) { if( MDNSNames[i] ) { os_zfree( MDNSNames[i] ); MDNSNames[i] = 0; } } for( i = 0; i < MAX_MDNS_SERVICES; i++ ) { if( MDNSServices[i] ) { os_zfree( MDNSServices[i] ); MDNSServices[i] = 0; os_zfree( MDNSServiceTexts[i] ); MDNSServiceTexts[i] = 0; MDNSServicePorts[i] = 0; } } nr_services = 0; ets_memset( MyLocalName, 0, sizeof( MyLocalName ) ); MDNSNames[0] = strdupcaselower( &SETTINGS.DeviceName[0] ); }
void* memset(void *s, int c, size_t n) { return ets_memset(s, c, n); }
irom void config_read(config_t *cfg) { int io, pin; io_config_pin_entry_t *pin_config; spi_flash_read(USER_CONFIG_SECTOR * SPI_FLASH_SEC_SIZE, (void *)cfg, sizeof(*cfg)); if((cfg->magic != config_magic) || (cfg->version != config_version)) // init config to default { ets_memset(cfg, 0, sizeof(*cfg)); cfg->magic = config_magic; cfg->version = config_version; strlcpy(cfg->client_wlan.ssid, DEFAULT_SSID, sizeof(cfg->client_wlan.ssid)); strlcpy(cfg->client_wlan.passwd, DEFAULT_PASSWD, sizeof(cfg->client_wlan.passwd)); strlcpy(cfg->ap_wlan.ssid, DEFAULT_SSID, sizeof(cfg->ap_wlan.ssid)); strlcpy(cfg->ap_wlan.passwd, DEFAULT_PASSWD, sizeof(cfg->ap_wlan.passwd)); cfg->ap_wlan.channel = 1; cfg->wlan_mode = config_wlan_mode_client; cfg->flags = 0; cfg->uart.baud_rate = 115200; cfg->uart.data_bits = 8; cfg->uart.parity = parity_none; cfg->uart.stop_bits = 1; config_set_flag(config_flag_print_debug, true); cfg->bridge.port = 23; cfg->bridge.timeout = 0; cfg->command.port = 24; cfg->command.timeout = 0; cfg->status_trigger.io = -1; cfg->status_trigger.pin = -1; cfg->assoc_trigger.io = -1; cfg->assoc_trigger.pin = -1; cfg->ntp.server = ip_addr("0.0.0.0"); cfg->ntp.timezone = 0; cfg->display.flip_timeout = 4; strlcpy(cfg->display.default_msg, "%%%%", sizeof(cfg->display.default_msg)); i2c_sensor_config_init(&cfg->i2c_sensors); for(io = 0; io < io_id_size; io++) { for(pin = 0; pin < max_pins_per_io; pin++) { pin_config = &config.io_config[io][pin]; pin_config->mode = io_pin_disabled; pin_config->llmode = io_pin_ll_disabled; pin_config->flags.autostart = 0; pin_config->flags.repeat = 0; pin_config->flags.pullup = 0; pin_config->flags.reset_on_read = 0; // activate UART by default if((io == io_id_gpio) && ((pin == 1) || (pin == 3))) // shamefully hardcoded :-( { pin_config->mode = io_pin_uart; pin_config->llmode = io_pin_ll_uart; if(pin == 3) pin_config->flags.pullup = 1; } } } } cfg->client_wlan.ssid[sizeof(cfg->client_wlan.ssid) - 1] = '\0'; cfg->client_wlan.passwd[sizeof(cfg->client_wlan.passwd) - 1] = '\0'; cfg->ap_wlan.ssid[sizeof(cfg->ap_wlan.ssid) - 1] = '\0'; cfg->ap_wlan.passwd[sizeof(cfg->ap_wlan.passwd) - 1] = '\0'; cfg->display.default_msg[sizeof(cfg->display.default_msg) - 1] = '\0'; // failsafe for corrupt / blank config if((ets_strlen(cfg->client_wlan.ssid) < 2) || (ets_strlen(cfg->client_wlan.passwd) < 8)) { strlcpy(cfg->client_wlan.ssid, DEFAULT_SSID, sizeof(cfg->client_wlan.ssid)); strlcpy(cfg->client_wlan.passwd, DEFAULT_PASSWD, sizeof(cfg->client_wlan.passwd)); } if((ets_strlen(cfg->ap_wlan.ssid) < 2) || (ets_strlen(cfg->ap_wlan.passwd) < 8) || (cfg->ap_wlan.channel < 1) || (cfg->ap_wlan.channel > 13)) { strlcpy(cfg->ap_wlan.ssid, DEFAULT_SSID, sizeof(cfg->ap_wlan.ssid)); strlcpy(cfg->ap_wlan.passwd, DEFAULT_PASSWD, sizeof(cfg->ap_wlan.passwd)); cfg->ap_wlan.channel = 13; } }
// initialize the custom stuff that goes beyond esp-link void user_init() { // Initialize the GPIO subsystem. gpio_init(); /* ====================================== */ /* UART */ /* ====================================== */ // Initialize UART0 and UART1 /* NOTE: UART1 and I2S share same GPIO. Cannot use simultaneously. */ uart_init( BIT_RATE_115200, BIT_RATE_115200 ); // uart0_sendStr( "\nUART0 - USED TO PROGRAM THE MODULE\n" ); os_printf("\n===================\nUART1 - DEBUG OUPUT\n===================\n"); /* NOTE: PWM CANNOT BE USED SIMULTANEOUSLY WITH HW TIMER */ #if 0 /* ====================================== */ /* PWM */ /* ====================================== */ uint32 pwm_period = 1000; uint32 pwm_duty[PWM_CHANNEL] = {0}; uint32 io_info[][3] = { {PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM}, {PWM_1_OUT_IO_MUX,PWM_1_OUT_IO_FUNC,PWM_1_OUT_IO_NUM}, }; /* PIN FUNCTION INIT FOR PWM OUTPUT */ pwm_init(pwm_period, pwm_duty, PWM_CHANNEL, io_info); /* set pwm_duty cycle */ pwm_set_duty (14185, 0); pwm_set_duty (22222, 1); // todo: explain why 22222 is the highest possible value /* start PWM */ pwm_start(); // NOTE: PWM causes spikes in other GPIOs #endif /* ====================================== */ /* GPIO INTERRPUT */ /* ====================================== */ /* Set GPIO12 in GPIO mode */ PIN_FUNC_SELECT( PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12 ); /* Set GPIO12 as input */ GPIO_DIS_OUTPUT( GPIO_ID_PIN(12) ); /* Disable all GPIO interrupts */ ETS_GPIO_INTR_DISABLE(); /* Set a GPIO callback function */ ETS_GPIO_INTR_ATTACH( gpioCallback, NULL ); /* Configure the type of edge */ gpio_pin_intr_state_set( GPIO_ID_PIN(12), GPIO_PIN_INTR_ANYEDGE ); ETS_GPIO_INTR_ENABLE(); /* ====================================== */ /* SOFTWARE TIMER */ /* ====================================== */ // Set GPIO0 to output mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); //Set GPIO0 low gpio_output_set(0, RELAY_PIN, RELAY_PIN, 0); /* disarm timer */ os_timer_disarm((ETSTimer*)&some_timer); /* set callback */ os_timer_setfn((ETSTimer*)&some_timer, (os_timer_func_t *) softwareTimerCallback, NULL); /* arm the timer -> os_timer_arm(<pointer>, <period in ms>, <fire periodically>) */ os_timer_arm((ETSTimer*)&some_timer, 10, 1); /* ====================================== */ /* OS TASK */ /* ====================================== */ /* setup OS task */ // system_os_task(user_procTask, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen); /* send a message to OS task (fire task) */ // system_os_post(user_procTaskPrio, 0, 0 ); /* ====================================== */ /* HARDWARE TIMER */ /* ====================================== */ /* The hardware timer is used to indicate when a complete IR message frame should have * arrived in order to process the received data and calculate the IR command. * * It is configured in "one-shot" mode. It is started when the beginning of an * IR message frame is detected and stopped after the complete message frame has been read. * This means that the duration of the HW timer should be longer than the duration of * the longest message frame. In the NEC IR tranmission protocol all message frames have * a duration of approximately 67.5ms. */ /* load the HW TIMER */ uint32 ticks = usToTicks(70000); // 70ms RTC_REG_WRITE(FRC1_LOAD_ADDRESS, ticks); /* register callback function */ ETS_FRC_TIMER1_INTR_ATTACH( hwTimerCallback, NULL ); /* enable interrupts */ TM1_EDGE_INT_ENABLE(); ETS_FRC1_INTR_ENABLE(); /* don't start timer yet */ /* the timer is started inside the GPIO INT callback */ /* ====================================== */ /* UDP SERVER */ /* ====================================== */ /* usage: echo <data> | nc -wl -u <ip address> <port> * example: echo "foo" | nc -w1 -u 192.168.1.187 7777 */ /* allocate space for server */ pUdpServer = (struct espconn *) os_zalloc(sizeof(struct espconn)); /* clear allocated memory */ ets_memset(pUdpServer, 0, sizeof(struct espconn)); /* create the server */ espconn_create(pUdpServer); /* set the type of server */ pUdpServer->type = ESPCONN_UDP; /* allocate memory for UDP settings */ pUdpServer->proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp)); /* set the port that the server will be listening to */ pUdpServer->proto.udp->local_port = 7777; /* register the callback */ espconn_regist_recvcb(pUdpServer, udpServerRxCb); /* start listening */ if (espconn_create(pUdpServer)) { while (1) { os_printf("Error creating a UDP server\n"); } } /* ====================================== */ /* WIFI */ /* ====================================== */ wifi_set_opmode(STATION_MODE); wifi_station_get_config_default(&stconf); // os_strncpy((char*) stconf.ssid, "TP-LINK_2.4GHz_FC2E51", 32); // os_strncpy((char*) stconf.password, "tonytony", 64); os_strncpy((char*) stconf.ssid, "WLAN-PUB", 32); os_strncpy((char*) stconf.password, "", 64); // os_strncpy((char*) stconf.ssid, "MAD air", 32); // os_strncpy((char*) stconf.password, "glioninlog", 64); stconf.bssid_set = 0; wifi_station_set_config(&stconf); // /* ====================================== */ // /* WS2812 LED STRIP */ // /* ====================================== */ // // /* NOTE: UART1 and I2S share same GPIO. Cannot use simultaneously. */ // ws2812_init(); // // /* G R B */ // uint8_t ledout[] = { // 0xff, 0x00, 0x00, //4th //// 0xff, 0x00, 0x00, //3rd //// 0x00, 0xff, 0x00, //2nd //// 0x00, 0x00, 0xff, //1st // }; // //#if 0 // os_printf("\r\nB R G: %x %x %x\r\n", ledout[0], ledout[1],ledout[2]); //#endif // // ws2812_push( ledout, sizeof( ledout ) ); /* ====================================== */ /* TCP CONNECTION */ /* ====================================== */ /* allocate space for server */ pTcpConn = (struct espconn *) os_zalloc(sizeof(struct espconn)); /* clear allocated memory */ ets_memset(pTcpConn, 0, sizeof(struct espconn)); /* set the type of connection */ pTcpConn->type = ESPCONN_TCP; /* set state to NONE */ pTcpConn->state = ESPCONN_NONE; /* allocate memory for TCP settings */ pTcpConn->proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); /* set the port that the connection will be listening to */ pTcpConn->proto.tcp->local_port = espconn_port(); /* set the remote port and IP address */ pTcpConn->proto.tcp->remote_port = 80; os_memcpy(pTcpConn->proto.tcp->remote_ip, server_ip_address, sizeof(server_ip_address)); /* register callbacks */ espconn_regist_connectcb(pTcpConn, tcpConnCb); espconn_regist_reconcb(pTcpConn, tcpReconnCb); /* disarm timer */ os_timer_disarm((ETSTimer*)&wifi_setup_timer); /* set callback */ os_timer_setfn((ETSTimer*)&wifi_setup_timer, (os_timer_func_t *) wifiConnectTimerCb, NULL); /* arm the timer -> os_timer_arm(<pointer>, <period in ms>, <fire periodically>) */ os_timer_arm((ETSTimer*)&wifi_setup_timer, 5000, 1); return; }
// prevent this function being placed inline with main // to keep main's stack size as small as possible static uint32 NOINLINE find_image() { uint8 flag; uint32 runAddr; uint32 flashsize; int32 romToBoot; uint8 gpio_boot = FALSE; uint8 updateConfig = TRUE; uint8 buffer[SECTOR_SIZE]; rboot_config *romconf = (rboot_config*)buffer; rom_header *header = (rom_header*)buffer; ets_delay_us(2000000); ets_printf("\r\nrBoot v1.0.0 - [email protected]\r\n"); // read rom header SPIRead(0, header, sizeof(rom_header)); // print and get flash size ets_printf("Flash Size: "); flag = header->flags2 >> 4; if (flag == 0) { ets_printf("4 Mbit\r\n"); flashsize = 0x80000; } else if (flag == 1) { ets_printf("2 Mbit\r\n"); flashsize = 0x40000; } else if (flag == 2) { ets_printf("8 Mbit\r\n"); flashsize = 0x100000; } else if (flag == 3) { ets_printf("16 Mbit\r\n"); flashsize = 0x200000; } else if (flag == 4) { ets_printf("32 Mbit\r\n"); flashsize = 0x400000; } else { ets_printf("unknown\r\n"); // assume at least 4mbit flashsize = 0x80000; } // print spi mode ets_printf("Flash Mode: "); if (header->flags1 == 0) { ets_printf("QIO\r\n"); } else if (header->flags1 == 1) { ets_printf("QOUT\r\n"); } else if (header->flags1 == 2) { ets_printf("DIO\r\n"); } else if (header->flags1 == 3) { ets_printf("DOUT\r\n"); } else { ets_printf("unknown\r\n"); } // print spi speed ets_printf("Flash Speed: "); flag = header->flags2 & 0x0f; if (flag == 0) ets_printf("40 MHz\r\n"); else if (flag == 1) ets_printf("26.7 MHz\r\n"); else if (flag == 2) ets_printf("20 MHz\r\n"); else if (flag == 0x0f) ets_printf("80 MHz\r\n"); else ets_printf("unknown\r\n"); // read boot config SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); // fresh install or old version? if (romconf->magic != BOOT_CONFIG_MAGIC || romconf->version != BOOT_CONFIG_VERSION) { // create a default config for a standard 2 rom setup ets_printf("Writing default boot config.\r\n"); ets_memset(romconf, 0x00, sizeof(rboot_config)); romconf->magic = BOOT_CONFIG_MAGIC; romconf->version = BOOT_CONFIG_VERSION; romconf->mode = MODE_STANDARD; romconf->current_rom = 0; romconf->count = 2; romconf->current_rom = 0; romconf->roms[0] = SECTOR_SIZE * 2; romconf->roms[1] = (flashsize / 2) + (SECTOR_SIZE * 2); // write new config sector SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } // if gpio mode enabled check status of the gpio if ((romconf->mode & MODE_GPIO_ROM) && (get_gpio16() == 0)) { ets_printf("Booting GPIO-selected.\r\n"); romToBoot = romconf->gpio_rom; gpio_boot = TRUE; } else if (romconf->current_rom >= romconf->count) { // if invalid rom selected try rom 0 ets_printf("Invalid rom selected, defaulting.\r\n"); romToBoot = 0; romconf->current_rom = 0; updateConfig = TRUE; } else { // try rom selected in the config romToBoot = romconf->current_rom; } // try to find a good rom do { runAddr = check_image(romconf->roms[romToBoot]); if (runAddr == 0) { ets_printf("Rom %d is bad.\r\n", romToBoot); if (gpio_boot) { // don't switch to backup for gpio-selected rom ets_printf("GPIO boot failed.\r\n"); return 0; } else { // for normal mode try each previous rom // until we find a good one or run out updateConfig = TRUE; romToBoot--; if (romToBoot < 0) romToBoot = romconf->count - 1; if (romToBoot == romconf->current_rom) { // tried them all and all are bad! ets_printf("No good rom available.\r\n"); return 0; } } } } while (runAddr == 0); // re-write config, if required if (updateConfig) { romconf->current_rom = romToBoot; SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } ets_printf("Booting rom %d.\r\n", romToBoot); // copy the loader to top of iram ets_memcpy((void*)_text_addr, _text_data, _text_len); // return address to load from return runAddr; }
// prevent this function being placed inline with main // to keep main's stack size as small as possible // don't mark as static or it'll be optimised out when // using the assembler stub uint32 NOINLINE find_image() { uint8 flag; uint32 runAddr; uint32 flashsize; int32 romToBoot; uint8 gpio_boot = FALSE; uint8 updateConfig = TRUE; uint8 buffer[SECTOR_SIZE]; rboot_config *romconf = (rboot_config*)buffer; rom_header *header = (rom_header*)buffer; // delay to slow boot (help see messages when debugging) //ets_delay_us(2000000); ets_printf("\r\nrBoot v1.2.1 - [email protected]\r\n"); // read rom header SPIRead(0, header, sizeof(rom_header)); // print and get flash size ets_printf("Flash Size: "); flag = header->flags2 >> 4; if (flag == 0) { ets_printf("4 Mbit\r\n"); flashsize = 0x80000; } else if (flag == 1) { ets_printf("2 Mbit\r\n"); flashsize = 0x40000; } else if (flag == 2) { ets_printf("8 Mbit\r\n"); flashsize = 0x100000; } else if (flag == 3) { ets_printf("16 Mbit\r\n"); #ifdef BOOT_BIG_FLASH flashsize = 0x200000; #else flashsize = 0x100000; // limit to 8Mbit #endif } else if (flag == 4) { ets_printf("32 Mbit\r\n"); #ifdef BOOT_BIG_FLASH flashsize = 0x400000; #else flashsize = 0x100000; // limit to 8Mbit #endif } else { ets_printf("unknown\r\n"); // assume at least 4mbit flashsize = 0x80000; } // print spi mode ets_printf("Flash Mode: "); if (header->flags1 == 0) { ets_printf("QIO\r\n"); } else if (header->flags1 == 1) { ets_printf("QOUT\r\n"); } else if (header->flags1 == 2) { ets_printf("DIO\r\n"); } else if (header->flags1 == 3) { ets_printf("DOUT\r\n"); } else { ets_printf("unknown\r\n"); } // print spi speed ets_printf("Flash Speed: "); flag = header->flags2 & 0x0f; if (flag == 0) ets_printf("40 MHz\r\n"); else if (flag == 1) ets_printf("26.7 MHz\r\n"); else if (flag == 2) ets_printf("20 MHz\r\n"); else if (flag == 0x0f) ets_printf("80 MHz\r\n"); else ets_printf("unknown\r\n"); // print enabled options #ifdef BOOT_BIG_FLASH ets_printf("rBoot Option: Big flash\r\n"); #endif #ifdef BOOT_CONFIG_CHKSUM ets_printf("rBoot Option: Config chksum\r\n"); #endif #ifdef BOOT_IROM_CHKSUM ets_printf("rBoot Option: irom chksum\r\n"); #endif ets_printf("\r\n"); // read boot config SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); // fresh install or old version? if (romconf->magic != BOOT_CONFIG_MAGIC || romconf->version != BOOT_CONFIG_VERSION #ifdef BOOT_CONFIG_CHKSUM || romconf->chksum != calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum) #endif ) { /* Modified by Cesanta */ ets_printf("Writing default boot config.\r\n"); ets_memset(romconf, 0x00, sizeof(rboot_config)); romconf->magic = BOOT_CONFIG_MAGIC; romconf->version = BOOT_CONFIG_VERSION; romconf->count = 2; romconf->mode = MODE_STANDARD; /* FWx_ADDR, FWx_FS_ADDR and FS_SIZE, FW_SIZE must be defined by -D */ romconf->roms[0] = FW1_ADDR; romconf->roms[1] = FW2_ADDR; romconf->fs_addresses[0] = FW1_FS_ADDR; romconf->fs_addresses[1] = FW2_FS_ADDR; romconf->fs_sizes[0] = romconf->fs_sizes[1] = FS_SIZE; romconf->roms_sizes[0] = romconf->roms_sizes[1] = FW_SIZE; #ifdef BOOT_CONFIG_CHKSUM romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum); #endif // write new config sector SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } // if gpio mode enabled check status of the gpio if ((romconf->mode & MODE_GPIO_ROM) && (get_gpio16() == 0)) { ets_printf("Booting GPIO-selected.\r\n"); romToBoot = romconf->previous_rom; /* * Modified by Cesanta * Make FD current */ updateConfig = TRUE; romconf->fw_updated = 0; romconf->is_first_boot = 0; gpio_boot = TRUE; } else if (romconf->current_rom >= romconf->count) { // if invalid rom selected try rom 0 ets_printf("Invalid rom selected, defaulting.\r\n"); romToBoot = 0; romconf->current_rom = 0; romconf->fw_updated = 0; romconf->is_first_boot = 0; updateConfig = TRUE; } else { /* Modified by Cesanta */ if (romconf->is_first_boot != 0) { ets_printf("First boot, attempt %d\n", romconf->boot_attempts); /* boot is unconfirmed */ if (romconf->boot_attempts == 0) { /* haven't try to load yes */ ets_printf("Boot is unconfirmed\r\n"); romconf->boot_attempts++; } else { ets_printf("Boot failed, fallback to fw #%d\r\n", romconf->previous_rom); romconf->current_rom = romconf->previous_rom; /* clear fw update flag, to avoid post-update acttions */ romconf->fw_updated = 0; romconf->boot_attempts = 0; } updateConfig = TRUE; } /* End of Cesanta modifications */ // try rom selected in the config romToBoot = romconf->current_rom; } // try to find a good rom do { runAddr = check_image(romconf->roms[romToBoot]); if (runAddr == 0) { ets_printf("Rom %d is bad.\r\n", romToBoot); if (gpio_boot) { // don't switch to backup for gpio-selected rom ets_printf("GPIO boot failed.\r\n"); return 0; } else { // for normal mode try each previous rom // until we find a good one or run out updateConfig = TRUE; romToBoot--; if (romToBoot < 0) romToBoot = romconf->count - 1; if (romToBoot == romconf->current_rom) { // tried them all and all are bad! ets_printf("No good rom available.\r\n"); return 0; } } } } while (runAddr == 0); // re-write config, if required if (updateConfig) { romconf->current_rom = romToBoot; #ifdef BOOT_CONFIG_CHKSUM romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum); #endif SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } ets_printf("Booting rom %d.\r\n", romToBoot); // copy the loader to top of iram ets_memcpy((void*)_text_addr, _text_data, _text_len); // return address to load from return runAddr; }