Close

Backstory

A project log for MicroPort

USB-CDC Serial port for PIC18F, in under 1KiB. Refactored down from a USB-DFU bootloader, hand written in assembler to be light and fast

jesseJesse 12/24/2016 at 05:520 Comments

Coders Log, Stardate... umm, Dec 19, 2016

For the HAD 1KB challenge, I comitted today to taking a working prototype USB firmware consisting of a DFU bootloader and seperate CDC serial extension, and condensing them into a single blob hopefully under the 1KB limit. This consolidation is necessary, as the DFU bootloader alone is nearly 2KB, and the CDC firmware is completely dependant on the bootloader for handling basic USB enumeration. After very recently getting this functionality working, I became excited about the prospect of having a viable contender for the challenge and started looking at whether or not I could even fit the needed logic into 1K

To start out, I tackled the easiest targets for reducing code

- DFU, while nice for deploying updates to commerical devices, and moderately useful for development (nothing next to a programming debugger) is the chief reason the bootloader is almost 2KB. Removing DFU code, and the extra descriptors made up most of the code space savings.

- USB String descriptors, while useful, are not needed and were removed.

- As the bootloader parses USB communication via interrupts, it must determine if and when to call into the seperate 'user' firmware. Unifying the two and removing this logic freed up some more space.

- Some other code cleanup led to modest savings: removed register save/restore during interrupt handler, refactored register clearing during initialization.

- Descriptor tables include 2 layers of indirection. For a device with 1 config descriptor, and no string descriptors, the 2nd table and associated code can be removed. This also led to a flash indexing function only being used in a single place, and no longer needed an extra offset feature as the only remaining call always used an index of zero. The function was 'inlined' to the location where it was used, and the index offset removed.

- The descriptor table was also capable of referencing 64kb of flash addresses. The tables were further shrunk, and more code removed by moving them to the first 256 bytes of flash

All of these changes (with the planned refactor of baud rate logic) have gotten the total firmware size down to just over 1KB. However, the prototype did not yet support receiving through Serial to USB Host. Adding this support will likely require more code to be removed.

Items to explore to gain the needed headroom:

- Remove ping-pong buffering - should save another 60-80 bytes

- The core bootloader has support for PIC18F Extended opcodes, while the CDC code did not. Making use of the extended opcodes should help squeeze out a few more bytes.

- The baud rate divider is calculated by dividing the MCU's clock rate by the desired baud rate. I had recently written a hand-tuned 3-byte division function, however, at over 144 bytes, will probably not make the cut.

- Code review to identify more opportunities for code-size optimization.

Discussions