# beyond_bootloader
Firmware repository for HMD main board USB bootloader program

## Requirements 
### Microchip Studio
Go to https://www.microchip.com/en-us/development-tools-tools-and-software/microchip-studio-for-avr-and-sam-devices to download the newest version of Studio.

This build was created with Microchip Studio Version 7.0.2594

Open the .atsln file in Microchip Studio to open and explore the firmware.

## Programming Notes
### Booloader Location
The bootloader resides in the beginning of Flash. On the ATSAMG55 microcontroller, there is a total of 512kB of Flash starting at address 0x00400000 (so it extends to 0x00480000). RAM starts at 0x20000000 and is 160kB (so it goes to 0x20028000).
The Flash is arranged in four sectors. Each sector is 128kB, but the first sector is also split into three sub-sectors of 8kB, 8kB, and 112kB.

![Flash Organization](img/Flash_Org.png)

The first two "small sectors" are reserved for the USB bootloader. This gives 16kB for the bootloader and 512kb-16kb = 496kB for the main application.

### Helpful Scripts
Python scripts in the [script](script) folder can be used to modify a .hex file generated by a compiler for the bootloader, and for uploading new code using the bootloader USB HID. Use "usb_fw_packager.py" to generate a compatible .hex file, and use "usb_fw_updater.py" to upload the new application firmware image.
**Note:** when compiling an application, the **linker script must be modified** to start at the application offset address of 0x00404000, not the default start of Flash at 0x00400000. This cannot be done by the python script.

### Application Firmware Requirements
The bootloader needs to check if a valid application firmware image exists before launching into the application. The application is expected to start after the first 16kB (location 0x00404000). The application is also expected to store the total length in bytes at an offset of 0x400 from the start of the application image. And finally, there is a CRC-32 calculated over the entire application image which is saved after the app image. The bootloader uses the following steps to check the firmware image. 

1. Check if the vector table (first bytes of Flash image) match what is expected for an Arm Cortex-M4. That is, the first 4 bytes are the top of stack pointer and the next 4 bytes are the reset vector location. The bootloader confirms that the stack pointer is a valid RAM location (between 0x20000000 and 0x20028000) and the reset vector is a valid Flash location .
2. Check the length of the app. This is a 4-byte integer, LSB first, stored after the vector table at an offset of 0x400 (so for the application it should be at 0x00404400). The length needs to be able to fit within the application area (496kB).
3. Check the CRC. The bootloader calculates this 32-bit Cyclic Redudancy Check using the BZIP2 format:
   - Initial value = 0xFFFF_FFFF
   - Polynomial = 0x04C1_1DB7
   - Final xor value = 0xFFFF_FFFF (equivalent to binary "NOT"ing the whole thing)
   - Don't reverse input data, don't reverse output data
   The application firmware must have the CRC-32 stored immediately after the application code. Again, LSB first.
   
If all 3 of those steps pass, then the bootloader starts the application firmware. If any of those checks fail the bootloader remains running.

### Updating Application Firmware
Normally the bootloader won't even connect as a USB device. Control jumps straight to the application. But if the application is not valid or doesn't exist, then the bootloader will connect to USB as a HID. Performing updates involves sending many HID write commands with chunks of the new application firmware (note the requirements above for the firmware file) and saving them to Flash.

If the application is valid and is booted into, then the application will be responsible for running the bootloader. The application must write to the ATSAMG55's General Purpose Backup Registers (they retain data on reset) and then reset the processor so the bootloader runs again. The values to load into BKUP registers are:
| Reg # | Value | 
|:---:|:---:|
| GPBR0 | 0x000000BB | 
| GPBR1 | 0x0000001A |

#### HID Commands
All commands start with a command byte. This byte tells the bootloader what type of command to process. The data following the command depends completely on that specific command.

| Command | Description | Command Byte (byte #0) | Data (bytes #1 through 63) | Returned Data |
|:---:|:---:|:---:|:---|:---:|
| Boot   into application | Loads application without the normal checks | 0x42 (B) | n/a | none |
| Erase   application area | Erases all Flash data in the application region | 0x22 (") | n/a | 0: status code |
| Write data | Writes 8 to 32 bytes to a specific Flash address | 0x44 (D) | <ul><li>Byte 1: Data length (must be a multiple of 8, Flash writes have to be 64 bits / 8 bytes</li><li>Bytes 2->5: Location (LSB first)</li><li>Bytes 6->6+length-1: New Flash data to write</li><li>Byte 6+length: 8-bit CRC on the ENTIRE command, including command byte 0 (0x44). Polynomial generator is 0x07, initial input is 0x00. No bit reversal or inversion.</li></ul> | 0: status code |
| Program data | Programs the previously written Flash data. Only whole pages (512B) should be written, so enough "Write data" commands should be sent prior to a "Program data" | 0x50 (P) | n/a | 0: status code |
| Read CRC | Reads the CRC-32 value written in the application image. | 0x43 (C)  | n/a | 0->3: CRC (read from app), MSB first |
| Calculate CRC | Calculates the CRC-32 value from the application image. | 0x4D (M) | n/a | 0->3: CRC (calculated by bootloader), MSB first |

Returned status codes:
| Code | Description |
|:---:|:---:|
| 0x00 | No error - command succeeded |
| 0x01 | Lock error - attempt to write to a locked Flash area |
| 0x02 | Command error - invalid command |
| 0x03 | Verify error - Flash data verification failed |
| 0x04 | Address error - attempt to write to an incorrect address |
| 0x05 | Size error - incorrect size given |
| 0x06 | CRC error - mismatch in given and generated CRC |

## Changelog
v0.2.2 - Nov 13 2024 - Removed USB2517 routines, added a third USB3803 for BS2.
v0.2.1 - Oct 31 2024 - Added USB2517 hub chip startup for BS2.
