I’m having some fun playing around with the caterina bootloader and made a few changes specifically for Arduboy.
Instead of breating an unimplemented LED the RGB LED breathes alternately read, green, blue. Holding down the A or B button will keep the Arduboy in bootloader mode too.
I’ve made 3 versions with different default timeouts 5 seconds, 7.5 seconds and 10 seconds. Since zip files can’t be uploaded here, here’s an external link
Updates
Latest info will be put here
You can download the latest Cathy3K bootloader from here
High fuses must be set to 0xD2 for Cathy3K bootloader
don’t want to worry about fusesettings? then flash the bootloader using the Arduino IDE with the Homemade package Installed
A demonstration of using the new Arduboy specific display, button and LED features
Warning
Using the custom bootloader requires a change of fuse settings. Burning fuses without knowing what you are doing may brick your Arduboy or Arduino board.
Bootloader commands
The bootloader is a serial device using a subset of the AVR109 protocol.
Standard Caterina supported AVR109 commands:
(these commands are used when uploading using the Arduino IDE)
'A' set current address
'a' get auto address increment support
'B' 0x00 0x80 'F' write block to flash page (auto erases page)
'E' Exit bootloader (after 500msec)
'g' MSB LSB 'F' read block of flash
'L' leave programming mode
'P' enter programming mode
'p' get programmer type
'S' get software ID string
's' read avr signature
'T' byte select device
't' get supported device types list
'V' get software version
0x1B escape
(following commands are supported but not used when uploading with the Arduino IDE)
'B' MSB LSB 'E' write block to EEPROM
'C' byte Write high byte to page buffer
'c' byte Write low byte to page buffer
'D' byte write EEPROM byte
'd' Read EEPROM byte
'e' erase chip (erases application flash area only)
'F' Get low fuse bits
'g' MSB LSB 'E' read EEPROM
'm' Flash pagebuffer
'N' Get high fuse bits
'R' Read flash word
'r' Get lock bits
'Q' Get extended fuse bits
Cathy 3K specific Arduboy commands:
'B' MSB LSB 'C' write block to flash cart (Cathy3K v1.3)
'B' MSB LSB 'D' write block to display
'g' MSB LSB 'C' read block from flash cart (Cathy3K v1.3)
'j' get flash cart JEDEC ID (Cathy3K v1.3)
'v' get button states (AVR109 hardware version command)
'x' set LEDs
If you want to get ambitious, look into moving the bootloader “magic key” to the end of RAM, to fix the magic key overwrite problem.
I believe you do this by indicating that it’s a LUFA bootloader by putting a LUFA signature value (0xDCFB) at the end of flash (FLASHEND -1) and then looking for the magic key at RAMEND - 1 instead of at location 0x800.
For more info, see USBCore.h, USBCore.cpp and CDC.cpp here:
You want to look at the code that deals with NEW_LUFA_SIGNATURE, MAGIC_KEY_POS and MAGIC_KEY. Also the equivalents: bootkey and bootkeyPtr in the Caterina bootloader itself.
I looked through the arduino code and it comes down to single check if the last two bytes of flash contain the word 0xDCFB and when it does, RAMEND-1 is used for magic_key_pos. I checked for references to any of the other the BootloaderAPI_Signature in that other link but didn’t find any so for a bare minimum setting FLASHEND-1 to 0xDCFB should do the trick.
The only problem I see is that in case of a burned protect fuse that disallowes reading the bootloader area. The Arduino IDE will fail to read the signature and will fall back using the old address (0x0800). So maybe the bootloader should check both key positions.
Now I need to find out a nice way how to define a section in the makefile to point to the last two bytes for some testing
#if MAGIC_KEY_POS != (RAMEND-1)
// For future boards save the key in the inproblematic RAMEND
// Which is reserved for the main() return value (which will never return)
if (_updatedLUFAbootloader) {
// horray, we got a new bootloader!
magic_key_pos = (RAMEND-1);
}
#endif
Hmm I just noticed this from the bootloader disassembly:
OK I turned to my reversed assembly version and added the DCFB signature at the end of flash. the bootloader checks for the magic key at RAMEND-1 and when it fails it will also check the old location 0x0800 for sketches using the old boot key pos. I also did some minor optimizing and the size is down to 3900 bytes
Updated the above zip file with this new test version: arduboy-bootloader-leonardo-7.5-sec-timeout-dual-bootkey.hex
Arduino boards, including the Arduboy, only protect the bootloader from being written, not read.
I don’t think there would be a problem with checking 0x0800 after RAMEND-1, though.
Me neither as the Magic key check is only performed when the watchdog timer was triggered.
I’ve added another button test while in bootmode. Besides pressing the A or B button to remain in bootloader mode, pressing any of the D-Pad buttons will exit bootloader mode and run the sketch. But while I’m typing this I’m wondering if I should limit buttons support . I read about the flashlight and config options by pressing a button (sequence) on startup. But not sure which they are.
I knew it was in the library. but I didn’t look into it yet. Thanks for the quick links.
I see I’d better change the button combos. Will need to change the B button from ‘stay in bootloader mode’ otherwise it would be near impossible to trigger the systemsounds optionwhen exiting bootloader mode.
I also realize now that it is’nt really handy to include all buttons in the test. we might wanna use a few combos in future for new features. Thinking about trying the following for the next test:
power on:
DOWN enter bootloader instead of starting sketch (shouldn’t be a problem with system sound as you’d press B first and then B+ UP/DOWN if I understand it correctly)
bootloader mode:
DOWN freeze bootloader timeout timer until button released (again shouldn’t be a problem with system sound feature)
B exit bootloader
This use of the DOWN buttons looks good. This shouldn’t conflict with the Arduboy2 library.
If holding DOWN freezes the timeout until it’s released, why do you need to use the B button to exit the bootloader? Once DOWN is released wouldn’t it exit anyway?
Yes it would after the standard timeout (I’m using 7.5 seconds instead of 8 for the RGB sequence) times out. When DOWN is pressed the timeout counter is simply not updated. When DOWN is released it continues counting towards it’s timeout value. It’s convenient this way and when you accidentally release the button it won’t leave bootloader mode right away.
However when your testing sketches a lot, after each upload it takes another 7.5 seconds to exit bootloader mode and start the sketch (timeout value gets reset during uploading). By pressing the B button after a successful upload, you can start the sketch immediately
Wouldn’t the sketch start immediately after a successful upload anyway? That is, as long as no button was being held. I assume if you were holding the UP button, you would release it as soon as you saw the TX and RX lights flashing, indicating that an upload had started.
If you’ve moved the magic key to RAMEND-1, then I’d think times that powering up into the bootloader and/or extending it’s timeout would be required would be extremely rare. I don’t even see the necessity of needing to extend the current timeout value.
No, because there is no execute command (see CDCtask caterina.c). the bootloader relies on timing out to start the sketch. Both the programming and read commands reset the timeout counter. so when the upload and verify are complete the sketch won’t start until the timeout period has passed.
Oops! I forgot the E command is issued and sets timeout to half a second .
I agree. But I think it’s a a nice little 4 byte feature for Arduboys with broken reset buttons or for anyone not having a toothpick at hand when an application bricked Arduboy.:
sbis PINF,4 ;test DOWN button
rjmp run_bootloader ;button pressed, enter bootloader
Yes I see the B button feature is not really worth it. Better save those 10 bytes of code for something more useful. Just made a new test version with the updated features and added it to the zip file
7.5 second timeout where the RGB LED breathes Red, Green , Blue and off 3 times.
*double MAGIC KEY check + boot signature to enter bootloader mode from opening and closing USB port at 1200baud.
Pressing DOWN button in bootloader mode will hold the bootloader timeout period for as long as the button is held down.
Pressing DOWN while turing on Arduboy put’s it in bootloader mode instead of running the sketch.
Behind the curtain changes:
Identifies it self as ‘ARDUBOY’ programmer instead of ‘CATERIN’ to distinguish itself from the standard bootloader.
After I turned it on it always ended up in bootloader mode. Having a quick look at the main code I realized that SetupHardware was called after I tried reading the DOWN button Putting the port initializing code in the right order made ik work as it should
I removed all the previous test versions and just kept the best version
Managed to kick out just over half a K (526 bytes to be exact) so there are now 562 bytes for new code
The RGB LED breathing is a bit faster now due to the code optimalisation. There are now 5 RGB cycles with the original 8 seconds timeout.
added arduboy-bootloader-leonardo-8-sec-timeout-dual-bootkey-down-button-v3.hex to the zip file
Sounds great! Is there a repo where your changes to the bootloader can be followed/reviewed? It’s mostly curiosity on my part at this stage but I think it would be useful to have traceability back to the “original” Caterina source for a potential substitute bootloader. Thanks!