2322 views|3 replies

155

Posts

1

Resources
The OP
 

[Luckfox RV1106 Linux Development Board Review] 12. Implementing FrameBuffer Device and LVGL Application [Copy link]

 

My post [Luckfox RV1106 Linux Development Board Review] link:

1. Unboxing and testing

2. SDK acquisition and image compilation

3. GPIO Lighting

4. Access the Internet through PC shared network and light up Python in Ubuntu

5. Compile the Buildroot system and test the camera

6. PWM control - command and C mode

7. PWM Control - Python and Device Tree Method

8. ADC and UART test

9. Python controls I2C to drive OLED

10. C program controls I2C to drive OLED

11. SPI drives LCD

This review is based on the SPI0 interface enabled in the previous review. By further modifying the device tree file <SDK directory>/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-pro-max.dts, the 0.96-inch Hezhou LCD (ST7735) driven by Luckfox Pro Max (SPI0 port) is registered as a FrameBuffer device. In this way, LVGL can be used as a display interface based on FB.

This experiment mainly refers to the LVGL User Guide of Luckfox Wiki ( https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-LVGL ).

1. Device tree file modification

The LVGL.zip provided in the official document contains the system image, lvgl_demo project and device files, but unfortunately it is based on the Weixue Pico-LCD-1.3 display (ST7789 driver), which is different from the Hezhou LCD in my hand. Fortunately, both LCD drivers are products of Sitronix, and both have drivers in the Linux system.

The Weixue 1.3-inch screen comes with a five-way switch and ABXY four-button, so the device tree file in LVGL.zip has not only the SPI0 configuration but also the IO configuration of these buttons. Because many IOs are used, interfaces such as I2C3 are disabled. The Hezhou 0.96-inch screen I use only comes with a five-way switch, so I did not copy the device tree file directly, but only modified the SPI0 part. The complete rv1106g-luckfox-pico-pro-max.dts file code is as follows:

// 基于官方案例提供设备树源码,剔除注释部分和未使用IO部分
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
 */

/dts-v1/;

#include "rv1106.dtsi"
#include "rv1106-evb.dtsi"
#include "rv1106-luckfox-pico-pro-max-ipc.dtsi"

/ {
	model = "Luckfox Pico Max";
	compatible = "rockchip,rv1103g-38x38-ipc-v10", "rockchip,rv1106";

	/*KEY*/
	/*KEY-DOWN*/
	gpio2pa0:gpio2pa0 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio2_pa0>;
		regulator-name = "gpio2_pa0";
		regulator-always-on;
	};

	/*KEY-RIGHT*/
	gpio2pa2:gpio2pa2 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio2_pa2>;
		regulator-name = "gpio2_pa2";
		regulator-always-on;
	};

	/*KEY-LEFT*/
	gpio2pa4:gpio2pa4 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio2_pa4>;
		regulator-name = "gpio2_pa4";
		regulator-always-on;
	};

	/*KEY-CENTER*/
	gpio1pc6:gpio1pc6 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio1_pc6>;
		regulator-name = "gpio1_pc6";
		regulator-always-on;
	};

	/*KEY-UP*/
	gpio1pc7:gpio1pc7 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio1_pc7>;
		regulator-name = "gpio1_pc7";
		regulator-always-on;
	};

	/*LCD_RES*/
	gpio1pc3:gpio1pc3 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio1_pc3>;
		regulator-name = "gpio1_pc3";
		regulator-always-on;
	};

	/*LCD_BL*/
	gpio2pb0:gpio2pb0 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio2_pb0>;
		regulator-name = "gpio2_pb0";
		regulator-always-on;
	};

	/*LCD_DC*/
    gpio2pb1:gpio2pb1 {
		compatible = "regulator-fixed";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio2_pb1>;
		regulator-name = "gpio2_pb1";
		regulator-always-on;
	};
};

/**********GPIO**********/
&pinctrl {
	/*KEY*/
	gpio2-pa0 {
		gpio2_pa0:gpio2-pa0 {
			rockchip,pins =	<2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};

	gpio2-pa2 {
		gpio2_pa2:gpio2-pa2 {
			rockchip,pins =	<2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};

	gpio2-pa4 {
		gpio2_pa4:gpio2-pa4 {
			rockchip,pins =	<2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};

	gpio1-pc6 {
		gpio1_pc6:gpio1-pc6 {
			rockchip,pins =	<1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};

	gpio1-pc7 {
		gpio1_pc7:gpio1-pc7 {
			rockchip,pins =	<1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};

	/*RESET*/
	gpio1-pc3 {
		gpio1_pc3:gpio1-pc3 {
			rockchip,pins =	<1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};

	/*BL*/
	gpio2-pb0 {
		gpio2_pb0:gpio2-pb0 {
			rockchip,pins =	<2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};

	/*LCD_DC*/
  gpio2-pb1 {
		gpio2_pb1:gpio2-pb1 {
			rockchip,pins =	<2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

/**********FLASH**********/
&sfc {
	status = "okay";
	flash@0 {
		compatible = "spi-nand";
		reg = <0>;
		spi-max-frequency = <75000000>;
		spi-rx-bus-width = <4>;
		spi-tx-bus-width = <1>;
	};
};

/**********ETH**********/
&gmac {
	status = "okay";
};

/**********USB**********/
&usbdrd_dwc3 {
	status = "okay";
	dr_mode = "peripheral";
};

/**********I2C**********/
&i2c3 {
	status = "okay";
	pinctrl-0 = <&i2c3m1_xfer>;
	clock-frequency = <100000>;
};

/**********SPI**********/
&spi0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&spi0m0_cs0 &spi0m0_pins>;

	st7735s@0{
		status = "okay";
		compatible = "sitronix,st7735r";
		reg = <0>;
		spi-max-frequency = <48000000>;
//		width = <80>;
//		height = <160>;
		rotate = <270>;
		fps = <30>;
		buswidth = <8>;
		debug = <0x7>;
		led-gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_HIGH>;//BL
		dc = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>;       //DC
		reset = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>;     //RES
	};
};

&pinctrl {
    spi0 {
        /omit-if-no-ref/
        spi0m0_pins: spi0m0-pins {
            rockchip,pins =
                /* spi0_clk_m0 */
                <1 RK_PC1 4 &pcfg_pull_none>,
                /* spie_miso_m0 */
                /* <1 RK_PC3 6 &pcfg_pull_none>, */
                /* spi_mosi_m0 */
                <1 RK_PC2 6 &pcfg_pull_none>;
        };
    };
};

In addition to the device tree file, you also need to modify <SDK directory>/sysdrv/source/kernel/arch/arm/configs/luckfox_rv1106_linux_defconfig to add FB file support. Editing the file directly can save the step of make menuconfig.

Figure 12-1 FB device support additions

After modifying the device tree and configuration files, you can compile the kernel again and flash the development board. After updating the system image, restart the development board and you will see the device file: /dev/fb0.

Figure 12-2 The development board has fb0

2. lvgl_demo project modification

The official LVGL.zip contains the test project lvgl_demo. Copy the project folder to the virtual machine. Because the project is based on FB's LVGL porting case, no other modifications are required. You only need to update the CC variable in Makefile to the Luckfox SDK path.

In addition, when the Hezhou screen is used in the case, the console outputs an error message: ioctl(FBIOBLANK): Invalid argument. Refer to a technical post ( https://blog.csdn.net/klp1358484518/article/details/130032766 ), and you need to comment out several lines of code in lv_drivers/display/fbdev.c:

// Located in fbdev_init() function

// Make sure that the display is on.

// if (ioctl(fbfd, FBIOBLANK, FB_BLANK_UNBLANK) != 0) {

// perror("ioctl(FBIOBLANK)");

// return;

// }

Of course, since I use a 0.96-inch screen, I have modified main.c - the original case shows pictures adapted to a 1.3-inch screen, and here it is changed to display a line of strings in the center of the screen. The code of main.c is as follows:

#include "lvgl/lvgl.h"
#include "DEV_Config.h"
#include "lv_drivers/display/fbdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

#define DISP_BUF_SIZE (160 * 128)

void fbdev_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p);

int main(void)
{
    /*LittlevGL init*/
    lv_init();

    /*Linux frame buffer device init*/
    fbdev_init();

    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE];

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb   = fbdev_flush;
    disp_drv.hor_res    = 160;
    disp_drv.ver_res    = 128;
    lv_disp_drv_register(&disp_drv);

    /*Initialize pin*/
    DEV_ModuleInit();

    lv_obj_t *scr = lv_disp_get_scr_act(NULL);
    // 显示字符串
    lv_obj_t *label = lv_label_create(scr);
    lv_label_set_text(label, "Luckfox LVGL FB!");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

    /*Create a cursor*/
    lv_obj_t *cursor = lv_img_create(scr);
    lv_img_set_src(cursor, LV_SYMBOL_GPS);
    lv_obj_set_pos(cursor, 70, 40);
    int x=70,y=40,move=0;

    /*Handle LitlevGL tasks (tickless mode)*/
    while(1) {
        lv_timer_handler();
        usleep(5000);

        /*Joystick*/
        if(GET_KEY_RIGHT == 0){
            x += 1;
            if(x > 226)x = 226;
            move =1;
        }
        else if(GET_KEY_LEFT == 0){
            x -= 1;
            if(x < 0)x = 0;
            move =1;
        }
       else if(GET_KEY_UP == 0){
            y -= 1;
            if(y < 0)y = 0;
            move =1;
        }
        else if(GET_KEY_DOWN == 0){
            y += 1;
            if(y > 224)y = 224;
            move =1;
        }
       else if(GET_KEY_PRESS == 0){
            x = 80;
            y = 64;
            move =1;
        }
        if(move == 1){
            lv_obj_set_pos(cursor, x, y);
            move = 0;
        }
    }

    return 0;
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

Figure 12-3 Example effect - the icons on the screen will move when the five-way switch is turned

3. Description of the problem in debugging

The project seemed simple, but it took the next day to debug. The main problem was screen adaptation. The screen was originally displayed vertically (i.e. the font in the above picture was rotated 90° to the left). I tried to adjust the screen direction by modifying the program code, using the lv_disp_set_rotation() function, but it didn't work. I thought that the underlying driver did not support screen rotation, so I changed my mind and tried to modify the device file. Note: I later found that the LVGL document mentioned that if there is no hardware support, the lv_draw_sw_rotate() function can be used to rotate the screen, but I didn't try it myself and I don't know if it works.

Figure 12-4 Screenshot of the Rotation section of the LVGL online documentation

It is not easy to find information about the device tree node description of ST7735. I also searched several technical blogs and analyzed the setting methods of "rotation, width and height" properties. However, after verification, if the screen size is set according to the actual parameters of 0.98 screen, part of the screen will not be usable, so I simply set only rotate.

As for the reason why the problem occurs after setting the width and height, I personally guess that it may be that the ST7735r driver provided in the Linux source code is adapted to the size of 160*128 and is not compatible with other sizes. This is also analyzed by checking the corresponding documentation in the Linux source code Documentation - <Luckfox SDK>/sysdrv/source/kernel/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml.

Figure 12-5 Device tree nodes for Hezhou 0.96-inch screen

Figure 12-6 Effect of setting the width and height attributes—part of the screen is unusable

Figure 12-7 Screenshot of sitronix,st7735r.yaml document content

After the above system image is burned, the fbset command in the development board shows that the current screen resolution is 160x128. I find it quite magical that the actual screen parameter is 160x80 but the system can recognize it as 160x128. In view of this, I also set the screen size to 160x128 in the program, and I didn't expect it to be displayed accurately.

Figure 12-8 fbset command to check screen resolution

Figure 12-9 LVGL sets width and height based on system resolution

This post is from Domestic Chip Exchange

Latest reply

OK, OK, I'll go see the snow.   Details Published on 2024-2-19 11:53
 
 

364

Posts

0

Resources
2
 

What is the price of this screen? If it is not expensive, I will also get one. It is quite convenient to display

This post is from Domestic Chip Exchange

Comments

The Hezhou one costs about 10 yuan. In fact, it is better to buy the Weixue one. The official case can be adapted and the size is also larger.  Details Published on 2024-2-19 10:33
 
 
 

155

Posts

1

Resources
3
 
LitchiCheng posted on 2024-2-19 09:34 What is the price of this screen? If it is not expensive, I will also get one. It is quite convenient to display.

The Hezhou one costs about 10 yuan. In fact, it is better to buy the Weixue one. The official case can be adapted and the size is also larger.

This post is from Domestic Chip Exchange

Comments

OK, OK, I'll go see the snow.  Details Published on 2024-2-19 11:53
 
 
 

364

Posts

0

Resources
4
 
sonicfirr posted on 2024-2-19 10:33 The Hezhou one is about 10 bucks. In fact, it is better to buy the Weixue one. The official case can be adapted and the size is also larger.

OK, OK, I'll go see the snow.

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list