# 1 Common LCD Debugging Issues
## 1.1 Green Stripe on the Right Side of the LCD Display
As shown in the following figure:

Confirm the modifications according to the following figure:

## 1.2 Distorted LCD Display
Debug method, as shown below:

1. After jlink is connected, type h to stop the cpu.
2. In the cmd window, go to this directory and execute \release\tools\crash_dump_analyser\script\save_ram_a0.bat to save the memory information.
3. The dumped memory information is as follows:

4. Run the release\tools\crash_dump_analyser\simarm\t32marm.exe tool to restore the hcpu context, and select load_memory_butterfli_hcpu.cmm to perform the restore operation.

Then, when it pops up again and asks you to select the bin at address 0x20000000, select hcpu_ram.bin.

When it pops up and asks you to select the bin at address 0x60000000, select psram.bin, as shown in the following figure:

When it pops up and asks you to select the *.axf file, select the compiled hcpu *.axf file.
The corresponding path for the Wachdemo project is: example\watch_demo\project\ec-lb551\build\bf0_ap.axf
As shown in the following figure:

After restoring the context, open the Var->watch window, enter the drv_lcd variable to search for, and then add it to the watch window for viewing.

Expand the drv_lcd variable in the watch window and you will find that the window size configured for the LCD does not match the LCD driver.

After modifying the configuration in the rtconfig.h file, the screen corruption issue is resolved.
```c
#define LCD_HOR_RES_MAX 454
#define LCD_VER_RES_MAX 454
```
The corresponding macros for the littleVGL display setting registers also need to be changed to match the LCD size.
```c
#define LV_HOR_RES_MAX 454
#define LV_VER_RES_MAX 454
#define LV_DPI 315
#define LV_FB_LINE_NUM 454
```
## 1.3 First Frame Distortion on TFT Display During Power-On or Wake-Up
Screen corruption occurs when the display is turned on and the data in the screen GRAM is incorrect. From the boot display logic,
data should be sent first, then display_on should be performed on the chip, and then the backlight should be turned on. If the sequence is wrong, the first frame will be corrupted. You can also send a black screen after initialization is complete. If the screen driver IC supports writing a register to make the output black, use the method of writing the screen register first.
Alternatively, use the following method:
Refer to the method used by the SPD2012 driver in the code. Before turning on the screen, first send black screen data through the LCDC background to clear the GRAM inside the screen.

## 1.4 Display Does Not Light Up Even Though Initialization Read/Write Operations Are Normal
For each screen IC, the delay between power-on and register initialization varies. If the delay from screen power-on in the BSP_Power_Up function to LCD register initialization init is insufficient, the registers cannot be configured during initialization, causing the LCD driver to fail to start.
Solution:
Then, at the beginning of LCD register initialization init, add a certain delay according to the requirements of the screen driver IC.

The following lists the three delay durations that need attention during screen initialization. If the delays are too long, the screen will light up more slowly. When reducing the delays, be sure to follow the screen IC datasheet.
```c
static void SPD2010_Init_SPI_Mode(LCDC_HandleTypeDef *hlcdc)
{
uint8_t parameter[14];
int i, j;
memcpy(&hlcdc->Init, &lcdc_int_cfg, sizeof(LCDC_InitTypeDef));
HAL_LCDC_Init(hlcdc);
BSP_LCD_Reset(0);//Reset LCD
rt_thread_delay(1); //依据屏驱IC规格书配置此延时
BSP_LCD_Reset(1);
/* Wait for 50ms */
rt_thread_delay(50); //依据屏驱IC规格书配置此延时
for (i = 0; i < sizeof(lcd_init_cmds) / MAX_CMD_LEN; i++)
{
SPD2010_WriteReg_I(hlcdc, lcd_init_cmds[i][0], (uint8_t *)&lcd_init_cmds[i][2], lcd_init_cmds[i][1]);
HAL_Delay_us(10);
}
rt_thread_delay(50); //依据屏驱IC规格书配置此延时
SPD2010_WriteReg(hlcdc, 0x29,(uint8_t *)NULL, 0);
}
```
## 1.5 How to Export from the Framebuffer to Check Whether the Image Is Normal?
a. Find the address of the buf1_1 global variable from the *.map file in the build directory, as shown in the following figure:
Alternatively, the address of the buf1_1 global variable can also be found in Ozone.

b. Use jlink to save the memory values as a bin file.
savebin
For example: savebin D:\sifli\customer\weizhang\lcd\1.bin 0x20036940 0x52e20
This panel uses rgb565 format, which occupies 2 bytes. With a 412x412 resolution, the length is 412x412x2=339488=0x52E20
c. Use the Python tool tools\bin2bmp\bin2bmp.py to convert the bin file to bmp image format.
The command is as follows:
Old command:
python bin2bmp.py
For example: for a 412x412 panel, 1.bin is saved from the base address, so no offset is required.
```
python bin2bmp.py 1.bin 412 412 16 0
```
New command:
python bin2bmp.py
```
python bin2bmp.py 1.bin rgb565 412 412 0
```
Supported color formats: a8/rgb565/rgb888/argb8888/rgba8888
d. The jlinkbin2bmp.py script has been added. When jlink is connected, it can export a bmp image in one step from savebin to conversion, using the following command:
```
python jlinkbin2bmp.py SF32LB55X rgb565 412 412 2004E3E0
```
e. For the latest usage instructions, refer to the tools\bin2bmp\readme.txt file.
## 1.6 Common Assert Crashes in the LCD Driver
Assert occurs:
```
Assertion failed at function:async_send_timeout_handler, line number:876 ,(0)
```

Root cause:
The macro LCD_GC9B71_VSYNC_ENABLE is enabled, which enables the TE function. After the LCD sends data, it waits for the TE signal before refreshing the screen. The LCD TE signal never arrives, causing a timeout Assert.
Common case 1:
This assert occurs during the OTA process because the default IO for the motor is PA44, while in this project PA44 is the lcd reset signal. Entering dfu starts the motor, causing the LCD to be reset unexpectedly. The LCD then no longer outputs a TE signal, and the system crashes when dfu refreshes the screen.
Common case 2:
Crash when waking by key after the screen is turned off
The symptom is that after the screen is turned off, pressing a key to wake it up causes an assert, and the system stops at the assert while waiting for TE during screen refresh.
Root cause:
After initializing the LCD panel, the initialization delay inside TP is too long, with a 100ms delay. The customer uses the rt_thread_mdelay(100); delay function, during which Hcpu enters the IDLE process and goes to sleep.
After the timer expires, it wakes up from standby. At this point, the LCD has been powered off and has not been initialized, so there is no TE signal. The previous screen refresh then continues, causing a crash.
Solution:
In the driver, do not use the rt_thread_mdelay(10); delay function.
Use the following instead: HAL_Delay(100); or HAL_Delay_us(10); functions.
The rt_thread_mdelay function performs a thread switch. After switching to the Idle process, the system goes to sleep.
The HAL_Delay function is a busy-wait loop and will not switch to the Idle process.
## 1.7 LCD Distorted Display and Frozen Display Issues During ESD Testing
Solution approach: Determine whether the display is normal using the TE output signal or register values of the display driver IC. If it is abnormal, reinitialize the LCD.
1. If there is no TE signal output when the LCD display is corrupted or stuck and the system crashes,
Solution:
In the drv_lcd.c file, in the TE wait timeout function async_send_timeout_handler:
Use the code in the red box below to reinitialize the LCD:
```c
drv_lcd.assert_timeout = 3; //配置刷屏超时情况下是assert、不做操作还是重初始化LCD
```

2. If there is TE signal output when the LCD display is corrupted, the LCD register values need to be read to determine the corrupted-display state.
Solution:
- Follow solution 1 above to first enable the display-refresh timeout code for reinitializing the LCD.
- In the XXXX_WriteMultiplePixels screen-send function of the LCD driver,
add reading of the LCD register values. If an incorrect register value is found, return without refreshing the screen.
At this time, because the screen-send operation is not executed, the screen refresh enters RT_ETIMEOUT. The LCD is reinitialized according to the `drv_lcd.assert_timeout` configuration, as shown below:
The LCD registers are checked 3 times. If the register values are incorrect all 3 times, the LCD is considered abnormal, and the function returns to trigger a screen-refresh timeout and reinitialize the LCD.

```c
void SH8601Z_WriteMultiplePixels(LCDC_HandleTypeDef *hlcdc, const uint8_t *RGBCode, uint16_t Xpos0, uint16_t Ypos0, uint16_t Xpos1, uint16_t Ypos1)
{
uint32_t size;
static uint32_t err_num=0;
//DEBUG_PRINTF("SH8601Z: WriteMultiplePixels %d,%d,%d,%d \n",Xpos0, Ypos0, Xpos1, Ypos1);
SH8601Z_ALIGN2(Xpos0);
SH8601Z_ALIGN2(Ypos0);
SH8601Z_ALIGN1(Xpos1);
SH8601Z_ALIGN1(Ypos1);
uint32_t data;
data = SH8601Z_ReadData(hlcdc, 0x0A, 1) & 0xff;
if(0x9c != data)
{
if(err_num<3)
{
err_num++;
rt_kprintf("\nSH8601Z_Read0A:0x%x,err_num:%d \n", data,err_num);
}
else
{
rt_kprintf("reinit SH8601Z \n");
err_num=0;
return; //return To trigger drv_lcd timeout and reinit lcd
}
}
else
{
err_num=0;
}
HAL_LCDC_LayerSetData(hlcdc, HAL_LCDC_LAYER_DEFAULT, (uint8_t *)RGBCode, Xpos0, Ypos0, Xpos1, Ypos1);
HAL_LCDC_SendLayerData2Reg_IT(hlcdc, SH8601Z_WRITE_RAM, 1);
}
```
## 1.8 Distortion in Power-On/Power-Off Animation or Charging Image Display
The display abnormality is shown below:


Root cause:
This is a pixel alignment issue. A multiple of 4 pixels must be sent to the panel. As shown in the datasheet of the panel driver IC below, the number of pixels sent to the panel must be a multiple of 4:

Solution:
1. Modify the image: Ensure that images sent to the full screen, such as the boot animation and charging images, have an even-numbered resolution. For example, the size shown below is 161x80. After correcting it to 160x80, the image distortion issue is resolved.

2. In the code, align to 4 pixels. For example, if the image above is 161x80, change it to 164x80 and fill the additional 3 pixels with the background color.
Alternatively, drop one pixel to make it 160x80.
## 1.9 Issue Where Display QSPI Cannot Read the Display ID
Currently, for 55x and 56x series chips, the QSPI of the display driver only supports reading QSPI/SPI data from IO0 and does not support reading SPI data output from IO1. The display ID is output from IO1, which is not supported (52x series chips support configuring any IO from IO0 to IO3 for reading), as shown below:

Output through Interface-II mode is not supported, as shown below:

The panel ID output from IO0 is supported, as shown below:

Solution:
GPIO-simulated SPI reading chipid
**Note:**
Currently, 52x series chips already support reading and writing QSPI/SPI data through any data line from IO0-IO3 of the panel driver's QSPI interface.
The configuration method is as follows:
```c
.readback_from_Dx= 0, /* 0对应IO0, 1对应IO1, 2对应IO2, 3对应IO3,*/
```

## 1.10 Dynamically Adjusting the CLK Rate for Display QSPI Register Read/Write Operations
For some panel driver ICs, there is an upper limit requirement on the CLK frequency for register read/write during initialization. For example, it cannot exceed 20Mhz, while screen sending can reach 50Mhz. This can be modified as follows:
The default screen-send frequency is .freq = 48000000, //48Mhz

When reading registers, change it to 2Mhz, as follows:

```c
void GC9B71_ReadMode(LCDC_HandleTypeDef *hlcdc, bool enable)
{
if (HAL_LCDC_IS_SPI_IF(lcdc_int_cfg.lcd_itf)){
if (enable){
HAL_LCDC_SetFreq(hlcdc, 2000000); //read mode min cycle 300ns
}
else {
HAL_LCDC_SetFreq(hlcdc, lcdc_int_cfg.freq); //Restore normal frequency
}
}
}
```
When writing registers with GC9B71_WriteReg, the above method can also be used to adjust the clk rate.