SpenceKonde/DxCore

Error when trying to write to flash with Optiboot (1.5.8)

technoblogy opened this issue · 15 comments

I’m using DxCore 1.5.8 with AVR DB-series (Optiboot) on an AVR128DB48:

Using library Flash at version 1.5.7 in folder: /Users/david/Library/Arduino15/packages/DxCore/hardware/megaavr/1.5.8/libraries/Flash 

I’m getting error code 0x23 from the call to Flash.checkWritable(). Any suggestions?

You need to reburn bootloader, one of the issues corrected was that the bootloader had the wrong version number.

I definitely reburnt the bootloader - just tried it again to make sure. Same error.

I left the FLMAP options at Use last FLMAP section as I didn't understand that - is that correct?

FLMAP option is unrelated though that can effect how flash is accessed (how addresses have to be treated) it's not related to the issue you are having. I've had a fix ready for some time now but I and should be left at the default unless you have read and understood the relevant section of the recently ammended PROGMEM reference document, but there are changes going out that need documentation ammendments in both cores for different reasons, which should be simple, except that documents that were supposed to be the same are completely different and some contradict reality...

No problem - I can just use an older version of the core for the time being.

But I want people testing the new code. Documentation is almost ready, except reconciling the part of the Optiboot reference relating to writing to flash from app. But who ever does THAT?!

Sure, I'll test it.

This should be fixed in github version.

I got a couple of compile errors from Flash.cpp:

/Users/david/Library/Arduino15/packages/DxCore/hardware/megaavr/1.5.8/libraries/Flash/src/Flash.cpp:21:36: warning: missing terminating " character
       #warning "Writing "everywhere" from within app without Optiboot requires LTO to be enabled.

and:

/Users/david/Library/Arduino15/packages/DxCore/hardware/megaavr/1.5.8/libraries/Flash/src/Flash.cpp: In member function 'uint8_t FlashClass::checkWritable()':
/Users/david/Library/Arduino15/packages/DxCore/hardware/megaavr/1.5.8/libraries/Flash/src/Flash.cpp:93:33: error: expected primary-expression before ')' token
     if (optiversion == 0x0901 ||) {

I fixed those as follows:

      #warning "Writing 'everywhere' from within app without Optiboot requires LTO to be enabled."

and:

    if (optiversion == 0x0901) {

Then it worked fine. No compile errors, and I can write to flash from my app.

Thanks!

PS Tested on AVR128DB48.

Writing from "everywhere" when LTO is disabled does not work for all sketches. LTO disabled rips out all of our guard rails, and some API calls are replaced with empty functions because the normal implementation won't compile with LTO disabled, but you need to compile with LTO disabled in order to get a human readable .S file in order to see what assembly the compiler generated from a given piece of inline ASM in order to diagnose a syntax error in that ASM. The core is not expected to act correctly or efficiently with LTO disabled - LTO disabled mode is for generating .S files in order to debug assembler errors, it is not expected to generate working code. That's why the LTO disabling platform.txt specifically prohibits uploading the code - we expect that the code will often be wrong, but that's okay because the point is not to disable the most dramatic (and really, only significant) compiler improvement since like avr-gcc v4.x or earlier through to gcc v11/12 or whatever they're up to now - they stopped getting better after 7, and the only thing that makes 7 better than 6 is that 6 had problems - but supported LTO which is the reason they updated to 6. So they moved to 7 to dodge the new bug and get LTO support. 5.4 often loses to 4.3 in binary size contests, ie, the best avr-gcc was 4.3, except for LTO :-P

You bootloader the board a long time ago I reckon, during the days when I'd first implemented this and hadn't yet realized that I had to bump the optiboot version and test for it. The current bootloader version is 0x1A01, with a custom version of 0x10 to prevent overlap with versions of other builds that someone who forked the code earlier might produce, the version bump reflects the (botched) new feature of permitting a variety of entry conditions, and improved armor against code bugs putting the chip into a bootloop or bugged-until-reset state.

I just uploaded the hopefully fixed binaries with version 1A02 of the bootloader. I also now keep the build logs around using the new build.bat. And the elves and listings. just in case

So the versions that will have shipped with DxCore will be:
0x0901 - old version, no support for flash writing. This has several vulnerabilities and should under no circumstances be used.
0x0901 - old version with support for flash writing built with the incorrect version number. These do not have safeguards against code putting the chip into a bad state (dirty resets) and should not be used
0x1901 - Supports flash writing, may protect against dirty resets. Since the latter is not certain, this version should not be used
0x1A01 - Protects against dirty resets and pretends to support various entry conditions, but that doesn't work. The entry conditions are all wrong on this, and it's use is therefore not recommended. .
0x1A02 - Protects against dirty resets, supports flash writes, and correctly supports alternate entry conditions. Needs to be built. Same problem was present on both mTC and DxC.

I'm not sure what question you're answering. There were a couple of typos in the Flash.cpp file (unmatched quotes, spurious '||' operator) that gave compile errors. When I fixed them it worked fine.

I just used whatever LTO option the core defaults to. There's no LTO option on the menu.

You bootloaded the board a long time ago I reckon

No - I uploaded a fresh bootloader via UPDI, and then uploaded my program via serial. As I say, I can then write to flash from my app without problems.

It's not a menu option, you have to rename files to enable it, and it disables uploads (which you've apparently "fixed") but the reason it did that that is that the binaries generally don't actually run. That option is there for one reason and one reason only: debugging asm.because inline asm gets generated by the compiler as part of the .S file passed to the assembler - but not only is it instantly deleted without special incantations, it's not human readable if you use LTO. So you need to see what the compiler renders you inline asm as in order to spot the syntax error sometimes. I was having that problem, and that is precisely why I implemented disabling of LTO. If LTO is disabled, I expect nothing to work, and I am shocked that you are experiencing any success at all while being confident that if you continued playing with the LTO disabled configuration, sooner or later you'd find something broken.

Also, my policy is that as clearly stated in the files involve, disabling LTO is known to make bad code, does not upload for that reason, and is only for asm debugging. Switch back to stock platform.txt!

and, I don't see how to burn bootloader could be succeeding, you can look at the files in any text editor and see plain as day that if the latest bootloader was used, the optiboot version would be 1A01 - and on the new ones, that'll be 1A02. and the line of the hex file describing that is :0201FE00021AE3 - 0x02 bytes starting at address 0x01FE. they are normal data (00)and have values 021A (which is 1A02 after endianness considerations) So if you're reading 0901, the only way that could happen is if the bootloader is an od version.....

Pretty sure you switched the platform.txt some time a while ago to the LTO disabled one I remember i tbeing mentioned and strongly warning against it. Not using LTO makes binaries 10-25% larger and use more ram, breaks all the compile time error checking, and is known to not be safe from undefined behavior and functions replaced by noops if run on actual hardware

I'm building 1A02 now and checking that file output is right.

I'm not quite sure what you're talking about.

You asked me to test your latest GitHub version to see if it fixes the problem of writing to flash from my app.

I have 1.5.8 installed via Boards Manager. I replaced only the files Flash.cpp and Flash.h with the versions copied from your latest version on GitHub.

I left the board options at their defaults apart from:

Bootloader Serial Port: "USART0 (default pins)...

to match the way my AVR128DB48 board is wired. I haven't changed anything else.

I got two compile errors, which appeared to be typos in the Flash.cpp file, and I fixed them to what I thought you'd intended.

It then all worked fine.

Oh....Okay, I totally misinterpreted what you said you had changed, those were the correct change.

Sorry - I should have been more explicit. All good now.