greatscottgadgets / apollo

microcontroller-based FPGA / JTAG programmer
BSD 3-Clause "New" or "Revised" License
61 stars 29 forks source link

uart_init: avoid division to reduce binary size #17

Closed mndza closed 1 year ago

mndza commented 1 year ago

This optimization removes a bunch of soft division routines in the final binary. Size is reduced by ~568 bytes (depends on toolchain).

mossmann commented 1 year ago

Can you please do this for the other boards too?

miek commented 1 year ago

Could you also add some of that description to the comment in the code (that it's a space optimisation by avoiding pulling in soft division routines)? Just so it's clear for future maintenance.

mndza commented 1 year ago

Revisited this and realized my previous attempts were not correct. I assumed the MCU had the ability to get the whole 64 bit result from a 32x32 bit multiplication, but Cortex-M0 cores only keep the lower 32 bits.

This is another attempt that looks good to me and returns exact results when compared against the original Atmel formula. Some notes if you want to dwelve in the details:

baud = ((clk << 16) - (baudrate << 20)) / clk = (1 << 16) - ceil((baudrate << 20) / clk)

Properties:
  x/y = floor(x/y) + (x/y mod 1)
  ceil(x/y) = floor((x-1)/y) + 1
  floor((x+n)/m) = floor((floor(x)+n)/m)
  ceil((x+n)/m) = ceil((ceil(x)+n)/m)