|
| 1 | +--- |
| 2 | +title: MaixCAM MaixPy SPI LCD Screen |
| 3 | +update: |
| 4 | + - date: 2024-12-02 |
| 5 | + author: 916BGAI |
| 6 | + version: 1.0.0 |
| 7 | + content: Initial document |
| 8 | +--- |
| 9 | + |
| 10 | +## Introduction |
| 11 | + |
| 12 | +`MaixCAM` is equipped with three hardware SPI interfaces, allowing you to connect and drive an LCD screen via the SPI interface. |
| 13 | + |
| 14 | +> Currently, only hardware SPI is supported for driving the LCD screen, and it requires modification to the Linux kernel. Software SPI is not supported. |
| 15 | +
|
| 16 | +> **Note:** Reading this document requires a certain level of knowledge in kernel compilation, kernel configuration, and kernel driver development. |
| 17 | +
|
| 18 | +## Using the ST7789 Screen |
| 19 | + |
| 20 | +This section uses the LCD screen driven by `ST7789` as an example. |
| 21 | + |
| 22 | +### Get the LicheeRV-Nano-Build Source Code |
| 23 | + |
| 24 | +The base system used by `MaixCAM` is [https://github.com/sipeed/LicheeRV-Nano-Build](https://github.com/sipeed/LicheeRV-Nano-Build). |
| 25 | + |
| 26 | +First, pull the latest source code and follow the instructions in the [README](https://github.com/sipeed/LicheeRV-Nano-Build/blob/main/README.md) to build the system. |
| 27 | + |
| 28 | +### Modify the Linux Kernel |
| 29 | + |
| 30 | +First, modify the kernel configuration to enable `FB_TFT` support. You can execute `menuconfig_kernel` in the root directory of LicheeRV-Nano-Build, then use the text-based menu interface to configure it. The configuration option is located at: |
| 31 | + |
| 32 | +`Device Drivers -> Staging drivers -> Support for small TFT LCD display modules` |
| 33 | + |
| 34 | +Select the driver for the screen you are using; in this case, choose the `ST7789` driver, and compile it as a kernel module: |
| 35 | + |
| 36 | +`<M> FB driver for the ST7789 LCD Controller` |
| 37 | + |
| 38 | +> Alternatively, you can directly modify the configuration file `build/boards/sg200x/sg2002_licheervnano_sd/linux/sg2002_licheervnano_sd_defconfig` |
| 39 | +> by adding `CONFIG_FB_TFT=y` and `CONFIG_FB_TFT_ST7789=m`. |
| 40 | +
|
| 41 | +### Modify the Device Tree |
| 42 | + |
| 43 | +Modify the device tree file `build/boards/sg200x/sg2002_licheervnano_sd/dts_riscv/sg2002_licheervnano_sd.dts`. |
| 44 | + |
| 45 | +```c |
| 46 | +&spi2 { |
| 47 | + status = "okay"; |
| 48 | + /delete-node/ spidev@0; |
| 49 | + st7789: st7789@0{ |
| 50 | + compatible = "sitronix,st7789"; |
| 51 | + reg = <0>; |
| 52 | + status = "okay"; |
| 53 | + spi-max-frequency = <80000000>; |
| 54 | + spi-cpol; |
| 55 | + spi-cpha; |
| 56 | + rotate = <90>; |
| 57 | + fps = <60>; |
| 58 | + rgb; |
| 59 | + buswidth = <8>; |
| 60 | + dc = <&porte 20 GPIO_ACTIVE_HIGH>; |
| 61 | + reset = <&porte 21 GPIO_ACTIVE_LOW>; |
| 62 | + debug = <0>; |
| 63 | + }; |
| 64 | +}; |
| 65 | +``` |
| 66 | +This example uses `SPI2`. Since the Wi-Fi module reuses the `SPI2` pins for `SDIO`, we need to modify the pin multiplexing. The method for modification is shown in the example below. After modification, the Wi-Fi functionality will be unavailable. |
| 67 | + |
| 68 | +After modifying the device tree, recompile the image and generate the MaixCAM-compatible image following the instructions in the [Compiling a System for MaixCAM](https://wiki.sipeed.com/maixpy/doc/en/pro/compile_os.html) guide. |
| 69 | + |
| 70 | +### Test the Screen |
| 71 | + |
| 72 | +maixpy example: |
| 73 | + |
| 74 | +```python |
| 75 | +from maix import pinmap, display, image, app |
| 76 | +import subprocess |
| 77 | + |
| 78 | +try: |
| 79 | + result = subprocess.run(['lsmod'], capture_output=True, text=True, check=True) |
| 80 | + if "aic8800_bsp" in result.stdout: |
| 81 | + subprocess.run(['rmmod', 'aic8800_fdrv'], check=True) |
| 82 | + subprocess.run(['rmmod', 'aic8800_bsp'], check=True) |
| 83 | + else: |
| 84 | + print(f"aic8800 module is not currently loaded, skipping remove.") |
| 85 | +except Exception as e: |
| 86 | + print(e) |
| 87 | + |
| 88 | +pinmap.set_pin_function("P18", "SPI2_CS") |
| 89 | +pinmap.set_pin_function("P22", "SPI2_MOSI") |
| 90 | +pinmap.set_pin_function("P23", "SPI2_SCK") |
| 91 | +pinmap.set_pin_function("P20", "GPIOP20") |
| 92 | +pinmap.set_pin_function("P21", "GPIOP21") |
| 93 | + |
| 94 | +try: |
| 95 | + result = subprocess.run(['lsmod'], capture_output=True, text=True, check=True) |
| 96 | + if "fb_st7789" in result.stdout: |
| 97 | + print(f"module is already loaded, skipping loading.") |
| 98 | + else: |
| 99 | + subprocess.run(['insmod', '/mnt/system/ko/fb_st7789.ko'], check=True) |
| 100 | + print(f"load fb_st7789 success.") |
| 101 | +except Exception as e: |
| 102 | + print(e) |
| 103 | + |
| 104 | +disp = display.Display(device="/dev/fb0") |
| 105 | +print("display init done") |
| 106 | +print(f"display size: {disp.width()}x{disp.height()}") |
| 107 | + |
| 108 | +y = 0 |
| 109 | +while not app.need_exit(): |
| 110 | + img = image.Image(disp.width(), disp.height(), image.Format.FMT_RGB888) |
| 111 | + img.draw_rect(0, y, image.string_size("Hello, MaixPy!", scale=2).width() + 10, 80, color=image.Color.from_rgb(255, 0, 0), thickness=-1) |
| 112 | + img.draw_string(4, y + 4, "Hello, MaixPy!", color=image.Color.from_rgb(255, 255, 255), scale=2) |
| 113 | + |
| 114 | + disp.show(img) |
| 115 | + |
| 116 | + y = (y + 1) % disp.height() |
| 117 | +``` |
| 118 | +- First, remove the aic8800 driver module to prevent it from occupying the SDIO bus, which could interfere with the screen driver. |
| 119 | +- Modify the pin multiplexing, mapping the corresponding pins to SPI functions. For detailed instructions on how to modify the pin multiplexing using pinmap, refer to [Using PINMAP in MaixCAM](https://wiki.sipeed.com/maixpy/doc/en/peripheral/pinmap.html). |
| 120 | +- Then, use `insmod` to load the screen driver module. Check the system logs to confirm that the driver has been successfully loaded. You can also find the generated `fb0` device in the /dev directory. |
| 121 | + |
| 122 | +```bash |
| 123 | +[ 1029.909582] fb_st7789: module is from the staging directory, the quality is unknown, you have been warned. |
| 124 | +[ 1029.911792] fb_st7789 spi2.0: fbtft_property_value: buswidth = 8 |
| 125 | +[ 1029.911814] fb_st7789 spi2.0: fbtft_property_value: debug = 0 |
| 126 | +[ 1029.911828] fb_st7789 spi2.0: fbtft_property_value: rotate = 90 |
| 127 | +[ 1029.911842] fb_st7789 spi2.0: fbtft_property_value: fps = 60 |
| 128 | +[ 1030.753696] graphics fb0: fb_st7789 frame buffer, 320x240, 150 KiB video memory, 4 KiB buffer memory, fps=62, spi2.0 at 80 MHz |
| 129 | +``` |
| 130 | + |
| 131 | +- Using the screen is straightforward. Simply specify the corresponding `fb` device when creating the `Display` instance. After that, you can use the `SPI` screen in the usual way ([MaixPy Screen Usage](https://wiki.sipeed.com/maixpy/doc/en/vision/display.html)). |
| 132 | + |
| 133 | +```python |
| 134 | +disp = display.Display(device="/dev/fb0") |
| 135 | +``` |
| 136 | +## Notes |
| 137 | +### Screen Timing Issues |
| 138 | +The initialization timing for different screens may vary. For example, the `ST7789` includes different versions such as `ST7789V1` and `ST7789V2`, each with potentially different initialization timings. The drivers in the [LicheeRV-Nano-Build](https://github.com/sipeed/LicheeRV-Nano-Build) repository cannot guarantee that they will work properly with every st7789 screen. You can contact the supplier to obtain the specific initialization sequence for your screen and modify the `init_display` function in `LicheeRV-Nano-Build/linux_5.10/drivers/staging/fbtft/fb_st7789.c`. |
| 139 | + |
| 140 | +### Pin Multiplexing |
| 141 | +When using `pinmap` to set pin multiplexing, ensure that it matches the pin configuration in the device tree. Generally, the `dc` and `reset` pins for SPI screens are not hardware-bound, so you can specify them arbitrarily in the device tree. Simply choose pins that are not in use on the `MaixCAM` board, and then map them to GPIO functions using `pinmap`. |
| 142 | + |
| 143 | +### Drive Other Screens |
| 144 | +Currently, the `fb` device has tested the `st7789` screen driver. There are other screen drivers available for testing in `linux_5.10/drivers/staging/fbtft`. If you encounter any issues, feel free to submit a `commit` or a `PR` to contribute. |
0 commit comments