This commit replaces most heap allocations in USB related code with
stack allocations. This is important for several reasons:
- It avoids running the GC unnecessarily.
- It reduces code size by 400-464 bytes.
- USB code might be called from interrupt handlers. The heap may be in
an inconsistent state when that happens if main thread code also
performs heap allocations.
The last one is by far the most important one: not doing heap
allocations in interrupts is critical for correctness. But the code size
reduction alone should be worth it.
There are two heap allocations in USB related code left: in the function
receiveUSBControlPacket (SAMD21 and SAMD51). This heap allocation must
also be removed because it runs in an interrupt, but I've left that for
a future change.
Calling errors.New in an error path causes a heap allocation at an
already unfortunate moment. It is more efficient to create these error
values in globals and return these constant globals. If these errors are
not used (because the related code was optimized out), the globals will
also be optimized out.
This greatly cuts down on compile time (by about 5x for small programs)
and also makes the program a whole lot smaller. Overall it cuts down
`make smoke-test` in the drivers repository by half (from 160s to 80s).
This will probably also fix the timeout issue in the Playground:
https://github.com/tinygo-org/playground/issues/7