Preface
This article introduces the LCD screen of milkv-duo loading st7735, and the screen display log.
Reference article:
Record configuring spi screen for Linux (st7735s)
https://community.milkv.io/t/milk-v-duo-spi-st7789/131
1. Circuit diagram
1.1 pin setting
Open the pin of spi2
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\u-boot\cvi_board_init.c
//spi2 -- st7735
pinmux_config(PINMUX_SPI2);
PINMUX_CONFIG(SPINOR_MISO, XGPIOA_23); //DC
PINMUX_CONFIG(SD0_PWR_EN, XGPIOA_14); //BL
PINMUX_CONFIG(SPK_EN, XGPIOA_15); //RES
Note that the DC here belongs to gpioA
The pinmux_config(PINMUX_SPI2) here; the corresponding configuration can be found in the source code
case PINMUX_SPI2:
PINMUX_CONFIG(SD1_CMD, SPI2_SDO);
PINMUX_CONFIG(SD1_CLK, SPI2_SCK);
PINMUX_CONFIG(SD1_D0, SPI2_SDI);
PINMUX_CONFIG(SD1_D3, SPI2_CS_X);
break;
1.2 dtsi configuration
build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts
&spi2 {
status = "okay";
/delete-node/ spidev@0;
st7789v: st7789v@0{
compatible = "sitronix,st7789v";
reg = <0>;
status = "okay";
spi-max-frequency = <48000000>;
spi-cpol;
spi-cpha;
rotate = <90>;
fps = <30>;
rgb;
buswidth = <8>;
dc-gpios = <&porta 23 GPIO_ACTIVE_HIGH>; //DC
reset-gpios = <&porta 15 GPIO_ACTIVE_HIGH>; //RES
led-gpios = <&porta 14 GPIO_ACTIVE_HIGH>; //BL
debug = <0x0>;
};
};
The gpio here must be implemented in conjunction with your pins.
2. Load the driver
Follow the reference article and use the st7789v code to modify it to st7735.
Documentation to configure spi screen for linux (st7735s)
Compilation conditions
duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\Makefile
obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o
obj-$(CONFIG_FB_TFT_ST7789V) += fb_st7789v.o
Borrow the code from st7789v
st7735s is consistent with st7735r
引用:https://www.cnblogs.com/milton/p/15614304.html#St7735%E4%BB%8B%E7%BB%8D
ST7735的配置
因为ST7735存在多个型号, 对于ST7735R和ST7735S, 使用默认的初始化方法
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\ cvitek_cv1800b_milkv_duo_sd_defconfig
# spi lcd -- st7735s
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=y
CONFIG_FB=y
CONFIG_FB_TFT=y
# CONFIG_FB_TFT_ST7735R=y
CONFIG_FB_TFT_ST7789V=y
Compilation process tips
CC drivers/staging/fbtft/fb_st7789v.o
3. Change the driver
3.1 st7789v driver
duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fb_st7789v.c
Reference source: https://blog.csdn.net/qq_46604211/article/details/116449891
3.1.2 Interface update
Since the driver is st7789v and my screen is st7735, some initialization interfaces need to be changed.
Note that gamma needs to comment out the for loop.
// st7735
static int init_display(struct fbtft_par *par)
{
par->fbtftops.reset(par);//硬复位
mdelay(50);
write_reg(par,0x11);//软复位
mdelay(100);
//下面添加初始化函数write_reg 参数分别为:结构体指针,写命令,写数据....(后都为数据)
//ST7735s Frame Rate
write_reg(par,0xB1,0x05,0x3c,0x3c);
write_reg(par,0xB2,0x05,0x3c,0x3c);
write_reg(par,0xB3,0x05,0x3c,0x3c,0x05,0x3c,0x3c);
write_reg(par,0xB4,0x03); //Column inversion
//ST7735s Power Sequence
write_reg(par,0xC0,0x28,0x08,0x04);
write_reg(par,0xC1,0xc0);
write_reg(par,0xC2,0x0d,0x00);
write_reg(par,0xC3,0x8d,0x2a); //VCOM
write_reg(par,0xc4,0x8d,0xee); //MX, MY, RGB mode
write_reg(par,0xc5,0x1a);
write_reg(par,0x36,0xc0);
//ST7735s Gamma Sequence
write_reg(par,0xe0,0x04,0x22,0x07,0x0a,0x2e,0x30,0x25,0x2a,0x28,0x26,0x2e,0x3a,0x00,0x01,0x03,0x13);
write_reg(par,0xe1,0x04,0x16,0x06,0x0d,0x2d,0x26,0x23,0x27,0x27,0x25,0x2d,0x3b,0x00,0x01,0x04,0x13);
write_reg(par,0x3A,0x05); //65k mode
write_reg(par,0x29);//Display on
mdelay(100);
return 0;
}
static int set_gamma(struct fbtft_par *par, u32 *curves)
{
int i;
int j;
int c; /* curve index offset */
/*
* Bitmasks for gamma curve command parameters.
* The masks are the same for both positive and negative voltage
* gamma curves.
*/
static const u8 gamma_par_mask[] = {
0xFF, /* V63[3:0], V0[3:0]*/
0x3F, /* V1[5:0] */
0x3F, /* V2[5:0] */
0x1F, /* V4[4:0] */
0x1F, /* V6[4:0] */
0x3F, /* J0[1:0], V13[3:0] */
0x7F, /* V20[6:0] */
0x77, /* V36[2:0], V27[2:0] */
0x7F, /* V43[6:0] */
0x3F, /* J1[1:0], V50[3:0] */
0x1F, /* V57[4:0] */
0x1F, /* V59[4:0] */
0x3F, /* V61[5:0] */
0x3F, /* V62[5:0] */
};
for (i = 0; i < par->gamma.num_curves; i++) {
c = i * par->gamma.num_values;
// for (j = 0; j < par->gamma.num_values; j++)
// curves[c + j] &= gamma_par_mask[j];
write_reg(par, PVGAMCTRL + i,
curves[c + 0], curves[c + 1], curves[c + 2],
curves[c + 3], curves[c + 4], curves[c + 5],
curves[c + 6], curves[c + 7], curves[c + 8],
curves[c + 9], curves[c + 10], curves[c + 11],
curves[c + 12], curves[c + 13]);
}
return 0;
}
3.1.3 Change width and height
The screen width and height of st7735 is 128*160.
duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fb_st7789v.c
static struct fbtft_display display = {
.regwidth = 8,
.width = 128,//240,
.height = 160,//320,
.gamma_num = 2,
.gamma_len = 14,
.gamma = HSD20_IPS_GAMMA,
.fbtftops = {
.init_display = init_display,
.set_var = set_var,
.set_gamma = set_gamma,
.blank = blank,
},
};
3.2 fbtft-core
duo-buildroot-sdk\linux_5.10\drivers\staging\fbtft\fbtft-core.c
3.2.1 Add header file
#include <linux/gpio.h> //add
#include <linux/of_gpio.h> //add
3.2.2 Change interface
This is caused by the kernel version update, and some interfaces may need to be changed.
The attributes in dtsi plus -gpio can be selected by yourself.
reset is reimplemented.
//https://blog.csdn.net/qq_46604211/article/details/116449891
static int fbtft_request_one_gpio(struct fbtft_par *par,
const char *name, int index,
struct gpio_desc **gpiop)
{
struct device *dev = par->info->device;
struct device_node *node = dev->of_node;
int gpio, flags, ret = 0;
enum of_gpio_flags of_flags;
if (of_find_property(node, name, NULL)) {
gpio = of_get_named_gpio_flags(node, name, index, &of_flags);
if (gpio == -ENOENT)
return 0;
if (gpio == -EPROBE_DEFER)
return gpio;
if (gpio < 0) {
dev_err(dev,
"failed to get '%s' from DT\n", name);
return gpio;
}
//active low translates to initially low
flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW :
GPIOF_OUT_INIT_HIGH;
ret = devm_gpio_request_one(dev, gpio, flags,
dev->driver->name);
if (ret) {
dev_err(dev,
"gpio_request_one('%s'=%d) failed with %d\n",
name, gpio, ret);
return ret;
}
*gpiop = gpio_to_desc(gpio);
fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n",
__func__, name, gpio);
}
return ret;
}
static int fbtft_request_gpios(struct fbtft_par *par)
{
int i;
int ret;
ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
if (ret)
return ret;
for (i = 0; i < 16; i++) {
ret = fbtft_request_one_gpio(par, "db-gpios", i,
&par->gpio.db[i]);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "led-gpios", i,
&par->gpio.led[i]);
if (ret)
return ret;
ret = fbtft_request_one_gpio(par, "aux-gpios", i,
&par->gpio.aux[i]);
if (ret)
return ret;
}
return 0;
}
//作者:Leesans https://www.bilibili.com/read/cv9947785/ 出处:bilibili
static void fbtft_reset(struct fbtft_par *par)
{
if (!par->gpio.reset)
return;
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
gpiod_set_value_cansleep(par->gpio.reset, 1);
msleep(10);
gpiod_set_value_cansleep(par->gpio.reset, 0);
msleep(200);
gpiod_set_value_cansleep(par->gpio.reset, 1);
msleep(10);
}
4. Screen display results
The driver loads normally.
You can test the screen function through the following two commands.
cat /dev/urandom > /dev/fb0 //显示花屏
cat /dev/zero > /dev/fb0 //清空屏幕
echo xxxx > /dev/fb0 //显示点个数
Look carefully at the upper right corner. There is a line of different colors. It is very short. You can echo followed by a long x. The more x, the longer the line.
This is manually assigned to the pixels.
5. Display the log on the screen
Reference source:
https://community.milkv.io/t/milk-v-duo-spi-st7789/131
5.1 Add compilation module
duo-buildroot-sdk\build\boards\cv180x\cv1800b_milkv_duo_sd\linux\cvitek_cv1800b_milkv_duo_sd_defconfig
# lcd display kernel log
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_FB=y
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FONT_SUPPORT=y
CONFIG_FONTS=y
CONFIG_FONT_8x16=y
CONFIG_VGA_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
5.2 Add tty0 to display log
duo-buildroot-sdk\u-boot-2021.10\include\configs\cv180x-asic.h
#define SET_BOOTARGS "setenv bootargs ${root} ${mtdparts} " \
"console=tty0 console=$consoledev,$baudrate $othbootargs;"