From 188e7fcf29e51d2f2727530930cde739b6300028 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 3 Jan 2025 20:03:08 +0100 Subject: [PATCH] docs: add README with information about the project --- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..1edfa53 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# Image viewer - Low level USB device on STM32H747 +Author: František Boháček + +This project focuses on making a low level usb device - ie. working directly with the registers, as opposed to HALs. +The goal is to make an application using CDC ACM to send images to the device, and show them on an LCD display connected +through MIPI DSI interface. For usb USB OTG peripheral may be used, in high-speed mode, for the display DSI and LTDC peripherals +can be utilized. To fit whole framebuffer in memory, external SDRAM present on the board is used. + +Because the focus of this work has been mostly on the USB OTG device, I used https://github.com/stm32-rs/stm32h7xx-hal a lot as inspiration, +some parts may even be 'direct translation'. +when writing SDRAM interfacing and DSI controller. It was very challenging to find information about the interface and display otherwise. +Luckily this hal library has even examples for the STM32H747-DISCO board, so the individual display configuration and commands required +to bring up the display, are present as well. + +## Project Structure + +The root project folder +contains folders `linux_app`, where Rust Linux application resides, +with typical structure for Rust crates, and `firmware`, +where the STM32 firmware is located. + +As for `firmware` structure: +- `devices` - Folder with support for various devices. It contains linker scripts, isr definitions, +as well as a startup file that ensures bss is nulled, .data contains initialized code in ram, and calls main. +- `include` - headers +- `libs` - Third-party libraries. Specifically CMSIS for register definitions for both Cortex-M and STM32H7 +- `src` - C source code +- `tests` - Tests runnable on Linux. Initially the author wanted to make more tests, where parts of the device +would be simulated. But afterall there was no need for this, and only one test was made. Specifically, +a test for seeing contents of device descriptor. The test utilizes that functions for sending data are used, +and they are replaced by code that just prints to a file instead of changing chip memory. + +## USB device + +The usb device support is split across multiple files. `usb.h` contains +USB protocol structures, and functions for general USB peripheral operations, +like sending or receiving specific data. `usb_device.h` contains functions specific +for initializing the device, for handling interrupts, and setup. +`usb_device_cdc.h` contains implementation of CDC ACM. + +Care has been taken to properly abstract the usb send, reception, from +setup and that from application layer. This means that it should be trivial +to add support for other application layers besides USB CDC. + +Each application layer has its `vtable` consisting of pointers to +a few functions that will be called from the 'controller' usb device when +the device is enumerated. For example callbacks with new data available +in fifo or setting up application-specific endpoints. + +Often the usb function implementations implement non-blocking aproach, +where if the function would have to spin loop, it will just return +WOULD_BLOCK. This ensures that no functions block, and it can be decided +from upper layers what to do about that, like when to retry this operation. + +cdc acm implementation leverages queue for reception of data. It saves +the data to queue, and then the application can receive the data from +the queue. This is quite handy as the application doesn't need to implement +some kind of a callback, but rather can just spin loop with `cdc_data_receive`. +The data are put to the queue in usb interrupt. + +This is handy for smaller amounts of data, but for large amounts of data +this has proven ineffective. For example, to upload a whole image (~ 2 MB), +it could take even 30 seconds for an image to be received. The issue +would arise every time size of the queue has been hit. Since at that point, +the queue will fill completely. Then the app will read 512 bytes, and +the queue will again get filled very quickly. So only last 512 bytes +are causing this issue. To mitigate this issue, there is another +possibility to receive data. + +The cdc application implements two possible callbacks, +one being a callback that will receive the data without putting them to queue, +but still, the data are first read to a variable, and have to be copied to framebuffer +afterwards. Another possibility is to return a pointer that will say where to write the +data to. In the first case it's possible to read only some data, but in the second +the application always has to receive everything in the specified buffer. + +The final application combines these two mechanisms. First, character `i` is detected +through the callback that receives copied data, and the data are copied to framebuffer. +Following transmissions will instead be handled by the callback that returns pointer +to where to save the data, and the data will be put to the framebuffer itself from +the peripheral fifo directly! + +## Display + +Although the display driving is made out of two peripherals, +support for both is contained in one file (`display.h`) and in the same functions. +Additionally there is `otm8009a.h` that defines how to initialize the display +used on the board. + +LTDC supports two modes, video mode and adapted command mode. In video mode +data are continuously streamed to the display from framebuffer inside of RAM. +In adapted command mode the application decides when to send data. Since +the application is not updating the framebuffer, adapted command mode +has been chosen. Although the display code contains support code for video +mode, it has never been tried on hardware. + +## Usage + +## Building and flashing + +For building, makefile is available. +It uses gcc cross toolchain for arm-none-eabi target. +To build the application, run `make` in `firmware` folder. +To flash it, `make flash` may be used. It uses `openocd` +to flash the program. + +### Communication protocol on top of CDC ACM + +There is a simple ASCII based protocol supporting a few simple commands. + +r - turn screen to all red +g - turn screen to all green +b - turn screen to all blue +l - toggle led +i - Upload an image and show it on the display. The IMG is expected to be in RGB888 format, ie. first three bytes show what's on the first pixel, +first byte is intensity of R, second G, third B. The image is written row by row. + +### Application + +The computer application has been made in Rust. +It is working on Linux, but nothing should be stopping +it from working on Windows as well. +The application is very simple, it accepts two cli arguments, +the first one is path to the image to upload. The second one is +path to TTY, default is /dev/ttyACM1. +The application will upload the image specified, and exit. -- 2.48.1