Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial rBoot bootloader implementation #816

Closed
raburton opened this issue Dec 5, 2015 · 83 comments
Closed

Initial rBoot bootloader implementation #816

raburton opened this issue Dec 5, 2015 · 83 comments
Labels

Comments

@raburton
Copy link

raburton commented Dec 5, 2015

After discussion in #806 (and as previously requested in #477) I have prototyped rBoot integration into nodemcu. You can find it here: https://github.com/raburton/nodemcu-firmware/tree/rboot

This allows you to have two versions of nodemcu-firmware on the device at the same time, switch between them and perform over the-air-updates (OTA).

You can use the following commands to interact with it:
print(rboot.rom()) - prints the current running rom number (0 or 1).
rboot.swap() - change the active rom and reboot into it
rboot.ota() - perform an OTA update of the rom
rboot.otafs() - perform an OTA update of the spiffs (for the other rom, not the current one!)

You will need:

  • A nodemcu devboard or other esp8266 device with 2mbyte flash or larger. Support for 512k devices is impossible (no way to fit two 450k roms on a 512k flash), 1mb devices is just about possible but requires a slightly different approach and more changes to the build system.
  • esptool2 from https://github.com/raburton/esptool2/tree/master add it to your path or define the env var ESPTOOL2 to point to the binary.
  • A decent webserver to serve the OTA rom from (Apache/IIS would be fine, some people have had trouble with python web server modules).

Instructions:

  • Checkout the rboot branch from my nodemcu-firmware fork.
  • Edit app/include/user_config.h and set the details for your ota webserver.
  • Build as normal.
  • Flash rboot.bin to 0x00000, eagle.app.v6.bin to 0x02000.
  • Copy eagle.app.v6.bin to the root of your webserver and rename it to whatever file name you gave in user_config.h
  • Run print(rboot.rom()) and check it returns 0.
  • Connect to wifi.
  • Run rboot.ota() and wait a minute, a second copy of the rom will be flash and the device will reboot into this rom.
  • Run print(rboot.rom()) and check it now returns 1.
@raburton
Copy link
Author

Ok, finished off the prototype. Sorry for the delay, I've been pretty busy.

Spiffs is now supported, each of the two roms gets it's own spiffs after the rom (position configurable) and the correct one is mounted depending on the rom in use. I've removed the url parameter from the ota method, I realised it didn't really make sense to include that. There are pro and cons, but mostly it's not needed and doing it properly would require a better understanding of the internals of the lua interpreter than I currently have. The instructions above have been updated.

Not actually had any feedback though, so I wonder if people are really that interested!

@nickandrew
Copy link
Contributor

@raburton I'm very interested, just not in a position to try anything at this time.

@robertfoss
Copy link
Contributor

I'm very tempted to try this feature out.

Is it possible to include a SPIFFS filesystem with the upgrade? And also, would that filesystem be R/W?

@raburton
Copy link
Author

Yes, there are two ways to add the spiffs to the OTA.

  1. Easiest. Append the spiffs to the nodemcu firmware (with sufficient padding between them for the spiffs to land in the right place on the flash). The position of the spiffs is defined in user_config.h so it would be a matter of adding a little padding to the end of the rom up to this position, then appending the spiffs bin file (remember the starting point for the rom is 0x2000, not at zero, on the flash). Then the spiffs will be updated automatically in a single operation, along with the rom.
  2. Slightly more effort. Add a second call to the ota function (slightly modified) to make a separate update of the spiffs area of the flash. This should probably be on a separate call e.g. rboot.otaspiffs() so that you have the option of just updating one or the other. Actually not that big a deal to implement, but it's two operations when you want to update.

Any spiffs written this way would be read/write as normal, but remember that if you are going to update the spiffs in this way each time you will loose anything that has been written to it by the user.

@raburton
Copy link
Author

@robertfoss I've added an rboot.otafs() method that will pull a spiffs bin file and write it to the other roms spiffs area (not the spiffs of the currently running rom), so you can do that alongside the actual rom update. Also fixed a little bug where the spiffs for the second rom was in the wrong place on a 4mb flash.

@robertfoss
Copy link
Contributor

@raburton Those are killer features. Thank you for taking the time to implement them.

@raburton
Copy link
Author

It's been a month and I've had no feedback. Doesn't look like anyone is very interested.

@jmattsson
Copy link
Member

That was the impression I had in my discussion thread too. I think it's just too early at this time. If you don't mind, keep your changes around and maybe down the track interest will grow/resume/something?

@SeanBannister
Copy link

Was just searching for this feature, great to see someone working on it :) unfortunately I'm not familiar with building NodeMCU so haven't had a chance to test it out.

@someburner
Copy link

Hi @raburton . I am very interested in this. I am using my own flavor of NodeMCU + Esp-ginx + SPIFFS. I just got done implementing the file-serving methods using SPIFFS and am now working on implementing OTA updates, so I will definitely be looking into this. I was actually pretty concerned that I would have to figure out how to implement this myself until I saw this.. I should have feedback for you sometime this week.

@jmattsson
Copy link
Member

@someburner do feel free to have a play with the alternative approach too, over in #806 (branch ref in this comment).

@someburner
Copy link

@jmattsson thanks for the heads up. Is there an example of loading either of these without LUA modules? Do I need to use rtctime_early_startup() or is there a way I can call (link?) the bootloader from user_main() ? I'm still a novice when it comes to the linker and bootloader.

@raburton
Copy link
Author

Was just searching for this feature, great to see someone working on it :) unfortunately I'm not familiar with building NodeMCU so haven't had a chance to test it out.

I think this is the problem, nodemcu is a distributed as a binary which users flash once and forget about, only working with their apps afterwards. Unlike, for example, sming or sdk apps, where the framework forms part of the same rom. Sure, you can get nodemcu as source, but unless you are looking to fix it or add to it why would you? And perhaps much of it's target audience are just learning a bit of programming with lua scripts so wouldn't be in a position to do these things anyway.

To be useful it doesn't need to be something users play with, it needs to be built in to the official rom and the ota updates put on the projects own server so that users can just use it when a new version is released.

@raburton
Copy link
Author

Hi @raburton . I am very interested in this. I am using my own flavor of NodeMCU + Esp-ginx + SPIFFS. I just got done implementing the file-serving methods using SPIFFS and am now working on implementing OTA updates, so I will definitely be looking into this. I was actually pretty concerned that I would have to figure out how to implement this myself until I saw this.. I should have feedback for you sometime this week.

Should be easy enough to add the spiffs ota as well, most if not all of the code you need to do it will already be in that branch. (Although another option to make it even easier is to append the two roms and update as a single unit.) Let me know if you need a hand.

Sming uses rBoot to do ota of the app and spiffs filesystems. There is a sample sming app that demonstrates the use of this using the Sming rBootHttpUpdate class, itself a wrapper for rboot-api, if you need more examples of use.

And as @jmattsson says there are other ways too, see what suits you best if you're doing something custom.

@willd
Copy link

willd commented Jan 25, 2016

Heya!

I seemingly succeeded to both build and flash your fork, but after "Booting rom 0" I get nothing more on baud 74880 and nothing on 9600.

This is the unit I'm trying to run it on: http://www.aliexpress.com/item/rgb-strip-WiFi-controller-1-port-control-15-rgb-lights-communicate-with-Android-phone-to-dim/32301423622.html.

That said, I haven't been able to run anything but the original firmware and v0.9.2.2 AT on it so far.
esptool.py flash_id says it is a e0 4014 flash, which according to this: esp8266/Arduino@5d7a3e9 is a 1Mbyte flash.

I would love some help on the matter :)

@raburton
Copy link
Author

That said, I haven't been able to run anything but the original firmware

That's probably not a good starting point. This devices uses a non-standard pin for the serial port, so you'll probably need to modify nodemcu to get any serial output once it's booted. Funnily enough I have one of these and had to do the same with sming, before I discovered how bad pwm is on the esp. I'm in the process of designing my own board, with hardware pwm and bigger mosfets. PCB almost done, just waiting for parts from China to test a breadboard prototype.

@willd
Copy link

willd commented Jan 25, 2016

How does that work with the bootloader? I can flash, and verify that it works. Does the bootloader push RX on all pins during download mode?

Your project sounds cool, are you perhaps releasing it later on?

Cheers!

Edit: Could you perhaps give me a pointer as to where I can find the pin assignment for the serial output? I'm out of my depth here :)

@raburton
Copy link
Author

Bootloader, rom boot messages and rBoot output will go to both serial lines, but once the sdk has initialised the serial ports you need to output to them individually (as I understand it), which is what NodeMCU will be doing under the covers. Had same problem with Sming, as soon as I got past rBoot it looked like it had hung, but it was just that all output was going to uart0 while uart1 was actually wired to the header pins. rBoot runs fine on them though (no reason it shouldn't of course), had that and Sming going fine, only gave up on them when I discovered how flaky pwm is (also probably need a bit more current. Once I have the device finalised I'll publish the designs. With cheap boards from dirtypcbs and a few parts off aliexpress, probably work no more than $10 a piece (I'm not planning on selling them, making them will be up to anyone who wants one).

@raburton
Copy link
Author

raburton commented Feb 7, 2016

FYI, I've updated the rBoot branch in my fork (https://github.com/raburton/nodemcu-firmware/tree/rboot) to latest master + rBoot implementation (obviously). I thought it was worth keeping it up to date, although few seem interested at present it might come in handy at some point in the future.

@jfollas
Copy link
Contributor

jfollas commented Feb 15, 2016

@raburton FYI: I've been keeping a close eye on this as a potential strategy for my device. Initially, I was convinced that device updates could be managed with just Lua files, but that locks out future enhancements (or bug fixes) that may require new binaries. So, it's good to have an OTA update strategy for firmware itself when devices are deployed to the field.

@devyte
Copy link

devyte commented Mar 7, 2016

@raburton @jmattsson I'm also keeping an eye on this, as well as #806. At the end of my project I'll have something like 40 nodemcu devices deployed around my house, so doing serial updates would be extremely time consuming. Having OTA updates would allow flashing all devices via some automated process.

@someburner
Copy link

@raburton

I just got time to start playing with this. Here's where I'm at: I'm not using the latest NodeMCU source and mine has branched off significantly since I'm not interested in any Lua features. I updated my rboot folder (apis as well as the main rboot folder), and have everything compiling and running on a 4MB ESP12 with rBoot 1.4, split config. I re-wrote the OTA API to use my own implementation and it kind of works. But my issue is not with the OTA I don't think.

I have read through your blog and readmes several times but am still having trouble wrapping my mind around the memory mapping. The actual addressing seems straightforward enough, and I've playing around quite a lot with SPIFFS in the past. But basically, whenever I try to switch ROMs, do an OTA, or anything like that, it crashes-- although I'm pretty sure there is a good reason for it:

I looked through rboot-bigflash.c and I'm fairly certain that Cache_Read_Enable_New is not being linked properly because uncommenting the ets_printf doesn't give me anything. But since it's all mapped I'm not sure if there's another way I can check whether that is indeed the case.

Is there any chance you could shed a little more light on the linking process for Cache_Read_Enable? From what you've written it doesn't sound like there's a definitive way to accomplish it. But perhaps you have some new info on that? The other thing I'm thinking is that I'm still a novice when it comes to makefiles and I'm not sure where to add in extra things (if it's even necessary).

I noticed in the more recent NodeMCU builds there is a prototype for Cache_Read_Enable(uint32_t b0, uint32_t b1, uint32_t use_40108000) and I'm curious about that as well. Any help on any of this would be greatly appreciated, and thanks again for making the port!

@TriAnMan
Copy link

@raburton @marcelstoer
I'm very interested in OTA feature and trying to build NodeMCU with it.
I'm using a docker image provided in docs but get an error:

CC rboot-api.c
CC rboot-bigflash.c
CC rboot-ota.c
AR .output/eagle/debug/lib/rboot.a
xtensa-lx106-elf-ar: creating .output/eagle/debug/lib/rboot.a
CC .output/eagle/debug/image/eagle.app.v6.out
/opt/esp-open-sdk/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: cannot find -lmain2
collect2: error: ld returned 1 exit status
make[1]: *** [.output/eagle/debug/image/eagle.app.v6.out] Error 1
make: *** [.subdirs] Error 2

I assume this error arises because I must add esptool2 somehow to the docker image.
Could you help me to do this?

@raburton
Copy link
Author

Someone else had this same issue with docker, but we never did work out why. It's not esptool2 related, although you will need that too. libmain2.a is created from libmain.a using the objcopy command (it just has one symbol weakened to allow a function to be overridden). The make file should be doing this for you, and if you look higher up the log you should see it happen, but for some reason it wasn't getting found. Have a look in the build dir and you should find the file. One easy option it so just copy it to the sdk lib folder, along side the original libmain.a, and it should find it then.

@someburner
Copy link

someburner commented May 31, 2016

@TriAnMan I think it's because you don't have libmain2 copied over, or it's not in the right directory. Here's how mine looks:

# Base directory for the compiler
OPENSDK_ROOT        ?= /home/jeffrey/esp-open-sdk-1.5.3
XTENSA_TOOLS_ROOT ?= $(OPENSDK_ROOT)/xtensa-lx106-elf/bin/
SDK_ROOT            ?= $(OPENSDK_ROOT)/sdk/
PROJ_ROOT = $(abspath $(dir $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))/

# Base directory of the ESP8266 SDK package, absolute
SDK_BASE                ?= $(abspath $(OPENSDK_ROOT)/esp_iot_sdk_v1.5.3)

............

.PHONY: all .subdirs rboot

ifndef PDIR
# targets for top level only
RBOOT=bin/rboot.bin
LIBMAIN_SRC = $(SDK_ROOT)lib/libmain.a
LIBMAIN_DST = $(PROJ_ROOT)sdk-overrides/lib/libmain2.a
endif

all: .subdirs $(LIBMAIN_DST) $(RBOOT) $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS)

$(LIBMAIN_DST): $(LIBMAIN_SRC)
    @echo "OC $@"
    @$(OBJCOPY) -W Cache_Read_Enable_New $^ $@

............

bin/rboot.bin: rboot/firmware/rboot.bin
    $(Q) cp $^ $@

rboot:
    $(Q) mkdir -p ${PROJ_ROOT}/sdk-overrides/lib;
    $(OBJCOPY) -W Cache_Read_Enable_New ${SDK_ROOT}lib/libmain.a ${LIBMAIN_DST}
    $(Q) $(MAKE) -C ${RBOOT_SRC_DIR}

The "............" is to show some separation. But these are the relevant sections that I have in my Makefile to automatically copy libmain and make a lib directory in sdk-overrides.

@TriAnMan
Copy link

I've just manually copied $(SDK_ROOT)lib/libmain.a to $(PROJ_ROOT)sdk-overrides/lib/libmain2.a and got another error. (:

CC rboot-api.c
CC rboot-bigflash.c
CC rboot-ota.c
AR .output/eagle/debug/lib/rboot.a
xtensa-lx106-elf-ar: creating .output/eagle/debug/lib/rboot.a
CC .output/eagle/debug/image/eagle.app.v6.out
../sdk-overrides/lib/libmain2.a(app_main.o): In function `Cache_Read_Enable_New':
(.text+0x3c): multiple definition of `Cache_Read_Enable_New'
rboot/.output/eagle/debug/lib/rboot.a(rboot-bigflash.o):/opt/nodemcu-firmware/app/rboot/rboot-bigflash.c:37: first defined here
collect2: error: ld returned 1 exit status
make[1]: *** [.output/eagle/debug/image/eagle.app.v6.out] Error 1
make: *** [.subdirs] Error 2

@raburton
Copy link
Author

libmain2 isn't an exact copy of libmain, there wouldn't be much point in that. See the part of the Makefile that generates it, you need to use the objcopy command with the -W option, as below:

$(LIBMAIN_DST): $(LIBMAIN_SRC)
    @echo "OC $@"
    @$(OBJCOPY) -W Cache_Read_Enable_New $^ $@

@TriAnMan
Copy link

TriAnMan commented May 31, 2016

@raburton my steps with docker was:

  1. Install docker (I've removed an old image just to be shure with docker rmi -f marcelstoer/nodemcu-build)
  2. Clone [email protected]:raburton/nodemcu-firmware.git
  3. Checkout rboot branch
  4. Run docker run -e INTEGER_ONLY=1 --rm -ti -vpwd:/opt/nodemcu-firmware marcelstoer/nodemcu-build
    So you can try to reproduce my error.

you need to use the objcopy command with the -W option

I'll try. (:

@TriAnMan
Copy link

TriAnMan commented May 31, 2016

I've made an objectcopy and got another error:

CC rboot-api.c
CC rboot-bigflash.c
CC rboot-ota.c
AR .output/eagle/debug/lib/rboot.a
xtensa-lx106-elf-ar: creating .output/eagle/debug/lib/rboot.a
CC .output/eagle/debug/image/eagle.app.v6.out
E2 ../bin/eagle.app.v6.bin
CC rboot-stage2a.c
LD build/rboot-stage2a.elf
/opt/esp-open-sdk/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: cannot open linker script file ../ld/eagle.rom.addr.v6.ld: No such file or directory
collect2: error: ld returned 1 exit status
make[1]: *** [build/rboot-stage2a.elf] Error 1
make: *** [.subdirs] Error 2

I ran docker with

docker run -e INTEGER_ONLY=1 --rm -ti -v `pwd`:/opt/nodemcu-firmware -v /var/git/esptool2:/var/git/esptool2 -e PATH=/var/git/esptool2:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin marcelstoer/nodemcu-build

@someburner
Copy link

someburner commented Jul 1, 2016

@ymxcc

My esp-rfm69 project is loosely based on NodeMCU firmware (started ~SDK 1.4.1) and I have a websocket uploader that you can drag-and-drop files to the ESP.. But it's all in C. I haven't pushed up any code for rboot OTA version of this and I cut out Lua completely, so I'd have to take some time to make a Lua version. But I think it shouldn't be too hard. Again, never used Lua before, can someone comment on what is required for loading Lua scripts? Are they just stored in SPIFFS?

Are you looking more for MQTT OTA or websocket file upload? I think MQTT would probably be better for most cases, especially with public brokers being available.

@ymxcc
Copy link

ymxcc commented Jul 1, 2016

My task is to provide the Lua Script Language for customers, you know they could operate it like node.js, whatever they like to do, it is so easy. To achieve the goal, for my work, I have to integrate all modules into the firmware. Including the OTA not only for the firmware update but the script. I am very lucky, I found @raburton 's code for firmware update. Sure, the most important thing is let the firmware could update using OTA from cloud, It worked now.

The left is how to update the script through cloud. In fact, I just want to find a shortcut, I mean it is better for me if I could find a good code from Github, I could save more time.

Correct! I used the MQTT to publish a message to inform the Node who need to update now, then updating.... Maybe, like @raburton 's code, the node receive the request, then to start up a request to webserver for the correct downloading script.

@mikewen
Copy link

mikewen commented Jul 1, 2016

This OTA is soooo useful for large projects or products that target end
consumers.

@raburton, thanks for your great work.

Anything I can do to help? Maybe I can start to add custom URL?

I would like to stick with NodeMCU for my WiReboot
https://www.kickstarter.com/projects/786298545/wireboot-keep-your-wifi-on-24-7-automatically-rebo
project.
(I was thinking to switch to Arduino just because OTA update feature.)

On Fri, Jul 1, 2016 at 1:01 AM, ymxcc [email protected] wrote:

My task is to provide the Lua Script Language for customers, you know they
could operate it like node.js, whatever they like to do, it is so easy. To
achieve the goal, for my work, I have to integrate all modules into the
firmware. Including the OTA not only for the firmware update but the
script. I am very lucky, I found @raburton https://github.com/raburton
's code for firmware update. Sure, the most important thing is let the
firmware could update using OTA from cloud, It worked now.

The left is how to update the script through cloud. In fact, I just want
to find a shortcut, I mean it is better for me if I could find a good code
from Github, I could save more time.

Correct! I used the MQTT to publish a message to inform the Node who need
to update now, then updating.... Maybe, like @raburton
https://github.com/raburton 's code, the node receive the request, then
to start up a request to webserver for the correct downloading script.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#816 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AFhSljWujwiFPf3fiqv5KbGuriMiAADHks5qRJ8xgaJpZM4Gvcx1
.

@raburton
Copy link
Author

raburton commented Jul 1, 2016

@mikewen Thanks for the offer. If you can add the custom URL option that'd be great, or if you are pretty good with the internals of nodemcu any improvements you could make to the integration (to make it more inline with the current internals, reuse stuff that's already there, etc.) would be nice.

@ymxcc
Copy link

ymxcc commented Jul 1, 2016

@raburton

Could you give me an example for Lua Script Update?

Thanks so much!

@raburton
Copy link
Author

raburton commented Jul 1, 2016

@ymxcc sorry, I don't actually use lua myself so can't give you a great answer. Suggestions - have your lua scripts in a spiffs, which you can ota update, or just download them with a http request.

@ALL sudden flurry of interest in this thread, but I'm leaving for a couple of weeks holiday this afternoon, so won't be able to participate till I return...

@ymxcc
Copy link

ymxcc commented Jul 1, 2016

@raburton Ok, thanks! Have a good trip!

@karrots
Copy link
Contributor

karrots commented Jul 1, 2016

@ymxcc I have two scripts I used to auto update the Lua on projects of mine. One is a HTTP update script which pulls a update.json file parses the file for further instructions. Typically the instructions are just a list of files to download. I then have a compile script which runs on boot which verifies if a file needs to be compiled. If so it compiles and deletes the source version.

Similar to has been suggested before I call the update script from a MQTT listener. If there is a desire I'll get a Gist posted and get a link to you some how. I hate to hijack this issue.

@devyte
Copy link

devyte commented Jul 3, 2016

Some comments:

  1. I looked a bit through the repo above, and I see code based on espconn. I think use of espconn for new features is deprecated, because it's not supported in the RTOS SDK (i.e.: ESP32). I strongly suggest porting to the lwip equivalent.
  2. I think that the best solution for OTA upgrading would be to split the functionality into two parts: a standalone module for flashing the firmware and choosing which image to boot, and a communication module for actually getting the firmware over the air to the ESP.
  3. There are two possible ways to flash and boot: this rboot-based code is one, the one at DiUS is the other. I think we should choose one of the two and stick with it. A comparison of the two is needed to make such a decision (i.e.: pros/cons, working/not working/missing features, etc). Anyone who has played with both solutions willing to do that?
  4. There are several different ways to get the firmware to the ESP. Some possibilities include:
    *a C webclient which GETs the firmware from a webserver
    *a C webserver similar to EUS which receives the firmware with e.g.: PUT
    *a LUA webclient
    *a LUA webserver
    *use of websockets in the webservers above
    *a LUA tftp server which gets the firmware pushed
    *a LUA tftp client which pulls the firmware from some server
    *MQTT
    The repo in this thread seems to use a C web client to get the firmware. MQTT and websockets seem to also have been implemented by others. I would personally use a LUA webserver running on the ESP.
    The point is: the communication part can be very varied, and hence there should probably be an interface that is generic and allows for different backends.
  5. Would it make more sense to flash the firmware on the fly as chunks of the firmware are received, or to store the entire firmware on the ESP e.g.: on SPIFFS, and only then flash? or (eventually) allow both options?

@raburton
Copy link
Author

@devyte sorry for slow reply, been on holiday.

  1. there are multiple layers here, as previously described, one of which does use espconn and can be replaced with an alternative while still using the rest of the layers below it (such as the actual bootloader, and flashing code, etc.). Sming also has an RTOS port and they use rBoot in it, but have not rewritten the download code yet. If someone in either project, or myself but I'm a bit short of time at the moment, wants to write an RTOS version of this code then it could be reused by any/all projects using rBoot with RTOS SDK.
  2. The bootloader and OTA code are already separate in rBoot, and people have created different OTA methods for their specific purposes.
  3. Can't make a comparison because I don't know the DiUS solution well enough. rBoot itself is well enough documented to see what it can do for you and how it can be used or adapted.
  4. Yes, you can do this any way you choose. I know people have written TFTP OTA code for use with rBoot.
  5. Better to do it on the fly and have two (or more) separate rom slots, better redundancy, and doesn't require lots of free space in your spiffs. It's also much more difficult to do the other way, if you put the rom in spiffs how do you then flash it? That'd need to be on next boot and that would mean putting spiffs code in the bootloader, which you can't do because it doesn't (and can't) use the SDK code or link against it's libraries.

@ymxcc
Copy link

ymxcc commented Sep 6, 2016

@raburton , I encountered a terrible problem.
Before, the rboot firmware could run and update very well.
But now, it can not work! Because I re-install the environment and download the newest version sdk from espressif 8266, that happed!

Although the received correct connection with webserver, however, in the nodemcu, the update processing was unsuccessful, I got some information as follows:

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x40100000, len 1392, room 16
tail 0
chksum 0xa2
load 0x3ffe8000, len 688, room 8
tail 8
chksum 0xe8
csum 0xe8

rBoot v1.4.1 - [email protected]
Flash Size: 32 Mbit
Flash Mode: QIO
Flash Speed: 40 MHz
rBoot Option: Big flash
rBoot Option: irom chksum

Rom 0 is bad.
Rom 1 is bad.
No good rom available.
user code done

I checked some information published before, like some guys @pjsg, @djphoenix, @raburton said, the reason is pointed to net.cert.verify function.

My question is how to "Better to embed the ca info at build time instead of trying to do it dynamically." What's meaning "ca info", and how to embed the ca info at build time instead of trying to do it dynamically?

I am looking forward to receive your or other responds!

Thanks so much!!!!!!!

@ymxcc
Copy link

ymxcc commented Sep 6, 2016

@raburton @djphoenix @pjsg

need help! thanks!

load 0x40100000, len 1392, room 16
tail 0
chksum 0xa2
load 0x3ffe8000, len 688, room 8
tail 8
chksum 0xe8
csum 0xe8

rBoot v1.4.1 - [email protected]
Flash Size: 32 Mbit
Flash Mode: QIO
Flash Speed: 40 MHz
rBoot Option: Big flash
rBoot Option: irom chksum

Rom 0 is bad.
Rom 1 is bad.
No good rom available.
user code done

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x40100000, len 1392, room 16
tail 0
chksum 0xa2
load 0x3ffe8000, len 688, room 8
tail 8
chksum 0xe8
csum 0xe8

rBoot v1.4.1 - [email protected]
Flash Size: 32 Mbit
Flash Mode: QIO
Flash Speed: 40 MHz
rBoot Option: Big flash
rBoot Option: irom chksum

Rom 0 is bad.
Rom 1 is bad.
No good rom available.
user code done

@devsaurus
Copy link
Member

Maybe related to #1390 (comment).

@ymxcc
Copy link

ymxcc commented Sep 7, 2016

@devsaurus it does not work! @raburton @djphoenix @pjsg

@djphoenix
Copy link
Contributor

@ymxcc

My question is how to "Better to embed the ca info at build time instead of trying to do it dynamically." What's meaning "ca info", and how to embed the ca info at build time instead of trying to do it dynamically?

In Makefile I see this part:

$(TOP_DIR)/app/modules/server-ca.crt.h: $(TOP_DIR)/server-ca.crt
        python $(TOP_DIR)/tools/make_server_cert.py $(TOP_DIR)/server-ca.crt > $(TOP_DIR)/app/modules/server-ca.crt.h

So just leave your server CA in server-ca.crt and this is enough to make it built-in. So in Lua-level just call net.cert.verify(true).

@ymxcc
Copy link

ymxcc commented Sep 7, 2016

@djphoenix @raburton
Thank you so much for your response. However, this problem is still happened. Could your OTA code run well with this method?

I use the openSSL toolbox to create a server-ca.crt (as follows for the content in it) and put it into the rboot of the nodemcu firmware build tree, it works.

MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=

When I upgrade, the problem still existed.

Could you have any idea, thanks!

@djphoenix
Copy link
Contributor

@ymxcc sorry, I can't help you because I never used @raburton's OTA code. My OTA method is based on UDP server that I use (with proprietary protocol that I can't open).

@ymxcc
Copy link

ymxcc commented Sep 7, 2016

@djphoenix @raburton
Thanks! Through a hard work day, I found I made a mistake, since I did not read the @raburton 's provided readme.txt carefully. Hnece, a very important message I missed as follows: Remember to set your flash size correctly with your chosen flash tool (e.g. for esptool.py use the -fs option).

Generally, if you do not set the flash size, the default size is 4Mbit with the flash command: e.g. esptool.py --baud 115200 --port /dev/tty.wchusbserial1420 write_flash 0x0000 rboot.bin 0x2000 eagle.app.v6.bin. In other word, the firmware from webserver (OTA) will be flashed from 0x4200. An example from my wrong operation as follows:

init addr: 0x00042000
bootconf.roms[upgrade->rom_slot], 270336
rBoot: Updating...
upgrade->content_len 384720
lupgrade->total_len1 1400
write addr: 0x00042000, len: 0x0578
lupgrade->total_len1 2800
write addr: 0x00042578, len: 0x0578
lupgrade->total_len1 4200
write addr: 0x00042af0, len: 0x0578
lupgrade->total_len1 5600
write addr: 0x00043068, len: 0x0578
lupgrade->total_len1 7000
write addr: 0x000435e0, len: 0x0578
lupgrade->total_len1 8400
write addr: 0x00043b58, len: 0x0578
lupgrade->total_len1 9800
write addr: 0x000440d0, len: 0x0578
lupgrade->total_len1 11200
write addr: 0x00044648, len: 0x0578
lupgrade->total_len1 12600
write addr: 0x00044bc0, len: 0x0578
lupgrade->total_len1 14000
write addr: 0x00045138, len: 0x0578
lupgrade->total_len1 15400
write addr: 0x000456b0, len: 0x0578
lupgrade->total_len1 21000
write addr: 0x00045c28, len: 0x15e0

ets Jan 8 2013,rst cause:2, boot mode:(3,4)

load 0x40100000, len 1392, room 16
tail 0
chksum 0xa2
load 0x3ffe8000, len 688, room 8
tail 8
chksum 0xe8
csum 0xe8

rBoot v1.4.1 - [email protected]
Flash Size: 32 Mbit
Flash Mode: QIO
Flash Speed: 40 MHz
rBoot Option: Big flash
rBoot Option: irom chksum

Rom 0 is bad.
Rom 1 is bad.
No good rom available.
user code done

Obviously, my flash size is 32Mbit, however, the initial address is 0x4000. So, when I was updating the firmware, the part 0f rom 0 would be rewritten by the new firmware.

Additionally, @raburton 's provided that "You can can then write your two roms to flash
addresses 0x2000 and (half chip size + 0x2000). E.g. for 8Mbit flash:
esptool.py write_flash -fs 8m 0x0000 rboot.bin 0x2000 user1.bin 0x82000 user2.bin".
Hence, the correct initial address is from 0x202000, not 0x42000.

After correcting the error, the update firmware ran pretty well. Parts of correcting information I printed as follows:
init addr: 0x00202000 bootconf.roms[upgrade->rom_slot], 2105344 rBoot: Updating... upgrade->content_len 384720 lupgrade->total_len1 1400 write addr: 0x00202000, len: 0x0578 lupgrade->total_len1 2800 write addr: 0x00202578, len: 0x0578 lupgrade->total_len1 4200 write addr: 0x00202af0, len: 0x0578 lupgrade->total_len1 5600 write addr: 0x00203068, len: 0x0578 lupgrade->total_len1 7000 write addr: 0x002035e0, len: 0x0578 lupgrade->total_len1 8400 write addr: 0x00203b58, len: 0x0578 lupgrade->total_len1 9800 write addr: 0x002040d0, len: 0x0578 lupgrade->total_len1 11200 write addr: 0x00204648, len: 0x0578 lupgrade->total_len1 12600 write addr: 0x00204bc0, len: 0x0578 lupgrade->total_len1 14000 write addr: 0x00205138, len: 0x0578 lupgrade->total_len1 15400 write addr: 0x002056b0, len: 0x0578 lupgrade->total_len1 16800 write addr: 0x00205c28, len: 0x0578 lupgrade->total_len1 18200 write addr: 0x002061a0, len: 0x0578 lupgrade->total_len1 19600 write addr: 0x00206718, len: 0x0578 lupgrade->total_len1 21000 write addr: 0x00206c90, len: 0x0578 lupgrade->total_len1 22400 write addr: 0x00207208, len: 0x0578 lupgrade->total_len1 23800 write addr: 0x00207780, len: 0x0578 lupgrade->total_len1 25200 write addr: 0x00207cf8, len: 0x0578 lupgrade->total_len1 26600 write addr: 0x00208270, len: 0x0578 ......................... rBoot: Firmware updated, rebooting to rom 1...

I hope my mistake as a suggestion or remind for somebody.

By the way, about the certificate ca, I also had a try. Unfortunately, I do not think that is main problem for OTA failure. But I insist that you'd better to make your code encryption protection.

@quirkz
Copy link

quirkz commented Apr 28, 2017

I can report this works with current dev 9dbae1c with a mostly clean merge (except for spiffs.c). Thanks @raburton.

print(rboot.rom())
0
print(node.info())
2 0 0 1504987 1458400 4096 0 40000000

@makefu
Copy link
Contributor

makefu commented Dec 3, 2017

Hey, what is the current status of this Issue? I'd really like to have a solution for OTA updates for nodemcu!

@raburton
Copy link
Author

raburton commented Dec 3, 2017

As far as I know OTA in nodemcu never happened due to a lack of interest.

@jmd13391
Copy link

jmd13391 commented Dec 6, 2017

Have you seen this? ==> #2060

@makefu
Copy link
Contributor

makefu commented Dec 8, 2017

@jmd13391 i have now, and this looks very promising. also #1496 looks cool but i still mostly work with esp8266. thanks for the heads-up

@jmd13391
Copy link

jmd13391 commented Dec 9, 2017

@makefu "but i still mostly work with esp8266" -- (so do I)... #2060 is for the ESP8266.,, Sorry, what am I missing?

@makefu
Copy link
Contributor

makefu commented Dec 9, 2017

@jmd13391 the PR i meant was the current open #2078 (only for esp32) , sorry :) i will try out the the code from #2060 this week.

@stale
Copy link

stale bot commented Jul 21, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jul 21, 2019
@stale stale bot closed this as completed Aug 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests