diff --git a/examples/automotive/cheri/send.cc b/examples/automotive/cheri/send.cc index 0d91718..4ed6077 100644 --- a/examples/automotive/cheri/send.cc +++ b/examples/automotive/cheri/send.cc @@ -222,7 +222,8 @@ void update_cheri_error_handling() * The remaining variable arguments are unsigned integers used to fill * in the formatting specifiers in the format string. */ -void lcd_draw_str(uint32_t x, +void lcd_draw_str(void *handle, + uint32_t x, uint32_t y, LcdFont font, const char *format, @@ -259,7 +260,7 @@ void lcd_draw_str(uint32_t x, * * `color` is the 32-bit colour to display. */ -void lcd_clean(uint32_t color) +void lcd_clean(void *handle, uint32_t color) { lcd->clean(static_cast(color)); } @@ -273,7 +274,8 @@ void lcd_clean(uint32_t color) * `h` is the height of the rectangle. * `color` is the 32-bit colour to fill the rectangle with. */ -void lcd_fill_rect(uint32_t x, +void lcd_fill_rect(void *handle, + uint32_t x, uint32_t y, uint32_t w, uint32_t h, @@ -293,7 +295,8 @@ void lcd_fill_rect(uint32_t x, * `data` is the byte array containing the image data, of size at least * of `w` * `h`, where each value is a RGB565 colour value. */ -void lcd_draw_img(uint32_t x, +void lcd_draw_img(void *handle, + uint32_t x, uint32_t y, uint32_t w, uint32_t h, @@ -571,6 +574,7 @@ void __cheri_compartment("automotive_send") entry() .ethernet_transmit = send_ethernet_frame, .lcd = { + lcd = lcd, .draw_str = lcd_draw_str, .clean = lcd_clean, .fill_rect = lcd_fill_rect, diff --git a/examples/automotive/legacy/lcd.c b/examples/automotive/legacy/lcd.c deleted file mode 100644 index ddddd38..0000000 --- a/examples/automotive/legacy/lcd.c +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include "lcd.h" - -#include "../../../third_party/display_drivers/src/core/lucida_console_10pt.h" -#include "../../../third_party/display_drivers/src/core/m3x6_16pt.h" -#include "../../../third_party/display_drivers/src/st7735/lcd_st7735.h" -#include "../../../third_party/sonata-system/sw/legacy/common/gpio.h" -#include "../../../third_party/sonata-system/sw/legacy/common/sonata_system.h" -#include "../../../third_party/sonata-system/sw/legacy/common/spi.h" -#include "../../../third_party/sonata-system/sw/legacy/common/timer.h" - -// Define our own GPIO_OUT as the version from `sonata-system` uses void -// pointer arithmetic, which clang-tidy forbids. -#define GPIO_OUT_LCD GPIO_FROM_BASE_ADDR((GPIO_BASE + GPIO_OUT_REG)) - -static void timer_delay(void *handle, uint32_t ms) -{ - uint32_t timeout = get_elapsed_time() + ms; - while (get_elapsed_time() < timeout) - { - __asm__ volatile("wfi"); - } -} - -static uint32_t spi_write(void *handle, uint8_t *data, size_t len) -{ - spi_tx((spi_t *)handle, data, len); - spi_wait_idle((spi_t *)handle); - return len; -} - -static uint32_t gpio_write(void *handle, bool cs, bool dc) -{ - set_output_bit(GPIO_OUT_LCD, LcdDcPin, dc); - set_output_bit(GPIO_OUT_LCD, LcdCsPin, cs); - return 0; -} - -int lcd_init(spi_t *spi, St7735Context *lcd, LCD_Interface *interface) -{ - // Set the initial state of the LCD control pins - set_output_bit(GPIO_OUT_LCD, LcdDcPin, 0x0); - set_output_bit(GPIO_OUT_LCD, LcdBlPin, 0x1); - set_output_bit(GPIO_OUT_LCD, LcdCsPin, 0x0); - - // Reset the LCD - set_output_bit(GPIO_OUT_LCD, LcdRstPin, 0x0); - timer_delay(NULL, 150); - set_output_bit(GPIO_OUT_LCD, LcdRstPin, 0x1); - - // Init LCD Driver, and set the SPI driver - interface->handle = spi; // SPI handle. - interface->spi_write = spi_write; // SPI write callback. - interface->gpio_write = gpio_write; // GPIO write callback. - interface->timer_delay = timer_delay; // Timer delay callback. - lcd_st7735_init(lcd, interface); - lcd_st7735_startup(lcd); - - // Set the LCD orientation - lcd_st7735_set_orientation(lcd, LCD_Rotate180); - - // Setup text font bitmaps to be used and the colors. - lcd_st7735_set_font(lcd, &m3x6_16ptFont); - lcd_st7735_set_font_colors(lcd, BGRColorWhite, BGRColorBlack); - - // Clean display with a white rectangle. - lcd_st7735_clean(lcd); - - return 0; -} diff --git a/examples/automotive/legacy/lcd.h b/examples/automotive/legacy/lcd.h deleted file mode 100644 index 72dec11..0000000 --- a/examples/automotive/legacy/lcd.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#ifndef LCD_H -#define LCD_H - -#include "../../../third_party/display_drivers/src/st7735/lcd_st7735.h" -#include "../../../third_party/sonata-system/sw/legacy/common/spi.h" - -// Constants. -enum -{ - // Pin out mapping. - LcdCsPin = 0, - LcdRstPin, - LcdDcPin, - LcdBlPin, - LcdMosiPin, - LcdSclkPin, - // Spi clock rate. - LcdSpiSpeedHz = 5 * 100 * 1000, -}; - -enum -{ - BGRColorBlack = 0x000000, - BGRColorBlue = 0xFF0000, - BGRColorGreen = 0x00FF00, - BGRColorRed = 0x0000FF, - BGRColorWhite = 0xFFFFFF, -}; - -int lcd_init(spi_t *spi, St7735Context *lcd, LCD_Interface *interface); - -#endif // LCD_H diff --git a/examples/automotive/legacy/send.c b/examples/automotive/legacy/send.c index ad96a23..9d53aee 100644 --- a/examples/automotive/legacy/send.c +++ b/examples/automotive/legacy/send.c @@ -8,15 +8,6 @@ #include #include -#include "../../../third_party/display_drivers/src/core/lucida_console_10pt.h" -#include "../../../third_party/display_drivers/src/core/lucida_console_12pt.h" -#include "../../../third_party/display_drivers/src/core/m3x6_16pt.h" -#include "../../../third_party/display_drivers/src/st7735/lcd_st7735.h" -#include "../../../third_party/sonata-system/sw/legacy/common/gpio.h" -#include "../../../third_party/sonata-system/sw/legacy/common/rv_plic.h" -#include "../../../third_party/sonata-system/sw/legacy/common/sonata_system.h" -#include "../../../third_party/sonata-system/sw/legacy/common/spi.h" -#include "../../../third_party/sonata-system/sw/legacy/common/timer.h" #include "../lib/analogue_pedal.h" #include "../lib/automotive_common.h" #include "../lib/automotive_menu.h" @@ -24,8 +15,18 @@ #include "../lib/joystick_pedal.h" #include "../lib/no_pedal.h" #include "adc.h" +#include "gpio.h" #include "ksz8851.h" #include "lcd.h" +#include "lcd_st7735.h" +#include "lucida_console_10pt.h" +#include "lucida_console_12pt.h" +#include "m3x6_16pt.h" +#include "pwm.h" +#include "rv_plic.h" +#include "sonata_system.h" +#include "spi.h" +#include "timer.h" // When using our model pedal, these are the maximum and minimum values that // are measured through the ADC from the pedal's full range of motion. We @@ -34,8 +35,8 @@ #define PEDAL_MIN_ANALOGUE 310 #define PEDAL_MAX_ANALOGUE 1700 -#define BACKGROUND_COLOUR ColorBlack -#define TEXT_COLOUR ColorWhite +#define BACKGROUND_COLOUR RGBColorBlack +#define TEXT_COLOUR RGBColorWhite #define ADC_BASE 0x8000B000 @@ -85,104 +86,6 @@ uint64_t wait(const uint64_t EndTime) return currentTime; } -/** - * Formats and draws a string to the LCD display based upon the provided - * formatting and display information. The string can use formatting - * specifiers as defined by `vsnprintf(3)`. - * - * `x` is the X-coordinate on the LCD of the top left of the string. - * `y` is the Y-coordinate on the LCD of the top left of the string. - * `font` is the font to render the string with. - * `format` is the formatting string to write. - * `backgroundColour` is the colour to use for the string's background. - * `textColour` is the colour to render the text in. - * The remaining variable arguments are unsigned integers used to fill in the - * formatiting specifiers in the format string. - */ -void lcd_draw_str(uint32_t x, - uint32_t y, - LcdFont font, - const char *format, - uint32_t backgroundColour, - uint32_t textColour, - ...) -{ - // Format the provided string - char buffer[1024]; - va_list args; - va_start(args, textColour); - vsnprintf(buffer, 1024, format, args); - va_end(args); - - Font stringFont; - switch (font) - { - case LucidaConsole_10pt: - stringFont = lucidaConsole_10ptFont; - break; - case LucidaConsole_12pt: - stringFont = lucidaConsole_12ptFont; - break; - default: - stringFont = m3x6_16ptFont; - } - lcd_st7735_set_font(&lcd, &stringFont); - lcd_st7735_set_font_colors(&lcd, backgroundColour, textColour); - lcd_st7735_puts(&lcd, (LCD_Point){x, y}, buffer); -} - -/** - * A callback function used to clean the LCD display with a given colour. - * - * `color` is the 32-bit colour to display. - */ -void lcd_clean(uint32_t color) -{ - size_t w, h; - lcd_st7735_get_resolution(&lcd, &h, &w); - LCD_rectangle rect = {(LCD_Point){0, 0}, w, h}; - lcd_st7735_fill_rectangle(&lcd, rect, color); -} - -/** - * A callback function used to draw a rectangle on the LCD. - * - * `x` is the X-position of the top-left corner of the rectangle on the LCD. - * `y` is the Y-position of the top-left corner of the rectangle on the LCD. - * `w` is the width of the rectangle. - * `h` is the height of the rectangle. - * `color` is the 32-bit colour to fill the rectangle with. - */ -void lcd_fill_rect(uint32_t x, - uint32_t y, - uint32_t w, - uint32_t h, - uint32_t color) -{ - LCD_rectangle rect = {(LCD_Point){x, y}, w, h}; - lcd_st7735_fill_rectangle(&lcd, rect, color); -} - -/** - * A callback function used to draw an image to the LCD. - * - * `x` is the X-position of the top-left corner of the image on the LCD. - * `y` is the Y-position of the top-left corner of the image on the LCD. - * `w` is the width of the image. - * `h` is the height of the image. - * `data` is the byte array containing the image data, of size at least - * of `w` * `h`, where each value is a RGB565 colour value. - */ -void lcd_draw_img(uint32_t x, - uint32_t y, - uint32_t w, - uint32_t h, - const uint8_t *data) -{ - LCD_rectangle rect = {(LCD_Point){x, y}, w, h}; - lcd_st7735_draw_rgb565(&lcd, rect, data); -} - /** * A callback function used to read the GPIO joystick state. * @@ -191,7 +94,7 @@ void lcd_draw_img(uint32_t x, */ uint8_t read_joystick() { - return ((uint8_t)read_gpio(GPIO_IN_DBNC_AM)) & 0x1f; + return ((uint8_t)(read_gpio(GPIO_IN_DBNC_AM) >> 8u) & 0x1f); } /** @@ -361,37 +264,44 @@ int main() timer_init(); timer_enable(SYSCLK_FREQ / 1000); + pwm_t lcd_bl = PWM_FROM_ADDR_AND_INDEX(PWM_BASE, PWM_LCD); + // Initialise LCD display driver LCD_Interface lcdInterface; spi_t lcdSpi; spi_init(&lcdSpi, LCD_SPI, LcdSpiSpeedHz); - lcd_init(&lcdSpi, &lcd, &lcdInterface); - lcd_clean(BACKGROUND_COLOUR); + lcd_init(&lcdSpi, lcd_bl, &lcd, &lcdInterface); + lcd_clean(&lcd, BACKGROUND_COLOUR); const LCD_Point Centre = {lcd.parent.width / 2, lcd.parent.height / 2}; + write_to_uart("%s:%d\n", __func__, __LINE__); // Initialise Ethernet support for use via callback rv_plic_init(); spi_t ethernetSpi; - spi_init(ðernetSpi, ETH_SPI, /*speed=*/0); + spi_init(ðernetSpi, ETH_SPI, 1 * 1000 * 1000); ethernetInterface.spi = ðernetSpi; uint8_t macSource[6]; for (uint8_t i = 0; i < 6; i++) { macSource[i] = FixedDemoHeader.macSource[i]; } + write_to_uart("%s:%d\n", __func__, __LINE__); ksz8851_init(ðernetInterface, macSource); + write_to_uart("%s:%d\n", __func__, __LINE__); // Wait until a good physical ethernet link to start the demo if (!ksz8851_get_phy_status(ðernetInterface)) { write_to_uart("Waiting for a good physical ethernet link...\n"); - lcd_draw_str(Centre.x - 55, + lcd_draw_str(&lcd, + Centre.x - 55, Centre.y - 5, M3x6_16pt, "Waiting for a good physical", BACKGROUND_COLOUR, TEXT_COLOUR); - lcd_draw_str(Centre.x - 30, + lcd_draw_str(&lcd, + Centre.x - 30, Centre.y + 5, M3x6_16pt, "ethernet link...", @@ -425,6 +335,7 @@ int main() .ethernet_transmit = send_ethernet_frame, .lcd = { + .lcd = &lcd, .draw_str = lcd_draw_str, .clean = lcd_clean, .fill_rect = lcd_fill_rect, diff --git a/examples/automotive/legacy/xmake.lua b/examples/automotive/legacy/xmake.lua index f4a1b98..0629024 100644 --- a/examples/automotive/legacy/xmake.lua +++ b/examples/automotive/legacy/xmake.lua @@ -3,93 +3,9 @@ set_project("Sonata Automotive Demo Legacy Version") --- The directory containing this script -local scriptdir = os.scriptdir() --- The root of the `sonata-software` repository -local rootdir = path.join(scriptdir, '../../..') --- The directory containing the legacy baremetal build files (link script, runtime, drivers) -local legacy_dir = path.join(rootdir, "third_party/sonata-system/sw/legacy") - --- This unnecessary boilerplate is used so that you can run `xmake -P examples/automotive/legacy` --- and then run `xmake -P examples` without xmake complaining. If this is not included, and no --- options are provided, then xmake will by default determine your local architecture/platform, --- and save this in the xmake config for future runs - which is wrong for the cross-compilation --- used in `examples/xmake.lua`, even though these are labelled as different projects. This --- ensures the xmake config is not altered without users knowing. -set_defaultarchs("cheriot") -set_defaultplat("cheriot") - --- Setup the GCC toolchain for building non-CHERI baremetal programs -toolchain("legacy-gcc") - set_kind("standalone") - set_toolset("cc", "riscv32-unknown-elf-gcc") - set_toolset("cxx", "riscv32-unknown-elf-g++") - set_toolset("objcopy", "riscv32-unknown-elf-objcopy") - set_toolset("ld", "riscv32-unknown-elf-gcc") - set_toolset("as", "riscv32-unknown-elf-gcc") - set_toolset("ar", "riscv32-unknown-elf-ar") - - -- Set up flags needed in the toolchain - on_load(function (toolchain) - local linkscript = path.join(legacy_dir, "link.ld") - -- Flags used for C/C++, assembly and the linker - local default_flags = { - "-march=rv32imc", - "-mabi=ilp32", - "-mcmodel=medany", - "-Wall", - "-fvisibility=hidden" - } - -- C/C++ flags - toolchain:add("cxflags", default_flags, {force = true}) - toolchain:add("cflags", default_flags) - -- Assembly flags - toolchain:add("asflags", default_flags) - -- Linker flags - toolchain:add("ldflags", default_flags) - toolchain:add("ldflags", "-ffreestanding -g -nostartfiles -T " .. linkscript) - end) -toolchain_end() - --- Helper function to define legacy firmware (running without CHERI or CHERIoT-RTOS, baremetal) --- Useful for comparing between CHERI and non-CHERI for e.g. demos/exercises -function legacy_firmware(name) - - -- Create the firmware target; remains open on return, so the caller can - -- add more rules to it as they like. - target(name) - set_kind("binary") - set_arch("rv32imc") - set_plat("ilp32") - set_languages("gnu99", "gnuxx11") - -- Add the basic C runtime to the baremetal firmware - add_files( - path.join(legacy_dir, "common/crt0.S"), - path.join(legacy_dir, "common/gpio.c"), - path.join(legacy_dir, "common/i2c.c"), - path.join(legacy_dir, "common/pwm.c"), - path.join(legacy_dir, "common/rv_plic.c"), - path.join(legacy_dir, "common/sonata_system.c"), - path.join(legacy_dir, "common/spi.c"), - path.join(legacy_dir, "common/timer.c"), - path.join(legacy_dir, "common/uart.c") - ) -end - +includes("../../legacy_drivers") set_toolchains("legacy-gcc") --- Legacy-specific LCD library for using the display drivers -target("lcd_st7735_lib_am") - set_kind("static") - local lcd_dir = path.join(rootdir, "third_party/display_drivers/src/") - add_files( - path.join(lcd_dir, "core/lcd_base.c"), - path.join(lcd_dir, "core/lucida_console_10pt.c"), - path.join(lcd_dir, "core/lucida_console_12pt.c"), - path.join(lcd_dir, "core/m3x6_16pt.c"), - path.join(lcd_dir, "st7735/lcd_st7735.c") - ) - -- The automotive library shared between the legacy & CHERIoT firmware target("automotive_lib") set_kind("static") @@ -101,8 +17,9 @@ target("automotive_lib") "../lib/digital_pedal.c", "../lib/analogue_pedal.c" ) + add_deps("legacy_drivers") -- Automotive demo: Sending Firmware (1st board) (non-CHERIoT version) legacy_firmware("automotive_demo_send_legacy") - add_deps("lcd_st7735_lib_am", "automotive_lib") - add_files("send.c", "ksz8851.c", "lcd.c", "adc.c") + add_deps("lcd_st7735_lib_am", "automotive_lib", "legacy_drivers") + add_files("send.c") diff --git a/examples/automotive/lib/analogue_pedal.c b/examples/automotive/lib/analogue_pedal.c index a9c0710..6230bac 100644 --- a/examples/automotive/lib/analogue_pedal.c +++ b/examples/automotive/lib/analogue_pedal.c @@ -34,13 +34,13 @@ void init_analogue_pedal_demo_mem(AnalogueTaskOne *taskOne, */ static uint64_t lerp_green_to_red(uint32_t portion, uint32_t segments) { - uint64_t red = ColorRed; - uint64_t green = ColorGreen; + uint64_t red = RGBColorRed; + uint64_t green = RGBColorGreen; red *= portion; green *= (segments - portion); red /= segments; green /= segments; - return (red & 0xFF) | (green & 0xFF00); + return (red & 0xFF0000) | (green & 0xFF00); } /** @@ -52,8 +52,10 @@ static uint64_t lerp_green_to_red(uint32_t portion, uint32_t segments) */ static void outline_volume_bar(uint32_t x, uint32_t y, uint32_t maxVolume) { - callbacks.lcd.fill_rect(x, y, 7 + maxVolume * 6, 13, ColorWhite); - callbacks.lcd.fill_rect(x + 2, y + 2, 3 + maxVolume * 6, 9, ColorBlack); + callbacks.lcd.fill_rect( + callbacks.lcd.lcd, x, y, 7 + maxVolume * 6, 13, RGBColorWhite); + callbacks.lcd.fill_rect( + callbacks.lcd.lcd, x + 2, y + 2, 3 + maxVolume * 6, 9, RGBColorBlack); } /** @@ -70,8 +72,12 @@ static void draw_volume_bar(uint32_t x, uint32_t y, uint32_t maxVolume) { for (uint32_t i = 0; i < maxVolume; ++i) { - callbacks.lcd.fill_rect( - x + 4 + (i * 6), y + 4, 5, 5, taskTwoMem->framebuffer[i]); + callbacks.lcd.fill_rect(callbacks.lcd.lcd, + x + 4 + (i * 6), + y + 4, + 5, + 5, + taskTwoMem->framebuffer[i]); } } @@ -160,27 +166,35 @@ void run_analogue_pedal_demo(uint64_t initTime) // Draw static LCD graphics, and populate the frame buffer with colours for // the initial volume bar. - callbacks.lcd.draw_img_rgb565(11, 30, 15, 11, soundIconImg15x11); + callbacks.lcd.draw_img_rgb565( + callbacks.lcd.lcd, 11, 30, 15, 11, soundIconImg15x11); outline_volume_bar(10, 45, 20); for (uint32_t i = 0; i < 20; ++i) { taskTwoMem->framebuffer[i] = (i < taskTwoMem->volume) ? lerp_green_to_red(i, 21) : 0; } - callbacks.lcd.draw_str(10, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 60, LucidaConsole_10pt, "Exceed max volume", - ColorBlack, - ColorDarkGrey); - callbacks.lcd.draw_str( - 10, 75, LucidaConsole_10pt, "for a bug!", ColorBlack, ColorDarkGrey); - callbacks.lcd.draw_str(10, + RGBColorBlack, + RGBColorDarkGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, + 75, + LucidaConsole_10pt, + "for a bug!", + RGBColorBlack, + RGBColorDarkGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 12, M3x6_16pt, "Press the joystick to end the demo.", - ColorBlack, - ColorDarkerGrey); + RGBColorBlack, + RGBColorDarkerGrey); // Call task one and task two sequentially in a loop until the user // selects to quit the demo by pressing the joystick. @@ -192,12 +206,13 @@ void run_analogue_pedal_demo(uint64_t initTime) analogue_task_two(); // Draw the volume bar to the screen each frame using the framebuffer - uint32_t labelColor = (taskTwoMem->volume > 20) ? ColorRed : ColorWhite; - callbacks.lcd.draw_str(33, + uint32_t labelColor = (taskTwoMem->volume > 20) ? RGBColorRed : RGBColorWhite; + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 33, 30, LucidaConsole_10pt, "Volume: %u/%u ", - ColorBlack, + RGBColorBlack, labelColor, (unsigned int)taskTwoMem->volume, 20u); diff --git a/examples/automotive/lib/automotive_common.h b/examples/automotive/lib/automotive_common.h index cc6d900..37b890e 100644 --- a/examples/automotive/lib/automotive_common.h +++ b/examples/automotive/lib/automotive_common.h @@ -5,6 +5,7 @@ #ifndef AUTOMOTIVE_COMMON_H #define AUTOMOTIVE_COMMON_H +#include "../../common/types.h" #include #include @@ -18,27 +19,6 @@ enum JoystickDir Right = 1 << 4, }; -// BGR Colours used for LCD display in the automotive demo -typedef enum LCDColor -{ - ColorBlack = 0x000000, - ColorWhite = 0xFFFFFF, - ColorGrey = 0xCCCCCC, - ColorDarkGrey = 0xA0A0A0, - ColorDarkerGrey = 0x808080, - ColorRed = 0x0000FF, - ColorGreen = 0x00FF00, - ColorBlue = 0xFF0000, -} LCDColor; - -// Fonts available for LCD rendering in the automotive demo -typedef enum LcdFont -{ - M3x6_16pt, // NOLINT - LucidaConsole_10pt, // NOLINT - LucidaConsole_12pt, // NOLINT -} LcdFont; - // Minimal Ethernet Header for sending frames typedef struct EthernetHeader { @@ -112,8 +92,10 @@ typedef struct */ typedef struct LcdCallbacks { + void *lcd; // A function that renders a string to the LCD - void (*draw_str)(uint32_t x, // NOLINT + void (*draw_str)(void *lcd, + uint32_t x, // NOLINT uint32_t y, LcdFont font, const char *format, @@ -121,15 +103,17 @@ typedef struct LcdCallbacks uint32_t textColour, ...); // A function that fills/cleans the LCD with a given colour. - void (*clean)(uint32_t color); + void (*clean)(void *lcd, uint32_t color); // A function that fills a rectangle on the LCD with a given colour. - void (*fill_rect)(uint32_t x, // NOLINT + void (*fill_rect)(void *lcd, + uint32_t x, // NOLINT uint32_t y, uint32_t w, uint32_t h, uint32_t color); // A function that draws a given RGB565 image to the LCD - void (*draw_img_rgb565)(uint32_t x, // NOLINT + void (*draw_img_rgb565)(void *lcd, + uint32_t x, // NOLINT uint32_t y, uint32_t w, uint32_t h, diff --git a/examples/automotive/lib/automotive_menu.c b/examples/automotive/lib/automotive_menu.c index 916eac6..8fdc744 100644 --- a/examples/automotive/lib/automotive_menu.c +++ b/examples/automotive/lib/automotive_menu.c @@ -22,19 +22,28 @@ static void fill_option_select_rects(uint8_t prev, uint8_t current, bool cursorImg) { - callbacks.lcd.fill_rect( - lcdCentre.x - 64, lcdCentre.y - 22 + prev * 20, 5, 5, ColorBlack); + callbacks.lcd.fill_rect(callbacks.lcd.lcd, + lcdCentre.x - 64, + lcdCentre.y - 22 + prev * 20, + 5, + 5, + RGBColorBlack); if (cursorImg) { - callbacks.lcd.draw_img_rgb565(lcdCentre.x - 64, + callbacks.lcd.draw_img_rgb565(callbacks.lcd.lcd, + lcdCentre.x - 64, lcdCentre.y - 22 + current * 20, 5, 5, cursorImg5x5); return; } - callbacks.lcd.fill_rect( - lcdCentre.x - 64, lcdCentre.y - 22 + current * 20, 5, 5, ColorWhite); + callbacks.lcd.fill_rect(callbacks.lcd.lcd, + lcdCentre.x - 64, + lcdCentre.y - 22 + current * 20, + 5, + 5, + RGBColorWhite); } /** @@ -48,13 +57,14 @@ fill_option_select_rects(uint8_t prev, uint8_t current, bool cursorImg) DemoApplication select_demo() { // Display static menu information to the LCD - callbacks.lcd.clean(ColorBlack); - callbacks.lcd.draw_str(lcdCentre.x - 60, + callbacks.lcd.clean(callbacks.lcd.lcd, RGBColorBlack); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + lcdCentre.x - 60, lcdCentre.y - 50, LucidaConsole_12pt, "Select Demo", - ColorBlack, - ColorWhite); + RGBColorBlack, + RGBColorWhite); const char *demoOptions[] = { "[1] Analogue", "[2] Digital", @@ -63,12 +73,13 @@ DemoApplication select_demo() }; for (uint8_t i = 0; i < 4; i++) { - callbacks.lcd.draw_str(lcdCentre.x - 55, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + lcdCentre.x - 55, lcdCentre.y - 25 + i * 20, LucidaConsole_10pt, demoOptions[i], - ColorBlack, - ColorDarkerGrey); + RGBColorBlack, + RGBColorDarkerGrey); } const uint8_t NumOptions = 4; @@ -101,6 +112,6 @@ DemoApplication select_demo() } } - callbacks.lcd.clean(ColorBlack); + callbacks.lcd.clean(callbacks.lcd.lcd, RGBColorBlack); return (DemoApplication)currentOption; } diff --git a/examples/automotive/lib/digital_pedal.c b/examples/automotive/lib/digital_pedal.c index a259822..08b4403 100644 --- a/examples/automotive/lib/digital_pedal.c +++ b/examples/automotive/lib/digital_pedal.c @@ -82,8 +82,13 @@ bool digital_task_two() // Display bug status information to the LCD const char *bugStr = isBugged ? "Bug triggered" : "Not triggered"; - callbacks.lcd.draw_str( - 10, 10, LucidaConsole_10pt, bugStr, ColorBlack, ColorGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 0, + 10, + LucidaConsole_10pt, + bugStr, + RGBColorBlack, + RGBColorGrey); // If flagged to be bugged, use an out-of-bounds index uint32_t index = 99; @@ -125,18 +130,20 @@ void run_digital_pedal_demo(uint64_t initTime) isBugged = false; // Draw static demo operation/usage information to the LCD - callbacks.lcd.draw_str(10, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 27, M3x6_16pt, "Joystick left/right to trigger bug", - ColorBlack, - ColorDarkGrey); - callbacks.lcd.draw_str(10, + RGBColorBlack, + RGBColorDarkGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 80, M3x6_16pt, "Press the joystick to end the demo.", - ColorBlack, - ColorGrey); + RGBColorBlack, + RGBColorGrey); // Call task one and task two sequentially in a loop until the user // selects to quit the demo by pressing the joystick diff --git a/examples/automotive/lib/joystick_pedal.c b/examples/automotive/lib/joystick_pedal.c index 0858756..d6cd11e 100644 --- a/examples/automotive/lib/joystick_pedal.c +++ b/examples/automotive/lib/joystick_pedal.c @@ -41,12 +41,13 @@ void init_joystick_demo_mem(TaskOne *taskOne, TaskTwo *taskTwo) static void joystick_task_one() { // Display speed information to the LCD - callbacks.lcd.draw_str(10, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 45, LucidaConsole_10pt, "Current speed: %u ", - ColorBlack, - ColorWhite, + RGBColorBlack, + RGBColorWhite, (unsigned int)taskOneMem->acceleration); // Transmit the previously measured pedal information to the car. @@ -104,8 +105,13 @@ bool joystick_task_two() // Display bug status information to the LCD const char *bugStr = isBugged ? "Bug triggered" : "Not triggered"; - callbacks.lcd.draw_str( - 10, 10, LucidaConsole_10pt, bugStr, ColorBlack, ColorGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, + 10, + LucidaConsole_10pt, + bugStr, + RGBColorBlack, + RGBColorGrey); // If flagged to be bugged, use an out-of-bounds index uint32_t index = 99; @@ -149,24 +155,27 @@ void run_joystick_demo(uint64_t initTime) isBugged = false; // Draw static demo operation/usage information to the LCD - callbacks.lcd.draw_str(10, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 62, M3x6_16pt, "Joystick up/down to change speed", - ColorBlack, - ColorDarkGrey); - callbacks.lcd.draw_str(10, + RGBColorBlack, + RGBColorDarkGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 27, M3x6_16pt, "Joystick left/right to trigger bug", - ColorBlack, - ColorDarkGrey); - callbacks.lcd.draw_str(10, + RGBColorBlack, + RGBColorDarkGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 10, 80, M3x6_16pt, "Press the joystick to end the demo.", - ColorBlack, - ColorDarkerGrey); + RGBColorBlack, + RGBColorDarkerGrey); // Call task one and task two sequentially in a loop until the // user selects to quit the demo by pressing the joystick. diff --git a/examples/automotive/lib/no_pedal.c b/examples/automotive/lib/no_pedal.c index adb652b..475127c 100644 --- a/examples/automotive/lib/no_pedal.c +++ b/examples/automotive/lib/no_pedal.c @@ -70,16 +70,22 @@ bool no_pedal_task_two() callbacks.uart_send("task_two, count = %u\n", (unsigned int)counter); // Draw simple pseudocode explaining the bug to the LCD - callbacks.lcd.draw_str(5, + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 5, 25, LucidaConsole_10pt, "int i = %u;", - ColorBlack, - ColorGrey, + RGBColorBlack, + RGBColorGrey, (unsigned int)counter); - uint32_t textColor = (counter >= 100) ? ColorRed : ColorGrey; - callbacks.lcd.draw_str( - 5, 55, LucidaConsole_10pt, " arr[i] = 1000;", ColorBlack, textColor); + uint32_t textColor = (counter >= 100) ? RGBColorRed : RGBColorGrey; + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 5, + 55, + LucidaConsole_10pt, + " arr[i] = 1000;", + RGBColorBlack, + textColor); // The buggy line of code implementing task two - this should be a "<" check // to be within the `write` array bounds, but the "<=" comparison check @@ -114,12 +120,22 @@ void run_no_pedal_demo(uint64_t initTime) resetCounter = true; // Draw pseudocode display information to the LCD. + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 5, + 10, + LucidaConsole_10pt, + "int arr[100];", + RGBColorBlack, + RGBColorGrey); + callbacks.lcd.draw_str(callbacks.lcd.lcd, + 5, + 40, + LucidaConsole_10pt, + "if (i <= 100) {", + RGBColorBlack, + RGBColorGrey); callbacks.lcd.draw_str( - 5, 10, LucidaConsole_10pt, "int arr[100];", ColorBlack, ColorGrey); - callbacks.lcd.draw_str( - 5, 40, LucidaConsole_10pt, "if (i <= 100) {", ColorBlack, ColorGrey); - callbacks.lcd.draw_str( - 5, 70, LucidaConsole_10pt, "}", ColorBlack, ColorGrey); + callbacks.lcd.lcd, 5, 70, LucidaConsole_10pt, "}", RGBColorBlack, RGBColorGrey); // Call task one and task two sequentially in a loop for 175 iterations. uint64_t prevTime = initTime; diff --git a/examples/common/types.h b/examples/common/types.h new file mode 100644 index 0000000..0102b41 --- /dev/null +++ b/examples/common/types.h @@ -0,0 +1,37 @@ +// Copyright lowRISC Contributors. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +enum LcdConstantes +{ + // Pin out mapping. + LcdCsPin = 0, + LcdDcPin, + LcdRstPin, + LcdMosiPin, + LcdSclkPin, + // Spi clock rate. + LcdSpiSpeedHz = 5 * 100 * 1000, +}; + +enum RGBColors +{ + RGBColorBlack = 0x000000, + RGBColorWhite = 0xFFFFFF, + RGBColorBlue = 0x0000FF, + RGBColorGreen = 0x00FF00, + RGBColorRed = 0xFF0000, + RGBColorLightGrey = 0xAAAAAA, + RGBColorGrey = 0xCCCCCC, + RGBColorDarkGrey = 0xA0A0A0, + RGBColorDarkerGrey = 0x808080, +}; + +// Fonts available for LCD rendering +typedef enum +{ + M3x6_16pt, // NOLINT + M5x7_16pt, // NOLINT + LucidaConsole_10pt, // NOLINT + LucidaConsole_12pt, // NOLINT +} LcdFont; diff --git a/examples/heartbleed/legacy/heartbleed.c b/examples/heartbleed/legacy/heartbleed.c index 0532f10..47897ec 100644 --- a/examples/heartbleed/legacy/heartbleed.c +++ b/examples/heartbleed/legacy/heartbleed.c @@ -134,28 +134,28 @@ void initial_lcd_write(St7735Context *lcd) lcd_draw_str(lcd, 5, 5, - LcdFontM5x7_16pt, + M5x7_16pt, "Move Joystick to Change Length.", BACKGROUND_COLOR, FOREGROUND_COLOR); lcd_draw_str(lcd, 5, 15, - LcdFontM5x7_16pt, + M5x7_16pt, "Press Joystick to Send.", BACKGROUND_COLOR, FOREGROUND_COLOR); lcd_draw_str(lcd, 5, 30, - LcdFontM5x7_16pt, + M5x7_16pt, "Request a larger buffer", BACKGROUND_COLOR, FOREGROUND_COLOR); lcd_draw_str(lcd, 5, 40, - LcdFontM5x7_16pt, + M5x7_16pt, "Suggested Length: ", BACKGROUND_COLOR, FOREGROUND_COLOR); @@ -172,13 +172,8 @@ void draw_request_length(St7735Context *lcd, size_t request_length) const size_t ReqLenStrLen = 15u; char req_len_s[ReqLenStrLen]; size_t_to_str_base10(req_len_s, request_length); - lcd_draw_str(lcd, - 110, - 40, - LcdFontM5x7_16pt, - req_len_s, - BACKGROUND_COLOR, - FOREGROUND_COLOR); + lcd_draw_str( + lcd, 110, 40, M5x7_16pt, req_len_s, BACKGROUND_COLOR, FOREGROUND_COLOR); } /** @@ -209,7 +204,7 @@ void get_request_length(St7735Context *lcd, size_t *request_length) lcd_draw_str(lcd, 110, 40, - LcdFontM5x7_16pt, + M5x7_16pt, " ", BACKGROUND_COLOR, FOREGROUND_COLOR); @@ -261,7 +256,7 @@ void network_send(void *handle, const char *package, size_t len) lcd_draw_str(lcd, 1, 55 + 10 * line_num, - LcdFontM5x7_16pt, + M5x7_16pt, line_content, TextAreaBgColor, TextAreaFgColor); @@ -276,7 +271,7 @@ void network_send(void *handle, const char *package, size_t len) lcd_draw_str(lcd, 1, 55 + 10 * line_num, - LcdFontM5x7_16pt, + M5x7_16pt, line_content, TextAreaBgColor, TextAreaFgColor); diff --git a/examples/heartbleed/legacy/lcd.h b/examples/heartbleed/legacy/lcd.h deleted file mode 100644 index 31d8994..0000000 --- a/examples/heartbleed/legacy/lcd.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#ifndef _HEARTBLEED_LCD_H_ -#define _HEARTBLEED_LCD_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - - // Constants. - enum - { - // Pin out mapping. - LcdCsPin = 0, - LcdDcPin, - LcdRstPin, - LcdMosiPin, - LcdSclkPin, - // Spi clock rate. - LcdSpiSpeedHz = 5 * 100 * 1000, - }; - - enum - { - RGBColorBlack = 0x000000, - RGBColorWhite = 0xFFFFFF, - RGBColorBlue = 0xFF0000, - RGBColorGreen = 0x00FF00, - RGBColorRed = 0x0000FF, - RGBColorGrey = 0xAAAAAA, - }; - - // Fonts available for LCD rendering - typedef enum LcdFont - { - LcdFontM3x6_16pt, // NOLINT - LcdFontM5x7_16pt, // NOLINT - LcdFontLucidaConsole_10pt, // NOLINT - LcdFontLucidaConsole_12pt, // NOLINT - } LcdFont; - - /** - * @brief Initialise the LCD, starting and clearing the screen. - * - * @param spi contains an initialized SPI handle to use to write to the LCD. - * @param backlight contains an initialized pwm handle to use to control the - * LCD backlight. - * @param lcd is an outparam to store the initialized LCD handle. - * @param interface is an outparam storing the initialized LCD interface. - */ - int lcd_init(spi_t *spi, - pwm_t backlight, - St7735Context *lcd, - LCD_Interface *interface); - - /** - * @brief Formats and draws a string to the LCD display based upon the - * provided formatting and display information. The string can use - * formatting specifiers as defined by `vsnprintf(3)`. - * - * @param lcd a handle to the LCD to draw to. - * @param x is the X-coordinate on the LCD of the top left of the string. - * @param y is the Y-coordinate on the LCD of the top left of the string. - * @param font is the font to render the string with. - * @param format is the formatting string to write. - * @param backgroundColour is the colour to use for the string's background. - * @param textColour is the colour to render the text in. - * The remaining variable arguments are unsigned integers used to fill in - * the formatiting specifiers in the format string. - */ - void lcd_draw_str(St7735Context *lcd, - uint32_t x, - uint32_t y, - LcdFont font, - const char *format, - uint32_t backgroundColour, - uint32_t textColour, - ...); - - /** - * @brief Clean the LCD display with a given colour. - * - * @param lcd a handle to the LCD to draw to - * @param color is the 32-bit colour to display. - */ - void lcd_clean(St7735Context *lcd, uint32_t color); - - /** - * @brief Draws a rectangle of a given colour on the LCD. - * - * @param lcd a handle to the LCD to draw to. - * @param x is the X-position of the top-left corner of the rectangle. - * @param y is the Y-position of the top-left corner of the rectangle. - * @param w is the width of the rectangle. - * @param h is the height of the rectangle. - * @param color is the 32-bit colour to fill the rectangle with. - */ - void lcd_fill_rect(St7735Context *lcd, - uint32_t x, - uint32_t y, - uint32_t w, - uint32_t h, - uint32_t color); - /** - * @brief Draw an image to the LCD. - * - * @param lcd a handle to the LCD to draw to. - * @param x is the X-position of the top-left corner of the image on the - * LCD. - * @param y is the Y-position of the top-left corner of the image on the - * LCD. - * @param w is the width of the image. - * @param h is the height of the image. - * @param data is the byte array containing the image data, of size at least - * of `w` * `h`, where each value is a RGB565 colour value. - */ - void lcd_draw_img(St7735Context *lcd, - uint32_t x, - uint32_t y, - uint32_t w, - uint32_t h, - const uint8_t *data); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // _HEARTBLEED_LCD_H_ diff --git a/examples/heartbleed/legacy/xmake.lua b/examples/heartbleed/legacy/xmake.lua index aa94116..4f1166a 100644 --- a/examples/heartbleed/legacy/xmake.lua +++ b/examples/heartbleed/legacy/xmake.lua @@ -2,93 +2,17 @@ -- SPDX-License-Identifier: Apache-2.0 set_project("Sonata Heartbleed Demo Legacy Version") - --- The directory containing this script -local scriptdir = os.scriptdir() --- The root of the `sonata-software` repository -local rootdir = path.join(scriptdir, '../../..') --- The directory containing the legacy baremetal build files (link script, runtime, drivers) -local legacy_dir = path.join(rootdir, "third_party/sonata-system/sw/legacy") +includes("../../legacy_drivers") set_defaultarchs("cheriot") set_defaultplat("cheriot") includes("../../../common.lua") --- Setup the GCC toolchain for building non-CHERI baremetal programs -toolchain("legacy-gcc") - set_kind("standalone") - set_toolset("cc", "riscv32-unknown-elf-gcc") - set_toolset("cxx", "riscv32-unknown-elf-g++") - set_toolset("objcopy", "riscv32-unknown-elf-objcopy") - set_toolset("ld", "riscv32-unknown-elf-gcc") - set_toolset("as", "riscv32-unknown-elf-gcc") - set_toolset("ar", "riscv32-unknown-elf-ar") - - -- Set up flags needed in the toolchain - on_load(function (toolchain) - local linkscript = path.join(legacy_dir, "link.ld") - -- Flags used for C/C++, assembly and the linker - local default_flags = { - "-march=rv32imc", - "-mabi=ilp32", - "-mcmodel=medany", - "-Wall", - "-fvisibility=hidden" - } - -- C/C++ flags - toolchain:add("cxflags", default_flags, {force = true}) - toolchain:add("cflags", default_flags) - -- Assembly flags - toolchain:add("asflags", default_flags) - -- Linker flags - toolchain:add("ldflags", default_flags) - toolchain:add("ldflags", "-ffreestanding -g -nostartfiles -T " .. linkscript) - end) -toolchain_end() - --- Helper function to define legacy firmware (running without CHERI or CHERIoT-RTOS, baremetal) --- Useful for comparing between CHERI and non-CHERI for e.g. demos/exercises -function legacy_firmware(name) - - -- Create the firmware target; remains open on return, so the caller can - -- add more rules to it as they like. - target(name) - set_kind("binary") - set_arch("rv32imc") - set_plat("ilp32") - set_languages("gnu99", "gnuxx11") - -- Add the basic C runtime to the baremetal firmware - add_files( - path.join(legacy_dir, "common/crt0.S"), - path.join(legacy_dir, "common/gpio.c"), - path.join(legacy_dir, "common/i2c.c"), - path.join(legacy_dir, "common/pwm.c"), - path.join(legacy_dir, "common/rv_plic.c"), - path.join(legacy_dir, "common/sonata_system.c"), - path.join(legacy_dir, "common/spi.c"), - path.join(legacy_dir, "common/timer.c"), - path.join(legacy_dir, "common/uart.c") - ) - after_link(convert_to_vmem) -end set_toolchains("legacy-gcc") --- Legacy-specific LCD library for using the display drivers -target("lcd_st7735_lib_am") - set_kind("static") - local lcd_dir = path.join(rootdir, "third_party/display_drivers/src") - add_files( - path.join(lcd_dir, "core/lcd_base.c"), - path.join(lcd_dir, "core/lucida_console_10pt.c"), - path.join(lcd_dir, "core/lucida_console_12pt.c"), - path.join(lcd_dir, "core/m3x6_16pt.c"), - path.join(lcd_dir, "core/m5x7_16pt.c"), - path.join(lcd_dir, "st7735/lcd_st7735.c") - ) - -- Heartbleed demo: Sending Firmware (non-CHERIoT version) legacy_firmware("heartbleed_demo_legacy") - add_deps("lcd_st7735_lib_am") + add_deps("lcd_st7735_lib_am", "legacy_drivers") add_includedirs( "../../../third_party/display_drivers/src/core/", "../../../third_party/display_drivers/src/st7735/", @@ -99,4 +23,4 @@ legacy_firmware("heartbleed_demo_legacy") "../../../third_party/sonata-system/vendor/cheriot_debug_module/tb/prog/syscalls.c" ) -- Keep the "-g3 -O0" flags as an example of a legacy flow that supports using a debugger - add_files("heartbleed.c", "../common.c", "lcd.c", {force = {cxflags = {"-g3", "-O0"}}}) + add_files("heartbleed.c", "../common.c", {force = {cxflags = {"-g3", "-O0"}}}) diff --git a/examples/automotive/legacy/adc.c b/examples/legacy_drivers/adc.c similarity index 95% rename from examples/automotive/legacy/adc.c rename to examples/legacy_drivers/adc.c index 9bdee53..7b0a50f 100644 --- a/examples/automotive/legacy/adc.c +++ b/examples/legacy_drivers/adc.c @@ -4,9 +4,9 @@ #include "adc.h" -#include "../../../third_party/sonata-system/sw/legacy/common/dev_access.h" -#include "../../../third_party/sonata-system/sw/legacy/common/sonata_system.h" #include "assert.h" +#include "dev_access.h" +#include "sonata_system.h" /** * Sets the bits of a given ADC register. Takes an ADC register, a mask of diff --git a/examples/automotive/legacy/adc.h b/examples/legacy_drivers/adc.h similarity index 100% rename from examples/automotive/legacy/adc.h rename to examples/legacy_drivers/adc.h diff --git a/examples/automotive/legacy/ksz8851.c b/examples/legacy_drivers/ksz8851.c similarity index 88% rename from examples/automotive/legacy/ksz8851.c rename to examples/legacy_drivers/ksz8851.c index e67cb60..cee3904 100644 --- a/examples/automotive/legacy/ksz8851.c +++ b/examples/legacy_drivers/ksz8851.c @@ -11,22 +11,18 @@ #include -#include "../../../third_party/sonata-system/sw/legacy/common/rv_plic.h" -#include "../../../third_party/sonata-system/sw/legacy/common/sonata_system.h" -#include "../../../third_party/sonata-system/sw/legacy/common/spi.h" -#include "../../../third_party/sonata-system/sw/legacy/common/timer.h" - -// Define our own GPIO_OUT as the version from `sonata-system` uses void -// pointer arithmetic, which clang-tidy forbids. -#define GPIO_OUT_ETH GPIO_FROM_BASE_ADDR((GPIO_BASE + GPIO_OUT_REG)) +#include "rv_plic.h" +#include "sonata_system.h" +#include "spi.h" +#include "timer.h" enum { // Ethernet IRQs - EthIntrIrq = 47, - // Ethernet GPIO Output Pins - EthCsPin = 13, - EthRstPin = 14, + EthIntrIrq = 2, + // Ethernet chip-select + EthSpiCs = 0, + EthSpiRst = 1, }; static struct Netif *ethNetif; @@ -47,11 +43,11 @@ static uint16_t ksz8851_reg_read(spi_t *spi, uint8_t reg) bytes[0] = (0b00 << 6) | (be << 2) | (reg >> 6); bytes[1] = (reg << 2) & 0b11110000; - set_output_bit(GPIO_OUT_ETH, EthCsPin, 0); + spi_set_cs(spi, EthSpiCs, 0); spi_tx(spi, bytes, 2); uint16_t val; spi_rx(spi, (uint8_t *)&val, 2); - set_output_bit(GPIO_OUT_ETH, EthCsPin, 1); + spi_set_cs(spi, EthSpiCs, 1); return val; } @@ -62,11 +58,11 @@ static void ksz8851_reg_write(spi_t *spi, uint8_t reg, uint16_t val) bytes[0] = (0b01 << 6) | (be << 2) | (reg >> 6); bytes[1] = (reg << 2) & 0b11110000; - set_output_bit(GPIO_OUT_ETH, EthCsPin, 0); + spi_set_cs(spi, EthSpiCs, 0); spi_tx(spi, bytes, 2); spi_tx(spi, (uint8_t *)&val, 2); spi_wait_idle(spi); - set_output_bit(GPIO_OUT_ETH, EthCsPin, 1); + spi_set_cs(spi, EthSpiCs, 1); } static void ksz8851_reg_set(spi_t *spi, uint8_t reg, uint16_t mask) @@ -150,7 +146,7 @@ bool ksz8851_output(struct Netif *netif, struct Fbuf *buf) // Start transmission. uint8_t cmd = 0b11 << 6; - set_output_bit(GPIO_OUT_ETH, EthCsPin, 0); + spi_set_cs(spi, EthSpiCs, 0); spi_tx(spi, &cmd, 1); uint32_t header = 0x8000 | (buf->len << 16); @@ -171,7 +167,7 @@ bool ksz8851_output(struct Netif *netif, struct Fbuf *buf) } spi_wait_idle(spi); - set_output_bit(GPIO_OUT_ETH, EthCsPin, 1); + spi_set_cs(spi, EthSpiCs, 1); // Stop QMU DMA transfer operation ksz8851_reg_clear(spi, ETH_RXQCR, StartDmaAccess); @@ -210,9 +206,9 @@ bool ksz8851_init(struct Netif *netif, uint8_t hwaddr[6]) return false; // Reset chip - set_output_bit(GPIO_OUT_ETH, EthRstPin, 0); + spi_set_cs(spi, EthSpiRst, 0); timer_delay(150); - set_output_bit(GPIO_OUT_ETH, EthRstPin, 0x1); + spi_set_cs(spi, EthSpiRst, 1); uint16_t cider = ksz8851_reg_read(spi, ETH_CIDER); #ifdef KSZ8851_DEBUG_PRINT diff --git a/examples/automotive/legacy/ksz8851.h b/examples/legacy_drivers/ksz8851.h similarity index 98% rename from examples/automotive/legacy/ksz8851.h rename to examples/legacy_drivers/ksz8851.h index 98bbdee..ab68007 100644 --- a/examples/automotive/legacy/ksz8851.h +++ b/examples/legacy_drivers/ksz8851.h @@ -12,7 +12,7 @@ #include #include -#include "../../../third_party/sonata-system/sw/legacy/common/spi.h" +#include "spi.h" struct Netif { diff --git a/examples/heartbleed/legacy/lcd.c b/examples/legacy_drivers/lcd.c similarity index 83% rename from examples/heartbleed/legacy/lcd.c rename to examples/legacy_drivers/lcd.c index 4cdf146..d0f7b44 100644 --- a/examples/heartbleed/legacy/lcd.c +++ b/examples/legacy_drivers/lcd.c @@ -80,7 +80,7 @@ int lcd_init(spi_t *spi, return 0; } -void lcd_draw_str(St7735Context *lcd, +void lcd_draw_str(void *lcd, uint32_t x, uint32_t y, LcdFont font, @@ -89,6 +89,7 @@ void lcd_draw_str(St7735Context *lcd, uint32_t textColour, ...) { +St7735Context * lcd_ = (St7735Context *) lcd; // Format the provided string char buffer[1024]; va_list args; @@ -99,49 +100,52 @@ void lcd_draw_str(St7735Context *lcd, Font stringFont; switch (font) { - case LcdFontLucidaConsole_10pt: + case LucidaConsole_10pt: stringFont = lucidaConsole_10ptFont; break; - case LcdFontLucidaConsole_12pt: + case LucidaConsole_12pt: stringFont = lucidaConsole_12ptFont; break; - case LcdFontM5x7_16pt: + case M5x7_16pt: stringFont = m5x7_16ptFont; break; default: stringFont = m3x6_16ptFont; } - lcd_st7735_set_font(lcd, &stringFont); - lcd_st7735_set_font_colors(lcd, backgroundColour, textColour); - lcd_st7735_puts(lcd, (LCD_Point){x, y}, buffer); + lcd_st7735_set_font(lcd_, &stringFont); + lcd_st7735_set_font_colors(lcd_, backgroundColour, textColour); + lcd_st7735_puts(lcd_, (LCD_Point){x, y}, buffer); } -void lcd_clean(St7735Context *lcd, uint32_t color) +void lcd_clean(void *lcd, uint32_t color) { +St7735Context * lcd_ = (St7735Context *) lcd; size_t w, h; - lcd_st7735_get_resolution(lcd, &h, &w); + lcd_st7735_get_resolution(lcd_, &h, &w); LCD_rectangle rect = {(LCD_Point){0, 0}, w, h}; - lcd_st7735_fill_rectangle(lcd, rect, color); + lcd_st7735_fill_rectangle(lcd_, rect, color); } -void lcd_fill_rect(St7735Context *lcd, +void lcd_fill_rect(void *lcd, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) { +St7735Context * lcd_ = (St7735Context *) lcd; LCD_rectangle rect = {(LCD_Point){x, y}, w, h}; - lcd_st7735_fill_rectangle(lcd, rect, color); + lcd_st7735_fill_rectangle(lcd_, rect, color); } -void lcd_draw_img(St7735Context *lcd, +void lcd_draw_img(void *lcd, uint32_t x, uint32_t y, uint32_t w, uint32_t h, const uint8_t *data) { +St7735Context * lcd_ = (St7735Context *) lcd; LCD_rectangle rect = {(LCD_Point){x, y}, w, h}; - lcd_st7735_draw_rgb565(lcd, rect, data); + lcd_st7735_draw_rgb565(lcd_, rect, data); } diff --git a/examples/legacy_drivers/lcd.h b/examples/legacy_drivers/lcd.h new file mode 100644 index 0000000..a3429c4 --- /dev/null +++ b/examples/legacy_drivers/lcd.h @@ -0,0 +1,99 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef LCD_H +#define LCD_H + +#include "../common/types.h" +#include "lcd_st7735.h" +#include "pwm.h" +#include "spi.h" + +/** + * @brief Initialise the LCD, starting and clearing the screen. + * + * @param spi contains an initialized SPI handle to use to write to the LCD. + * @param backlight contains an initialized pwm handle to use to control the + * LCD backlight. + * @param lcd is an outparam to store the initialized LCD handle. + * @param interface is an outparam storing the initialized LCD interface. + */ +int lcd_init(spi_t *spi, + pwm_t backlight, + St7735Context *lcd, + LCD_Interface *interface); + +/** + * @brief Formats and draws a string to the LCD display based upon the + * provided formatting and display information. The string can use + * formatting specifiers as defined by `vsnprintf(3)`. + * + * @param lcd a handle to the LCD to draw to. + * @param x is the X-coordinate on the LCD of the top left of the string. + * @param y is the Y-coordinate on the LCD of the top left of the string. + * @param font is the font to render the string with. + * @param format is the formatting string to write. + * @param backgroundColour is the colour to use for the string's background. + * @param textColour is the colour to render the text in. + * The remaining variable arguments are unsigned integers used to fill in + * the formatiting specifiers in the format string. + */ +void lcd_draw_str(void *lcd, + uint32_t x, + uint32_t y, + LcdFont font, + const char *format, + uint32_t backgroundColour, + uint32_t textColour, + ...); + +/** + * @brief Clean the LCD display with a given colour. + * + * @param lcd a handle to the LCD to draw to + * @param color is the 32-bit colour to display. + */ +void lcd_clean(void *lcd, uint32_t color); + +/** + * @brief Draws a rectangle of a given colour on the LCD. + * + * @param lcd a handle to the LCD to draw to. + * @param x is the X-position of the top-left corner of the rectangle. + * @param y is the Y-position of the top-left corner of the rectangle. + * @param w is the width of the rectangle. + * @param h is the height of the rectangle. + * @param color is the 32-bit colour to fill the rectangle with. + */ +void lcd_fill_rect(void *lcd, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + uint32_t color); +/** + * @brief Draw an image to the LCD. + * + * @param lcd a handle to the LCD to draw to. + * @param x is the X-position of the top-left corner of the image on the + * LCD. + * @param y is the Y-position of the top-left corner of the image on the + * LCD. + * @param w is the width of the image. + * @param h is the height of the image. + * @param data is the byte array containing the image data, of size at least + * of `w` * `h`, where each value is a RGB565 colour value. + */ +void lcd_draw_img(void *lcd, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + const uint8_t *data); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _HEARTBLEED_LCD_H_ diff --git a/examples/legacy_drivers/xmake.lua b/examples/legacy_drivers/xmake.lua new file mode 100644 index 0000000..dda1acb --- /dev/null +++ b/examples/legacy_drivers/xmake.lua @@ -0,0 +1,107 @@ +-- Copyright lowRISC Contributors. +-- SPDX-License-Identifier: Apache-2.0 + +set_project("Sonata Automotive Demo Legacy Version") + +-- The directory containing this script +local scriptdir = os.scriptdir() +-- The root of the `sonata-software` repository +local rootdir = path.join(scriptdir, '../..') +-- The directory containing the legacy baremetal build files (link script, runtime, drivers) +local legacy_dir = path.join(rootdir, "third_party/sonata-system/sw/legacy") + +-- This unnecessary boilerplate is used so that you can run `xmake -P examples/automotive/legacy` +-- and then run `xmake -P examples` without xmake complaining. If this is not included, and no +-- options are provided, then xmake will by default determine your local architecture/platform, +-- and save this in the xmake config for future runs - which is wrong for the cross-compilation +-- used in `examples/xmake.lua`, even though these are labelled as different projects. This +-- ensures the xmake config is not altered without users knowing. +set_defaultarchs("cheriot") +set_defaultplat("cheriot") + +-- Setup the GCC toolchain for building non-CHERI baremetal programs +toolchain("legacy-gcc") + set_kind("standalone") + set_toolset("cc", "riscv32-unknown-elf-gcc") + set_toolset("cxx", "riscv32-unknown-elf-g++") + set_toolset("objcopy", "riscv32-unknown-elf-objcopy") + set_toolset("ld", "riscv32-unknown-elf-gcc") + set_toolset("as", "riscv32-unknown-elf-gcc") + set_toolset("ar", "riscv32-unknown-elf-ar") + + -- Set up flags needed in the toolchain + on_load(function (toolchain) + local linkscript = path.join(legacy_dir, "link.ld") + -- Flags used for C/C++, assembly and the linker + local default_flags = { + "-march=rv32imc", + "-mabi=ilp32", + "-mcmodel=medany", + "-Wall", + "-fvisibility=hidden" + } + -- C/C++ flags + toolchain:add("cxflags", default_flags, {force = true}) + toolchain:add("cflags", default_flags) + -- Assembly flags + toolchain:add("asflags", default_flags) + -- Linker flags + toolchain:add("ldflags", default_flags) + toolchain:add("ldflags", "-ffreestanding -g -nostartfiles -T " .. linkscript) + end) +toolchain_end() + +-- Helper function to define legacy firmware (running without CHERI or CHERIoT-RTOS, baremetal) +-- Useful for comparing between CHERI and non-CHERI for e.g. demos/exercises +function legacy_firmware(name) + + -- Create the firmware target; remains open on return, so the caller can + -- add more rules to it as they like. + target(name) + set_kind("binary") + set_arch("rv32imc") + set_plat("ilp32") + set_languages("gnu99", "gnuxx11") + -- Add the basic C runtime to the baremetal firmware + add_files( + path.join(legacy_dir, "common/crt0.S"), + path.join(legacy_dir, "common/gpio.c"), + path.join(legacy_dir, "common/i2c.c"), + path.join(legacy_dir, "common/pwm.c"), + path.join(legacy_dir, "common/rv_plic.c"), + path.join(legacy_dir, "common/sonata_system.c"), + path.join(legacy_dir, "common/spi.c"), + path.join(legacy_dir, "common/timer.c"), + path.join(legacy_dir, "common/uart.c") + ) +end + +set_toolchains("legacy-gcc") + +-- Legacy-specific LCD library for using the display drivers +target("lcd_st7735_lib_am") + set_kind("static") + local lcd_dir = path.join(rootdir, "third_party/display_drivers/src/") + add_files( + path.join(lcd_dir, "core/lcd_base.c"), + path.join(lcd_dir, "core/lucida_console_10pt.c"), + path.join(lcd_dir, "core/lucida_console_12pt.c"), + path.join(lcd_dir, "core/m3x6_16pt.c"), + path.join(lcd_dir, "core/m5x7_16pt.c"), + path.join(lcd_dir, "st7735/lcd_st7735.c") + ) + add_includedirs( + path.join(lcd_dir,"st7735"), + path.join(lcd_dir,"core"), + {public = true} + ) + +target("legacy_drivers") + set_kind("static") + add_files("ksz8851.c", "lcd.c", "adc.c", "ksz8851.c") + add_includedirs( + "./", + path.join(legacy_dir,"common"), + {public = true} + ) + add_deps("lcd_st7735_lib_am") diff --git a/libraries/lcd.hh b/libraries/lcd.hh index d226c61..347d380 100644 --- a/libraries/lcd.hh +++ b/libraries/lcd.hh @@ -14,12 +14,12 @@ namespace sonata::lcd { extern "C" { -#include "../third_party/display_drivers/src/core/lcd_base.h" -#include "../third_party/display_drivers/src/core/lucida_console_10pt.h" -#include "../third_party/display_drivers/src/core/lucida_console_12pt.h" -#include "../third_party/display_drivers/src/core/m3x6_16pt.h" -#include "../third_party/display_drivers/src/core/m5x7_16pt.h" -#include "../third_party/display_drivers/src/st7735/lcd_st7735.h" +#include "core/lcd_base.h" +#include "core/lucida_console_10pt.h" +#include "core/lucida_console_12pt.h" +#include "core/m3x6_16pt.h" +#include "core/m5x7_16pt.h" +#include "st7735/lcd_st7735.h" } void __cheri_libcall lcd_init(LCD_Interface *, St7735Context *, diff --git a/libraries/xmake.lua b/libraries/xmake.lua index b039b8e..e4d4ce4 100644 --- a/libraries/xmake.lua +++ b/libraries/xmake.lua @@ -11,7 +11,7 @@ library("lcd") add_files("../third_party/display_drivers/src/st7735/lcd_st7735.c") add_files("lcd.cc") add_includedirs( - "../third_party/display_drivers/core/src/", {public = true} + "../third_party/display_drivers/src/", {public = true} ) library("sense_hat")