Basic process for adding a new display driver

1. Introduction

This document explains the process of adding internal and external displays for Sichuang Technology, using SF32LB52-LCD_N16R8 as an example.
Internal display: Screens that can be selected via menuconfig across all projects.
External display: Screen drivers added under specific projects.
This article briefly demonstrates how to add a new display driver module.
Display Parameters:

  • Driver IC: st77989
  • Interface: DBI
  • Resolution: 480 × 320

Reference Document

2. General Configuration

Display driver configuration follows a universal process, applicable to both internal and external displays.
Main configurations include interface setup, timing settings, and initialization.
Reference Document

2.1 Timing & Registers

Macro definitions for timing and registers, which can be customized as needed.

2.2 THE_LCD_ID

This value can be custom-defined and is primarily used for screen presence detection.

2.3 LCDC Configuration

lcdc_int_cfg is used to configure screen interface, color format, timing, and related parameters.

static LCDC_InitTypeDef lcdc_int_cfg =
{
    .lcd_itf = LCDC_INTF_DBI_8BIT_B, // 8-bit DBI interface mode
    .freq = 12000000, // 12 MHz
    .color_mode = LCDC_PIXEL_FORMAT_RGB565, // RGB565 color format

    .cfg = {
        /* For different interfaces, cfg parameters can vary. Refer to LCDC_InitTypeDef structure in bf_hal_lcdc.h */
        .dbi = {
            .syn_mode = HAL_LCDC_SYNC_DISABLE, // HAL_LCDC_SYNC_VER, // HAL_LCDC_SYNC_DISABLE,
            .vsyn_polarity = 0,
            .vsyn_delay_us = 0,
            .hsyn_num = 0,
        },
    },

};

2.4 Display Initialization Configuration

LCD_Init() performs initialization of screen registers. Specific configurations should refer to the display driver’s datasheet.

static void LCD_Init(LCDC_HandleTypeDef *hlcdc)
{
    uint8_t parameter[15];

    /* Initialize st7789_dbi low level bus layer ----------------------------------*/
    memcpy(&hlcdc->Init, &lcdc_int_cfg, sizeof(LCDC_InitTypeDef));
    if (!te_enabled)
    {
        hlcdc->Init.cfg.spi.syn_mode = HAL_LCDC_SYNC_DISABLE;
    }
    HAL_LCDC_Init(hlcdc);

    BSP_LCD_Reset(1);
    LCD_DRIVER_DELAY_MS(1);
    BSP_LCD_Reset(0); // Reset LCD
    HAL_Delay_us(20);
    BSP_LCD_Reset(1);
    LCD_DRIVER_DELAY_MS(50);

    // remark
    // parameter[0] = 0x20;
    // LCD_WriteReg(hlcdc, 0xE9, parameter, 1);

    /* Sleep Out Command */
    LCD_WriteReg(hlcdc, 0x11, (uint8_t *)NULL, 0);
    /* Wait for 120ms */
    LCD_DRIVER_DELAY_MS(120);

    parameter[0] = 0x40; // A0
    LCD_WriteReg(hlcdc, 0x36, parameter, 1);

    parameter[0] = 0x05;
    LCD_WriteReg(hlcdc, 0x3A, parameter, 1);

    parameter[0] = 0x0C;
    parameter[1] = 0x0C;
    parameter[2] = 0x00;
    parameter[3] = 0x33;
    parameter[4] = 0x33;
    LCD_WriteReg(hlcdc, 0xB2, parameter, 5);

    ...

    parameter[0] = 0x00;
    parameter[1] = 0x00;
    parameter[2] = 0x01;
    parameter[3] = 0x3F;
    LCD_WriteReg(hlcdc, 0x2A, parameter, 4);
#endif
    LCD_WriteReg(hlcdc, 0x20, (uint8_t *)NULL, 0);
    /* clear gram */
    HAL_LCDC_Next_Frame_TE(hlcdc, 0);
    HAL_LCDC_SetROIArea(hlcdc, 0, 0, THE_LCD_PIXEL_WIDTH - 1, THE_LCD_PIXEL_HEIGHT - 1);
    HAL_LCDC_LayerSetFormat(hlcdc, HAL_LCDC_LAYER_DEFAULT, LCDC_PIXEL_FORMAT_RGB565);
    HAL_LCDC_LayerDisable(hlcdc, HAL_LCDC_LAYER_DEFAULT);
    HAL_LCDC_SetBgColor(hlcdc, 0, 0, 0);
    HAL_LCDC_SendLayerData2Reg(hlcdc, REG_WRITE_RAM, 1);
    HAL_LCDC_LayerEnable(hlcdc, HAL_LCDC_LAYER_DEFAULT);
    LCD_WriteReg(hlcdc, 0x29, (uint8_t *)NULL, 0);
}

2.5 Driver Callback Functions

Callback Function Reference

2.6 Screen Registration Declaration

Image Description

2.7 Script Link – SConscript

from building import *

cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd + '/../common', cwd]
group = DefineGroup('Drivers', src, depend = ['LCD_USING_ST77989_8080'], CPPPATH = CPPPATH)
/*-------------------------------------- Modify to custom screen name to avoid conflicts with other screens */
Return('group')

3. External Process

3.1 Project Selection

First, select a suitable base project. Here we choose the rt_driver project recommended in the documentation.

3.2 Peripherals Creation

Create a peripherals folder under rt_driver to place user devices. You may also refer directly to SDK/customer/peripherals.
Then create the display driver chip code and necessary script files in this directory, as shown below:

3.3 SConscript – Linking Script 1

No modification required; simply add the code into the project build script.

# for module compiling
import os
from building import *

cwd  = GetCurrentDir()
objs = []
list = os.listdir(cwd)
if GetDepend(['BSP_USING_RTTHREAD']):
    if not GetDepend(['BSP_USING_PC_SIMULATOR']):
        if not GetDepend(['BSP_USING_BUILTIN_LCD']):
            # include all subfolders
            for d in list:
                path = os.path.join(cwd, d)
                if os.path.isfile(os.path.join(path, 'SConscript')):
                    objs = objs + SConscript(os.path.join(d, 'SConscript'))
    
Return('objs')

3.4 Kconfig.proj

Add the relevant display driver to menuconfig via this script.
This script is located in the project’s corresponding project directory.
Code configuration details are as follows:
Configuration parameters reference

# APP specific configuration.

config CUSTOM_MEM_MAP
    bool 
    select custom_mem_map
    default y

comment "------------Project configuration-----------"

if !BSP_USING_BUILT_LCD

<!-- Add display driver -->
config LCD_USING_ST7796_8080
    bool
    default n

<!-- menuconfig option -->
choice
        prompt "Custom LCD driver"
        default LCD_TFT_ST7796_8080            <!-- Default display driver -->

        config LCD_TFT_ST7796_8080                <!--  -->
            bool "4.0 rect DBI Video TFT LCD(480x320)"   <!-- Display name shown in menuconfig -->
            select LCD_USING_ST7796_8080                 <!-- Selected driver must match registration -->
            select BSP_LCDC_USING_DBI                    <!-- Screen interface type, explained earlier -->

    endchoice

<!-- Horizontal resolution -->
    config LCD_HOR_RES_MAX
        int
        default 480 if LCD_TFT_ST7796_8080
<!-- Vertical resolution -->
    config LCD_VER_RES_MAX
        int
        default 320 if LCD_TFT_ST7796_8080
<!-- DPI value from datasheet or calculation -->
    config LCD_DPI
        int
        default 315 if LCD_TFT_ST7796_8080

endif

3.5 menuconfig Selection

After completing Kconfig.proj, the option becomes available in menuconfig.
The following options will appear in menuconfig.
When using an external display, disable the original built-in display driver, or add # CONFIG_BSP_USING_BUILTIN_LCD is not set in proj.conf.


Disable original display driver

4. Internal Process

Unlike external displays, internal display drivers are added under SDK/customer/peripherals, which already contains various built-in driver codes.
Place the common display driver code in this folder, then proceed with further configuration.

4.1 Kconfig Configuration

This file is located in SDK/customer/peripherals.
Add driver declarations here — including touch and backlight drivers.
Ensure the declared names match those registered in the driver code.


4.2 Kconfig_lcd Configuration

This file is located in SDK/customer/boards.
The configuration added here is the same as in the external process’s Kconfig.proj.
Add screen options and parameters.





4.3 menuconfig Selection

Open menuconfig. A new screen option (the one you configured) will appear among the existing LCD options. Select it and compile.

5. Expected Results

After completing configuration and ensuring correct driver implementation, successful compilation and flashing should result in the following:
The screen ID can be read correctly, logs show no read/write timeouts, and the display functions normally.