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

reading storage is not working for boot from user2 #1507

Closed
MaBecker opened this issue Sep 12, 2018 · 15 comments
Closed

reading storage is not working for boot from user2 #1507

MaBecker opened this issue Sep 12, 2018 · 15 comments
Labels
ESP8266 This is only a problem on ESP8266 devices

Comments

@MaBecker
Copy link
Contributor

using wiflash to update user1 or user2 switches between boot images

like

435898> OTA: Next firmware: user1.bin (1=0x00101000)

or

144921> OTA: Next firmware: user2.bin (0=0x00001000)

a reboot jumps to run user1 @ 1000 or user2 @ 10100

load 0x40100000, len 2408, room 16
....
  SPI Flash Size & Map: 32Mbit(1024KB+1024KB)
jump to run user1 @ 1000

when jump to run user1 @ 1000 ".wificfg" is available

>require('Storage').list();
=[
  ".wificfg"
 ]

and empty when jump to run user2 @ 101000

>require('Storage').list();
=[  ]

A new Wifi.save() does not fix this issue.

@MaBecker MaBecker added the ESP8266 This is only a problem on ESP8266 devices label Sep 12, 2018
@wilberforce
Copy link
Member

when jump to run user2 @ 101000

Try a reset(1);

That should intialise the storage area - the try the list and save

@MaBecker MaBecker changed the title reading storgare is not working for boot from user2 reading storage is not working for boot from user2 Sep 13, 2018
@MaBecker
Copy link
Contributor Author

@wilberforce thanks for this hint. It does not fix it.

There is #define FLASH_MMAP 0x40200000 used in jsFLashRead and not in jsFlashWrite.
Is this correct?

@wilberforce
Copy link
Member

@MaBecker
Yes it is correct.

addr += FLASH_MMAP; // Direct fast read if < 1Mb

This only happens if the addresses is in the first 1mb - otherwise
res = spi_flash_read(addr, buf, len); is used and this automatically applies the offset.

remember that this works correctly for the user1.bin.

There are some storage debug functions you can compile in - I would start turning those one to see what addresses are used for user1.bin and what address is used for user2.bin.

@MaBecker
Copy link
Contributor Author

Yep good point, just start to activate those os_printf() to check what going on.

@wilberforce
Copy link
Member

@MaBecker
@gfwilliams had #defines already in place from what I recall when I review that code. You should just need to turn those on.

@MaBecker
Copy link
Contributor Author

MaBecker commented Oct 25, 2018

had #defines already in place from what

Yep but targets/esp8266/jshardware.c has lots of commented os_printf() with bad formats [-Wformat=] that have be cleaned up first.....

@wilberforce
Copy link
Member

This might be wirth a try when booting into user2:

#1538 (comment)

require("Storage").eraseAll()

@MaBecker
Copy link
Contributor Author

Good point, but has no effect. still empty

jump to run user2 @ 101000
.....
>require("Storage").write(".boot0","console.log('hello');");
=true
>require('Storage').list()
=[  ]
> 

JSF_START_ADDRESS is used when writing in it is defined in board py file

for ESP8266_4MB it is 0x0CB000

So maybe reading back is get translated to a different addr/sector

@MaBecker
Copy link
Contributor Author

jump to run user1 @ 1000
.....
>require('Storage').list()
=[
  ".bif` "
 ]
>var Wifi = require('Wifi');SSID='SBIT';SSIDPASS='xxxx';Wifi.connect(SSID, {password:SSIDPASS}, function(e){if (e === null){console.log('Connected to AP',SSID);Wifi.setHostname(Wifi.getAPDetails().ssid.replace('_','-'));Wifi.stopAP();Wifi.setConfig({powersave : 'none'});Wifi.save();} else {console.log("error:",e)Wifi.disconnect();}});
=undefined
Connected to AP SBIT
Uncaught Error: File already written with different data
 at line 1 col 174
...rsave : 'none'});Wifi.save();} else {console.log("error:",e)...
                              ^
in function called from system
>require("Storage").eraseAll()
=undefined
>var Wifi = require('Wifi');SSID='SBIT';SSIDPASS='xxxx';Wifi.connect(SSID, {password:SSIDPASS}, function(e){if (e === null){console.log('Connected to AP',SSID);Wifi.setHostname(Wifi.getAPDetails().ssid.replace('_','-'));Wifi.stopAP();Wifi.setConfig({powersave : 'none'});Wifi.save();} else {console.log("error:",e)Wifi.disconnect();}});
=undefined
Connected to AP SBIT
>require('Storage').list()
=[
  ".wificfg"
 ]
> 

@MaBecker
Copy link
Contributor Author

First of all 0x40200000 is used to map the active sector into memory, so it is sector 1 for user1 and sector two for user2. The location of save area is fixed and in sector 1 starting at 0x0CB000 for a ESP8266_4MB board.

void jshFlashRead()
    //replace 
    if (addr < FLASH_MAX) 
    //with 
    if (addr < FLASH_MAX && system_get_userbin_addr() < FLASH_MAX ) 

require('Storage').list() is now working

and similar in size_t jshFlashGetMemMapAddress(size_t ptr)

but still not working when loading user2 @ 101000

@MaBecker
Copy link
Contributor Author

Like to keep storage JSF_START_ADDRESS same for user1 and user2 to have one storage for both images.

Storage.list() and Storage.write() work fine with some litte modifications because they use jshFlashRead() and jshFlashWrite()

Storage.read() fails because it is implemented as memory based read which only works for user1.

@gfwilliams Is there a smart way to make it use jshFlashRead() ?

@gfwilliams
Copy link
Member

We could arrange that jshFlashGetMemMapAddress is allowed to return 0? In case of failure we could then allocate a string in RAM and load the contents of flash into it with jshFlashRead?

The LINUX code above in https://github.com/espruino/Espruino/blob/master/src/jsflash.c#L492 does do that, but it's pretty rough and could fail for large strings on a uC. I'd just allocate the string, use a small (64 byte?) buffer and read from flash in chunks.

Only gotcha there is you could potentially save code to storage that'd work fine from user1, but would fail with out of memory when running from user2. Still, it's better than crashing :)

@MaBecker
Copy link
Contributor Author

Only gotcha there is you could potentially save code to storage that'd work fine from user1, but would fail with out of memory when running from user2. Still, it's better than crashing :)

Good point.

Or user1 uses first segment and user2 uses the second. As I am not sure how many use this wiflash.

So let me fixit, document it and close it :)

@MaBecker
Copy link
Contributor Author

Each userbin segment is using it's own storage area in the same segment.

@wilberforce
Copy link
Member

Nice job

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ESP8266 This is only a problem on ESP8266 devices
Projects
None yet
Development

No branches or pull requests

3 participants