This is a ball of Claude-generated code which was guided by
the datasheets, some trait APIs and other prompt info.
The prompt used to generate the code is appended to this file.
The result is structurally pretty similar to the accelerometer
driver templates I've seen provided by the vendor, except in Rust
and with Xous idioms, so I think this is a pretty reasonable
whack at reducing boilerplate. There's way more features in these
accelerometers than I have time to write getters/setters for.
The few functions I have used look good insofar as getter/setters,
but there are some oddly specific defaults in the file that should
probably be corrected, probably due to over-prompting of the code
generator. I'll work through these over time.
this is some technical debt - Drop doesn't coordinate across
all instances of an object and so the disconnect isn't able
to know exactly when to disconnect. This will require some
guru meditation later on to correct this in a "proper" fashion.
this is a prelude to clock tuning the internal bus networks
for bandwidth. The "trivial" thing of just cranking the speed
up to the edge and letting the dividers didn't seem to help
performance much, though; this could be due to the clock synchronizers
beating against each other.
- remove bounds checking for accelerating blits that are already checked
- fix the command ordering for display power-on to remove "noise"
during power-on of the display.
quick feasibility study to confirm that BIO can convert
a QSPI video stream into 8080-style display stream support.
One of those quirky weird applications that I think BIO is
kind of perfect for.
I think it should work, at the speeds required, but nothing
compares to actual hardware testing.
- oem-baosec-lite board support
- more flash memory types
- transparent polarity switching on reset line
The reset line in particular is having its polarity switched
because the I/Os pull-up by default, and we'd like the reset
line for peripherals to be asserted on reset (this prevents
glitching on e.g. displays while the CPU boots).
I decided i feel too uncomfortable doing any state changes based
on unvalidated data. I can't see a downside to moving the check
to only after the signature has been verified.
one minor issue with this implemnetation is it requires dev
images to have an anti-rollback counter that matches or exceed
the last signed image seen.
This is more of a developr ergonomics issue - this will certainly
lead to some surprise by developers who are trying to take
production devices and "downgrade" them to an old dev tree
that has an old anti-rollback firmware number in it.
However, I think this is navigable and probably the simplicity
of not having an "escape" path for dev-signed imgaes is worth it.
All a developer has to do is to set the anti-rollback version
number to be equal to or greater than what was reported in
the device.
this is a sanity check number that can be used by firmware
to vet a counter value before incrementing to it. it's particularly
useful to thwart wear-out attacks agaisnt anti-rollback firmware
versions, i.e. by specifying an extremely high anti-rollback number
one might be able to cause a reset-to-0 failure and this prevents
that from happening by limiting the maximum value of the the
counter that can be requested.
anti-rollback is a number that is stored in a monatomic counter
inside the device that is compared against the firmware images
presented to the device. If the image version is lower than the
anti-rollback counter, the image is rejected. If the image is
higher, the anti-rollback counter is incremented until it equals
the vesrion in the image.
the receipt mechanism is a method for ensuring that cross-third
party signed images can't be used to dump keys on other third party
images. Every time a boot1 is accepted, a copy of the key block
that was used to accept the third party image is stored in the
receipt block.
If those keys rotate, then the collateral keys are rotated. this
prevents a rotation of third-party images from being used to
dump other third party images.
it does mean that third party signers have to be careful to not
rotate any of their signing keys uninitentially.
The IFR copy of pubkeys is truly actually indelible because
of the no-exceptions write inhibit byte. Add code to check
against that copy.
Note that the IFR region's downside is the presence of
the write-inhibit byte means the check is complicated
as the full key is striped across two locations, but
this code handles that.
The keystore is a sensitive server, and the one-way counters
have security-critical propoerties. So instead of revealing a
generic one-way counter API to the world, specific, limited
requests to do things are going to be created for the keystore.
In this case, the bootwait flag would be convenient to be able
to set from userspace. The motivation for this requirement is
actually continuous integration - a normal human could just
hold down a button while turning on power, but in CI, I don't
have a robotic thumb (or an alternative electrical signal) to
simulate the nerve-pinch on boot.
Previously I was "cheating" and simulating this by nuking the
loader, which effectively forces a bootwait.
However, in production, this is *not possible* because the JTAG
port is sealed off. Thus, this may be the first of a series
of small PRs to incorporate CI tooling that clears up tech
debt like nuking the loader to get into boot wait.
It is not clear if I can get the factory to burn the serial number
(wafer lot, ID, x/y location) into the location I want it to be.
So, I am allowing this to be updated by the firmware on boot,
thus necessitating the permissions to be writeable for the serial
number field.
Furthermore, if there is any error in initializing the chip's
identity in the factory, right now the chip goes into a mode
where it has crashed and can't run diagnostic code. Write errors
in this stage are thus turned into .ok() instead of .unwrap()
because we want to allow the chip to go through the whole flow
and then diagnose any issues later on.
The prior implementation tried to use the UDMA streaming mode
to get Rx data out of the UART.
The problem is that with streaming mode, it's hard to tell how much
data is actually available. This is because the thing that sets up
the stream sets "some number of bytes" as the fetch depth of the
DMA Rx, but all you can read is "number of bytes remaining" out
of the DMA interface.
So when 0 bytes are remaining, you can fetch some data, but you don't
know *how much* to fetch. And if someone else fetched partial data
before you, you don't know how much partial data was fetched. This
could be resolved with some gnarly, highly concurrent state that
gets incremented on every fetch.
Or, we could use poll mode. There's a reason i think it's in the
block, because the Rx DMA mode is more or less not usable. Poll
mode you read a config register, see if there's valid data, and if
so, when you read the data register, it's pulled out of a FIFO.
The FIFO is in hardware and it's 4-deep. As long as you don't
need more than a depth of 4, you're rock solid.
This is a lot easier than the UDMA Rx mode, so I've just gone ahead
and deprecated the Rx mode. I could only ever get the Rx mode
to work to receive a single character *anyways*, so despite its
potential to receive thousands of bytes without CPU intervention,
it was only ever used as a 1-deep buffer because of the inability
to know exactly how much was in the buffer. Thus, the poll mode
is actually an improvement over the DMA mode, in practice.
More importantly, it means the Rx link is much more stable in
GDB kernel mode, if the baud rate is cranked down to 115200 (at
1M baud, the kernel still can't respond quite fast enough to
reliably drain it).
the main issue is that if the IO configuration fully replaces
a previous configuration, two apps can't be loaded at the same
time because the later one replaces the previous one's configuration.
now the I/O settings take an option for a configuration mode,
which is somewhat clumsily expressed as either replacing the
I/O configuration, setting bits only, or clearing bits only.
This maybe could use a cleaner API but not quite sure how to
do it yet.