It’s actually nothing to do with Arduino, it’s to do with the AVR chips. (I expect other Arduino-supported chips have some similar arrangement, though I’m not certain.)
Yes, it is. Though there is a bit more to it as well…
Program memory (i.e. the flash memory, not the RAM or EEPROM) on AVR chips is divided into two sections: ‘bootloader space’ and ‘user space’.
When you boot a ‘classic’ Arduboy it more or less goes straight into ‘user mode’ (it might briefly run in bootloader mode, I’m not certain). That’s because of the way the bootloader is programmed. The original Arduboy uses the ‘Cathy’ bootloader, as do the majority of ATmega32u4s (as far as I’m aware).
When you boot an Arduboy FX it usually goes into the bootloader mode first (that menu you see showing you all the games on the chip is actually the bootloader). That’s a custom bootloader written by @Mr.Blinky. (I’m not sure what the official name is, if there is one.) It can also be configured to boot straight into the last loaded game. (Again, I don’t know if that means it boots straight into ‘user mode’ or makes a brief detour into ‘bootloader mode’ first.)
When the chip runs in ‘bootloader mode’ it runs the ‘bootloader code’ (machine code stored in ‘bootloader space’), and when the chip runs in ‘user mode’ it runs the ‘user code’ (machine code stored in the ‘user space’).
The bootloader mode is responsible for handling the uploading of a ‘user mode’ program, and thus is the part that implements the serial communication over USB. Theoretically you could upload code to an AVR chip through other means, it just happens to be the case that the majority use USB to do this. (Importantly, an AVR chip can only overwrite user space when in bootloader mode.)
User mode software can also do serial communication over USB, but this happens (as far as I understand) entirely separately to the communication the bootloader does. I.e. they do not share any code at all.
Note that overwriting the bootloader actually requires a different process to overwriting user space (typically that method is to use an ICSP as mentioned by @MLXXXp earlier).
In Rust, or in some other language?
What about avr-libc?
(Arduino’s AVR implementation depends upon avr-libc, and Arduboy2 relies on both, so the dependency graph would actually be a sort of triangle-shaped DAG.)
As far as I’m aware, the actual CPU doesn’t really require much initialisation.
I think Arduino might set up a few interrupts, but the actual
main function is very bare bones:
Note that those
loop functions are the ones Arduino instructs programmers to define.
main is actually marked as a ‘weak symbol’, so it’s possible for a programmer to create a new
main function and the compiler will then ignore Arduino’s
main in favour of the programmer’s. (Note that this is a compiler feature, not a feature of the C++ language.)
main is the entry point for any piece of C++ software, this implies that nothing else would be called before or after
main and that you should be able to trace everything that occurs throughout the program from
main. (With the exception of interrupt handlers, which must be defined separately.)
For the Arduboy, it’s actually Arduboy2 that sets up the majority of the hardware. In particular the screen, buttons and speakers. Arduino only handles the CPU because Arduino can’t predict what peripherals the user of an Arduino board will attach to the chip. An ‘Arduino board’ is actually fairly minimal in terms of defined hardware since it’s designed for rapid prototyping and flexibility where peripherals are concerned. (See Arduino Leonardo for the board the Arduboy is based on.)
As long as you haven’t overwritten the bootloader (which shouldn’t be possible to do by accident as long as the bootloader protection fuses are set) then any software you write will end up in the ‘user section’ and run in ‘user mode’, and as mentioned earlier that game select screen is actually the custom FX bootloader, so it should run and function properly regardless of what you upload into the ‘user section’.
I would however advise you to keep your device bootloading into the menu rather than using the ‘boot directly into game’ feature as a precaution. That way if you do end up making something that ‘misbehaves’, rebooting will take you to the bootloader instead of the ‘misbehaving’ user code.
The Arduino IDE actually just sends commands to avrdude.
If you enable verbose uploading you’ll get avrdude messages.
There isn’t actually anything particularly ‘magical’ about how uploading works.
Basically the uploading software just sends a bunch of part-text part-binary commands to the bootloader and the bootloader interprets and responds to them. That protocol is known as avr109. (See also this thread and this thread.)
I know about this because I’ve actually written a fully functional* uploader for Arduboy in C++.
(* When I say ‘fully functional’, it could handle all of the commands properly but I never bothered to make it parse command line arguments or handle COM-port hopping properly, so it was more of a proof of concept/library than a functioning program, which is one of the reasons I never actually published it.)