0

WEB page from SD Card on RP2040
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Re: WEB page from SD Card on RP2040

by blakebr on Fri Sep 24, 2021 1:43 pm

Mike,

Code: Select all | TOGGLE FULL SIZE
import samd
samd.disable.autoreset()

The above are not recognised by CircuitPython 7.0.0 for RP2040. I invoked the following.
Code: Select all | TOGGLE FULL SIZE
switch           = DigitalInOut(board.D6)
switch.direction = Direction.INPUT
switch.pull      = Pull.UP
time.sleep(0.25)
print("Switch Value (D6): {}".format(switch.value))

if(switch.value):
    supervisor.enable_autoreload()
    print("Autoreload Enabled!")
else:
    supervisor.disable_autoreload()
    print("Autoreload Disabled!")

The above did not change the issue of delayed writing to the flash memory.

supervisor.reload() is what the RP2040 uses for a soft reboot (softreset). I will implement that if we don't have a 'eureka moment'.
supervisor.reload will only provide current weather information if I soft reboot the hardware every 5 minutes or so. That does not look to me to be an elegant solution.

I am confused as to what updating the bootloader of the AirLift will do toward a solution.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Fri Sep 24, 2021 4:48 pm

Sorry. I had confused some of your hardware. Obviously the SAMD instructions won't help and there is no bootloader upgrade to do on a RP2040.

Is the RP2040 doing all the writing to the SD card? Is the SD card mounted as READONLY by the Pi?

I think we can come up with something better than a software reset.

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Re: WEB page from SD Card on RP2040

by blakebr on Fri Sep 24, 2021 5:57 pm

Mike,

Forget everything I have said.

I am working with a Feather RP2040 with AirLift WiFi also a Nano RP2040 Connect, both RP2040s with SD Card storage. From what I understand they are functionally equivalent for what I need. I want to publish 30 weather web pages that are each updated once every 5 minutes on 20 second intervals. e.g. Update page 1, wait 20 seconds, update page 2, wait 20 seconds.

I have an option I can select in the boot.py file to switch the RP2040 permissions to 'write' between the SD Card or the flash memory, but not both. When the SD Card option is selected, it is mounted for read/write.

When the RP2040 can write to the SD Card, the data is not available as a web page. Web pages on the flash memory are available but the flash memory can't be written to.

When the RP2040 can write to the flash memory, the SD Card is unavailable to the RP2040 for write. I have not tested read because if I can't write updated data why would I want to read from it.
When the RP2040 can write to the flash memory the data is available to the web page BUT it is only updated to the web viewer every 9 hours or after a reboot. The reboot can be a power reboot, a RESET button reboot or supervisor.reload() reboot. None of which are optimal solutions. The supervisor.reload() option is least bad option.

My preference would be to write the web pages to the SD Card for posting to the web. The web client would have access to that data only. That would eliminate the need for the boot.py routines, and protect the flash memory from corruption by unexpected events from code.py. The first index.html web page can reside on the flash memory, pointing to all the other real time web pages on the SD Card. I don't update the first web page real time, it is static.

I hope I have done a good job of describing what I would like to do and some of the issues.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by blakebr on Sat Sep 25, 2021 12:49 pm

Mike,

I did a test to see if supervisor.reload() would be a big issue. supervisor.reload() does not cause the most recent data to be displayed after the soft reboot.

I did a test where I deleted all the web pages and booted the system. I waited for three loops of 30 web pages per loop to be "written" with a supervisor.reload() at the end of each loop of 30 web pages. The web pages were not showing on the flash memory. I pushed the RESET button and like magic they were there.

With that information, I think the data displayed on the web pages is pulled into a buffer area at power on or after a RESET button push or a ~9 hour wait. That buffered data is what is displayed to the web client. The data created every 20 seconds is written to the flash memory as it is created. The buffer is not updated with the new data.

A power reboot or RESET button reboot is not practical every 5 to 6 minutes. The 8 to 9 hour data refresh shows that there is something that can cause the data in the flash memory to be updated to the buffer location. We just need to find out what that magic command is.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by blakebr on Sun Sep 26, 2021 5:02 pm

Mike,

microcontroller.reset() does cause a full board reset and it does bring the weather data into web view.

Bad math in my head. 30 locations X 20 seconds = 600 seconds aka 10 minutes to go through all the locations.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Mon Sep 27, 2021 2:31 pm

Bruce,

Thank you for the excellent summary and congratulations on the small wins this weekend.

I think you are right that there is something that can cause flash to write out to SD.

Two thoughts occurred to me while reading your updates.

1) Are you toggling the SPI CS pin HIGH for the device not in use. EG. after web download turning the AirLift CS HIGH (disable) and during SD write turning SD CS pin low (enable)? Maybe that would explain the conflict of downloading data from web and trying to write to the SD card if they are sharing the same SPI port.

2) Is the web server code itself causing any sort of buffering. EG. if you print the index.html contents over the serial console are the files being updated?

One final thought. Is it possible to buffer all your webpage downloads in memory then write them out at once to the SD card to only have to do a single microcontroller.reset()?

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Re: WEB page from SD Card on RP2040

by blakebr on Mon Sep 27, 2021 7:38 pm

Mike,

Two BIG wins. I root for the Ravens and the P a c k e r s! They both almost gave me a heart attack.

#2 "Your message contains banned spam words."

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by blakebr on Mon Sep 27, 2021 8:54 pm

Mike,

1) I do nothing to/with the SPI CS line. It is totally controlled by imports of storage, digitalio, adafruit_sdcard, and adafruit_esp32spi.

2) I do nothing to buffer data. All web calls are handled by imports of adafrui_requests, os, server, and server.WSGIServer.

I may have confused you. code.py writes the data to the flash memory. The web server shows data from the suspected buffer memory. The web pages need to be updated every from flash memory to buffer memory so we can get the weather information on our iPad, iPhone, or PC any time we want it.

I am writing all 30 web pages to the flash memory as they are created over a 9 to 10 minute period. When the RP2040 is reboot by microcontroller.reset(), every 30 pages,the web pages are copied to the buffer memory. code.py then shows the flash memory copies of the web pages to the client.

Rebooting the RP2040 every 30 web pages/9.5 minutes is not a optimal solution. Real-time access to the web pages without rebooting is my goal. Without microcontroller.reset() the buffer memory is updated every 8 to 9 hours from the data in the flash memory, therefore there must be some magic code that makes that happen on command I can put in code.py.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Tue Sep 28, 2021 12:30 pm

Bruce,

Thank you for stating your situation yet another way.

I was looking into any magic happening with the soft microcontroller.reset. This thread is a nice summary of what is going on with flash and buffer states during a soft reset, but ultimate does not point to a solution.

https://electronics.stackexchange.com/q ... and-turnin

Stupid question for you. What model of SD card are you using?

Did you read about some of the patch that was done to the adafruit_sdcard CircuitPython library around large writes and 32GB Samsung EVO cards? Some of the instrumentation used for debugging might be helpful if you are not experiencing the same issue.

https://github.com/adafruit/Adafruit_Ci ... /issues/11
https://github.com/adafruit/Adafruit_Ci ... /issues/13
https://github.com/adafruit/Adafruit_Ci ... SD/pull/20

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Re: WEB page from SD Card on RP2040

by blakebr on Tue Sep 28, 2021 3:53 pm

Mike,

There are no stupid questions.

For the SD Card memory. ******************

NOTE: The SD Card is not in playing a role when code.py is writing map data to the flash memory or sending web data from the buffer memory.

I am using a Samsung EVO Select, 32GB SD card. Several times over the past trials and tribulations I have pulled the SD Card (power removed from Feather) and put it in my Windows machine and run diagnostics. Each time "No Errors".

The 'index.html' is static in size at 5,558 bytes. It is not written during operation and does not change.

The Open Weather Map HTML files are only 367 bytes to 391 bytes in size. Cluster size is 1kb, so no very large file is written that would cause a write buffer overflow. But each small HTML file looks to be immediately written to the SD Card, so buffer size or overflow should not be an issue.

These are the only files on the SD Card.

For the flash memory. ******************

The 'index.html' is static in size at 5,558 bytes. It is not written during operation and does not change.

The Open Weather Map HTML files are only 367 bytes to 391 bytes in size. Each small HTML file looks to be immediately written to the flash memory, so buffer size or overflow should not be an issue.

These are the only files in the flash memory in the subdirectory accessed for web pages.

********************************

I looked at the references you found. They did not look to address my issue. They were interesting and I did learn stuff. Thanks for the deep dive.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Wed Sep 29, 2021 3:14 pm

Bruce,

I've enjoyed working on this problem with you, but I believe it is now resolved. You had the right idea all along. It just took me 20 minutes to find what you were asking for. There is a filesystem_flush() funciton being called from by microcontroller.reset just before the system softboots with the reset_cpu().

circuitpython/ports/nrf/common-hal/microcontroller

Code: Select all | TOGGLE FULL SIZE
void common_hal_mcu_reset(void) {
    filesystem_flush();
    reset_cpu();
}


https://github.com/adafruit/Adafruit_Ci ... 210928.zip

unzip the above file and go to this file to see the above NRF microcontroller.reset for yourself:

circuitpython/ports/nrf/common-hal/microcontroller/__init__.c

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Re: WEB page from SD Card on RP2040

by blakebr on Wed Sep 29, 2021 4:51 pm

Mike,

I agree with you we are very close to a solution because of your searches.

I downloaded the file your message pointed to - adafruit-circuitpython-bundle-py-20210928.zip.
I was not able to find circuitpython/ports/nrf/common-hal/microcontroller/__init__.c.

I tried filesystem_flush() and got the error - NameError: name 'filesystem_flush' is not defined Not an unexpected error.

I then tried file.filesystem_flush() and got the error - AttributeError: 'TextIOWrapper' object has no attribute 'filesystem_flush'

I may well have missed the mark on what you wanted me to try. Can you give me a step-by-step of what I should do?

I have a file.flush() statement in my code.py that is not causing the result needed.

file.write("%d%%\t Humidity\r\n" % Humi)
file.write("</html>")
file.flush() # *******************
time.sleep(0.05)
file.close()

I don't think we are having a problem flushing the files to the flash memory. We have not found out why and how the OS causes the files in flash memory to be transferred to the buffer memory that is displayed through the web calls. Would it help if I uploaded my code.py and boot.py? ~ 750 lines. Its only requirements in flash memory mode is a Feather RP2040 and an AirLift.

Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Wed Sep 29, 2021 7:23 pm

Bruce,

I had dropped an incorrect link above. Here is the file in question with filesystem_flush being called before the CPU is reset.

https://github.com/adafruit/circuitpyth ... __init__.c

The above is the C code that makes up CircuitPython so we will need find an access point to filesystem_flush from CircuitPython user land.

Going a little deeper into what filesystem_flush() is made up of reveals:

supervisor_flash_flush() being called as part of filesystem_flush().

Code: Select all | TOGGLE FULL SIZE
void filesystem_flush(void) {
    // Reset interval before next flush.
    filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS;
    supervisor_flash_flush();
    // Don't keep caches because this is called when starting or stopping the VM.
    supervisor_flash_release_cache();
}


https://github.com/adafruit/circuitpyth ... lesystem.c

It looks as if you could build a CircuitPython vesion with a custom flush interval. Not sure if we can override that in boot.py.

Code: Select all | TOGGLE FULL SIZE
 CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS


I would also be curious if using os.sync has any effect. It would require doing something like this from the REPL to test or adding it to your code.

Code: Select all | TOGGLE FULL SIZE
import os
os.sync

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Re: WEB page from SD Card on RP2040

by blakebr on Wed Sep 29, 2021 8:26 pm

Mike,

From REPL I get:

import os
os.sync
<function>


Does that meal I should do/try os.sync(filesystem_flush())? I fear disaster. ;-)

When I add os.sync to my code.py it does not crash. But it does not update the web pages.

The more I think about it, the web buffer memory is updated at power on boot, RESET button release boot, and the magic 9 hour thing. It is not updated at power down, or RESET push. There is no warning to those functions to for to update the web buffer memory. So something at power on, RESET release, or 9 hour thing that copies flash memory to buffer memory.

As a WAG the 9 hour thing may be triggered by an unknown number of bytes written, a time thing for a buffer update. 9 hours is 32,400 seconds (32,768 seconds???). We update a ~400 byte file every ~20 seconds in that 9 hours. That would be a total of about 648,000 bytes. That number does not correspond to anything I can correlate it to. So what happens every 32,768 seconds?

FYI Only - I know it is common on older Windows machines with slow BIOS ROMs to copy the BIOS into RAM for faster execution. This may be happening in the RP2030. Flash memory exterior to the RP2040 almost has to be slower than the internal RP2040 RAM. The RP2040 has 264kB on-chip SRAM in six independent banks (44kB each bank). I would bet your bank account (pun intended) that the buffer memory we have been chasing is in there some place. This is probably a Red Herring, but it is probably "why" what is happening, is happening. It does not give us a "how" we fix the issue.

Bruce


Bruce

blakebr
 
Posts: 133
Joined: Tue Apr 17, 2012 6:23 pm

Re: WEB page from SD Card on RP2040

by mikeysklar on Fri Oct 01, 2021 3:51 pm

Bruce,

It seems we have run out of options in terms of google search troubelshooting.

Do you want to write up a short summary of what you have learned and open an issue with the CircuitPython issue. Ideally you would have a tiny piece of example code that shows a buffer not being written to flash until microcontroller.reset() is called.

This way the the circuitpython experts can chime in on whether this is a shutdown or boot up process that is moving the dumping the buffer and maybe how to do it without the reset.

https://github.com/adafruit/circuitpython/issues

mikeysklar
 
Posts: 5767
Joined: Mon Aug 01, 2016 8:10 pm

Please be positive and constructive with your questions and comments.