Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sonata Automotive Demo #44

Merged
merged 21 commits into from
Sep 18, 2024
Merged

Add Sonata Automotive Demo #44

merged 21 commits into from
Sep 18, 2024

Conversation

AlexJones0
Copy link
Contributor

@AlexJones0 AlexJones0 commented Sep 12, 2024

This PR adds the automotive demo for the Sonata board.

You can run xmake -P examples from within the nix develop environment, which will generate 3 new targets of interest:

  • build/cheriot/cheriot/release/automotive_demo_receive
  • build/cheriot/cheriot/release/automotive_demo_send_cheriot
  • build/ilp32/rv32imc/release/automotive_demo_send_legacy

The first 2 can be loaded in the standard manner using the bootloader with an up-to-date CHERI bitstream, and the latter target must be loaded manually via e.g. OpenOCD as it runs baremetal, and must run on an up-to-date non-CHERI (legacy) bitstream.

Most of the documentation for this demo can be found in the two relevant README.md files, the code documentation, and the commit messages. This PR is quite significant in size but the changes are for the most part very isolated and localised to adding things for the demo - please let me know if it would be preferable to split this into several PRs (and if so, where/how to split it) and I'd be happy to do so. The changes that are not localised are the following:

  1. Bump cheriot-rtos to the latest hyperram branch, which contains the rebased hyperram branch including the newest upstream commits, including the ADC and PWM drivers that this demo needs.
  2. Add a submodule for sonata-system under third-party, which is needed so that we can support legacy (non-CHERIoT) baremetal building and cross-compilation without duplicating the existing legacy firmware found in the sonata-system repository.
  3. Updates the LCD library draw_str method to support specifying an additional argument with one of three fonts built into the display drivers, rather than forcing use of m3x6_16pt.
  4. Updates the quick-lint job to not lychee lint or mypy lint the third_party directory, because an error in the included sonata-system submodule (specifically, an error in its vendored coremark dependency containing a non-UTF-8 copyright symbol in a markdown file), and a python module test_runner of the same name, was causing CI to fail.
  5. To support the legacy build process, adds lrPkgs.lowrisc-toolchain-gcc-rv32imcb to the developer environment packages and the common software build packages in the flake.nix. This lets the legacy software be built in CI as a test, and shouldn't affect any existing firmware.

The first four of these changes are in the first four commits and can be easily reviewed independently. The last change is added as part of adding the automotive demo legacy firmware.

In terms of organisation, all demo-specific files are under examples/automotive/. The library files are found under the lib/ sub-directory of that directory, and contain the environment-agnostic code that is used in both pieces of sending firmware. The legacy/ sub-directory contains the non-CHERIoT specific logic required to implement the sending firmware, and the cheri/ sub-directory contains the CHERIoT specific logic required to implement the sending firmware, and the implementation of the receiving firmware also.

As directed in the documentation, this demo can be tested by directly building and configuring the demo - which requires two Sonata boards connected via Ethernet with the correct bitstreams, a 3.3V analogue pedal and a PWM-powered model car to test the full functionality.

@AlexJones0 AlexJones0 force-pushed the auto_demo branch 6 times, most recently from 0bf7787 to bc47e56 Compare September 12, 2024 16:43
Bumps the `cheriot-rtos` submodule to the newest `hyperram` branch
on the local fork, which has been rebased on the latest
`cheriot-rtos` commits. This means that Sonata functionality like
the PWM and ADC drivers are now availabile.
The automotive demo runs on both CHERIoT and non-CHERIoT, and to support
the build flow for this, requires access to some of the definitions in
`sonata-system` to be able to compile for a legacy baremetal
environment. This commit adds a submodule for `sonata-system` so that
these files can be used, without code duplication.
@AlexJones0 AlexJones0 force-pushed the auto_demo branch 2 times, most recently from 3c1f440 to 8ef7dfd Compare September 12, 2024 17:18
@AlexJones0 AlexJones0 marked this pull request as ready for review September 12, 2024 17:21
Copy link
Member

@HU90m HU90m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the commit messages!

flake.nix Outdated Show resolved Hide resolved
libraries/lcd.cc Show resolved Hide resolved
@AlexJones0 AlexJones0 force-pushed the auto_demo branch 2 times, most recently from cef9015 to 7ef46e6 Compare September 18, 2024 15:19
Linting was breaking on including `sonata-system` as a submodule, due to
one of the vendored files from coremark in `sonata-system` containing a
non-UTF-8 copyright symbol in one of its markdown files. This broke
lychee linting.

In general, it doesn't make sense to lint submodules included under the
`third_party` directory. The exclude path contained `vendor`, which does
not exist, but not `third_party` - this is likely an error from copying
or a typo. This commit excludes that path from the lychee lint to avoid
these lints, fixing errors.

mypy was also running into python module naming conflicts with a
`test_runner` in both `sonata-software` and `sonata-system`, so a flag
has similarly been added to the `mypy` linting call to exclude the
`third_party` directory.
Extends the existing Sonata LCD library to support drawing a string with
a specified font, rather than always just using the m3x6 16pt font. The
original method is retained with that font as a default, but an
additional method is added via overloading which accepts an additional
font argument. To avoid exposing the internal font implementation, an
external-facing Font enum class is created which is then just mapped to
these internal fonts.

The LucidaConsole 10pt and 12pt fonts that are already in the display
drivers are then added as optional fonts that can be exposed.
This commit adds the initial common resources that are used by different
demonstration applications in the automotive demo, and adds the first
such application, which is the "no pedal" demo. This is a demo without
any user input, where a bug in a program that counts up and writes to an
array using that count over time causes an out-of-bounds array write
that overwrites some constant acceleration being transmitted.
This commit adds another automotive demo application, in which the demo
remains open until the user decides to quit by pressing the joystick,
and where the user can move the joystick up or down to change the
"speed" being transmitted to the car, sort of simulating the pressing
down of an analogue pedal via a small bit of memory and the joystick
GPIO. This still uses the same out-of-bounds write bug, but is instead
manually triggered when the user moves the joystick left/right.
This commit adds the "digital pedal" application to the automotive demo
library, which is an application that is very similar to the "Joystick
Pedal" demo in its operation, but that instead uses the digital joystick
read callback implemented by users to read the value of some actual
external pedal as a digital input. The demo is initialised in simulation
mode to allow a reasonable demo application with a digital input, and
the same bugged behaviour as in the Joystick pedal demo is incorporated,
with the user moving the joystick to manually trigger the bug, or
pressing the joystick to end the demo.
This commit adds the main "Analogue Pedal" application that will be used
to showcase the demo, relying on the implementing firmware having access
to a working ADC. The analogue pedal read callback is used to read the
input analogue value coming from some external pedal, and this is then
passed through to the receiving board via Ethernet.

Unlike with the other 3 demo applications added so far, this application
features a more visual and realistic bugged task, which is a small
"volume slider" application which allows the user to move the joystick
left or right to increase or decrease the volume correspondingly.
However, a purposeful bug in the code allows the volume to increase one
past its maximum value, to 21/20. The volume value is used every frame
to calculate colour information that is placed inside a small
"framebuffer" array to make a nice coloured volume bar slider, except
when the bugged behaviour occurs, this colour will overwrite the value
of the analogue accelerator pedal that has been read, causing a
wrong / very large acceleration to be transmitted.
This commit introduces a menu for the automotive demo, which allows the
easy navigation of and selection between the different demo applications
available in the automotive demo, using the joystick callback inputs.
This provides a nice environment-agnostic way of perform the
platform-independent demo selection logic.
Adds example firmware for the receiving side of the automotive demo,
which will be running on the 2nd board. This requires the ethernet
driver, as well as the common automotive library.

The receiving firmware is responsible for receiving ethernet frames with
a specific structure over a connection. It has two possible modes of
operation, depending on which demo application is being run. For most
applications, it uses passthrough mode, which directly uses the incoming
acceleration pedal value to drive the car's motor. For specifically the
digital pedal app, it uses simulation mode, which uses the accelerator
pedal value as the driving force input to a model Eulerian physics
simulation, where the car's speed as it is driven against resistive
forces is loosely modeled via some arbitrary constants. The car's
simulated speed is then used to drive the car's motor instead.

The joystick can be pressed down to reset the car's speed between demos.
Adds PWM support to the automotive demo's receiving (board 2) firmware,
so that by using the PWM driver the demo is able to drive a model car
that is connected via PWM. The car is driven by linearly transforming
the car's acceleration from a given range to the range of duty cycles
representable by Sonata's PWM, and then writing the relevant period and
duty cycles to the PWM registers to drive the car's motor.
Adds a seven-segment speedometer display to the automotive demo's
receiving firmware, presenting the car's current speed in a more legible
and aesthetically pleasing manner for the demo.
Implements the base sending firmware (board 1) for the automotive demo,
running in CHERI on top of CHERIoT RTOS. Implements the common
automotive demo library, passing in callbacks with appropriate driver
functionality so that the automotive demos function on the sending board
side. This commit does not include support for the analogue pedal demo,
which requires use of the ADC.

The sending board is responsible for displaying a menu allowing the user
to select a demo application, and then either simulating a pedal or
polling a pedal (depending on the app selected), and transmitting this
pedal information the the receiving board (board 2) via an Ethernet
connection. It is also responsible for simultaneously running another
separate task that is bugged, such that it accidentally overwrites the
acceleration pedal value at some point. Linker script sections are used
to place these tasks contiguously in memory, albeit CHERI would not
allow the access without a capability violation either way.
Uses the ADC driver to implement the ability to read an analogue value
from the pedal, for use in the "Analogue Pedal" application in the
automotive demo's common library.

This allows the demo to become fully functional when running on a
CHERIoT system, which can be used to show the differences when running
on CHERI and without CHERI.
Adds a simple LCD wrapper to be used in the automotive demo's sending
firmware for non-CHERIoT systems. This is based on the existing code in
the `lcd_st7735` demo in the `sonata-system` submodule that is already
using the LCD, but is stripped down to the bare essentials of just
initialising the LCD and removing some of the initialised defaults. This
then allows for LCD callbacks to be implemented for use by the
automotive demo library, which can then use the LCD when running in
baremetal non-CHERI.
The automotive demo requires the ability to send ethernet frames
(between two Sonata boards), but does not want to use an entire TCP/IP
stack on top of it; data is being sent at the data-link layer level.

This commit adds a simple wrapper/driver for using the Ethernet in this
way for the automotive demo, which is based on the existing code already
present in the legacy ethernet demo in the `sonata-system` submodule. It
simply takes the existing code and extracts the LWIP TCP/IP interface,
to allow the functions to use a simplified network interface (containing
just the SPI handle, MAC source and maximum transfer units) and a
simplified frame buffer (storing just the payload and length). This then
enables ethernet to be used for the demo without having to define
TCP/IP-level logic.
Implements the base sending firmware (board 1) for the automotive demo,
running in legacy mode (non-CHERI), baremetal. Implements the common
automotive demo library, passing in callbacks with appropriate driver /
system functionality so that the automotive demo functions on the
sending board side. This commit does not include support for the
analogue pedal demo, which requires use of the ADC.

This commit also includes a simple build flow for legacy baremetal
firmware in xmake based on the existing cmake flow in the sonata-system
submodule, allowing cross-compilation for RISC-V non-CHERI. As part of
this, the rv32imcb GCC compiler toolchain is added to `flake.nix`.
Implements a simple legacy (X)ADC driver for use in the automotive demo.
As the XADC is already configured with defaults such that it starts by
sampling all connected analogue channels and system measurements, this
driver simply provides an easily-extensible interface for reading the
latest ADC measurements from the mapped XADC DRP registers, and for
using the configuration registers to modify the divider / clock speed to
potentially reduce power draw if your application requires this, and
does not need to use the ADC. This is based on the upstream CHERIoT RTOS
CHERIoT version of this driver.
Uses the ADC implementation to provide the ability to read an analogue
value from the pedal, for use in the "Analogue Pedal" application in the
automotive demo's common library.

This allows the demo to become fully functional when running on a
legacy (non-CHERI) baremetal environment, which can be used to show the
differences when running with and without CHERI.
Reorganises the automotive demo to place the CHERI-specific code
in its own CHERI directory, to mirror the organisation used for
non-CHERIoT legacy firmware, and to more clearly modularise and
separate the two implementations of the demo library.
@AlexJones0 AlexJones0 merged commit 72e04e7 into lowRISC:main Sep 18, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants