【目标】
瑞萨RA8D1 LVGL移植,基于mdk的环境搭建。
【开发环境】
win11
【硬件】
1、CPKCOR-RA8D1B核心板
2、拓展板(CPKEXP-EKRA8X1)
【开发工具】
1、keil+fsp
2、vscode+fsp
【移植LVGL】
1、首先准备一个基于ra8d1的led工程。
2、rasc提供了lvgl的组件,打开rasc后,在stack中添加lvgl

3、打开bsp,开启sdram,将堆栈空间加大:

4、开启LCD时钟,时钟为240MHz

【配置LVGL】
1、关闭RTOS

2、修改自定义参数:



3、新建MIPI Display

然后修改LIN为1

生成工程,使用mdk打开工程。
【自定义代码添加】
1、添加dsi_layer.c/h
#include "r_ioport.h"
#include "r_mipi_dsi_api.h"
#include "hal_data.h"
#include "dsi_layer.h"
void mipi_dsi0_callback(mipi_dsi_callback_args_t * p_args);
static fsp_err_t dsi_layer_set_peripheral_max_return_msg_size(void);
static volatile bool g_message_sent = false;
void mipi_dsi_push_table (const LCD_setting_table *table);
fsp_err_t dsi_layer_configure_peripheral()
{
fsp_err_t err = FSP_SUCCESS;
LCD_setting_table * init_table = lcd_init_focuslcd;
err = dsi_layer_set_peripheral_max_return_msg_size(); // This must be performed prior to reading from display
if (FSP_SUCCESS == err)
{
LCD_setting_table * p_entry = init_table;
uint32_t counter = 0;
while(p_entry->msg_id != MIPI_DSI_DISPLAY_CONFIG_DATA_END_OF_TABLE)
{
mipi_dsi_cmd_t msg = { .channel = 0,
.cmd_id = p_entry->msg_id,
.flags = p_entry->flags,
.tx_len = p_entry->size,
.p_tx_buffer = p_entry->buffer };
if (p_entry->msg_id == MIPI_DSI_DISPLAY_CONFIG_DATA_DELAY_FLAG)
{
R_BSP_SoftwareDelay(p_entry->size, BSP_DELAY_UNITS_MILLISECONDS);
}
else
{
g_message_sent = false;
err = R_MIPI_DSI_Command (&g_mipi_dsi0_ctrl, &msg);
if (FSP_SUCCESS == err)
{
while(!g_message_sent);
mipi_dsi_status_t status;
R_MIPI_DSI_StatusGet(&g_mipi_dsi0_ctrl, &status);
while (MIPI_DSI_LINK_STATUS_CH0_RUNNING & status.link_status)
{
R_MIPI_DSI_StatusGet(&g_mipi_dsi0_ctrl, &status);
}
}
else
{
break;
}
}
p_entry++;
counter++;
}
}
return err;
}
void mipi_dsi0_callback (mipi_dsi_callback_args_t * p_args)
{
fsp_err_t err;
switch (p_args->event)
{
case MIPI_DSI_EVENT_SEQUENCE_0:
{
// g_message_sent |= (p_args->tx_status == MIPI_DSI_SEQUENCE_STATUS_DESCRIPTORS_FINISHED);
if (MIPI_DSI_SEQUENCE_STATUS_DESCRIPTORS_FINISHED == p_args->tx_status)
{
g_message_sent = 1U;
}
break;
}
case MIPI_DSI_EVENT_SEQUENCE_1:
{
__NOP();
break;
}
case MIPI_DSI_EVENT_VIDEO:
{
__NOP();
break;
}
case MIPI_DSI_EVENT_RECEIVE:
{
__NOP();
break;
}
case MIPI_DSI_EVENT_FATAL:
{
__NOP();
break;
}
case MIPI_DSI_EVENT_PHY:
{
__NOP();
break;
}
case MIPI_DSI_EVENT_POST_OPEN:
{
/* This case is called from R_DSI_Open(), so not from an interrupt */
err = dsi_layer_configure_peripheral();
if (FSP_SUCCESS != err)
{
__BKPT(0);
}
break;
}
default:
{
break;
}
}
}
/* See ILI9806E Datasheet, chapter 3.5.39
* 1. Set max return packet size
* 2. Read data be sending appropriate request */
static fsp_err_t dsi_layer_set_peripheral_max_return_msg_size()
{
fsp_err_t err;
uint8_t msg_buffer[] = {0x02, 0x00};
mipi_dsi_cmd_t return_size_msg = { .channel = 0,
.cmd_id = MIPI_CMD_ID_SET_MAXIMUM_RETURN_PACKET_SIZE,
.flags = MIPI_DSI_CMD_FLAG_LOW_POWER,
.tx_len = 2,
.p_tx_buffer = msg_buffer, };
/* Set Return packet size */
g_message_sent = false;
err = R_MIPI_DSI_Command (&g_mipi_dsi0_ctrl, &return_size_msg);
if (FSP_SUCCESS == err)
{
while(!g_message_sent);
}
return err;
}#pragma once
#include "r_mipi_dsi.h"
typedef struct {
unsigned char size;
unsigned char buffer[15];
mipi_dsi_cmd_id_t msg_id;
mipi_dsi_cmd_flag_t flags;
} LCD_setting_table;
extern const mipi_dsi_cfg_t g_mipi_dsi1_cfg;
extern mipi_dsi_instance_ctrl_t g_mipi_dsi0_ctrl;
extern LCD_setting_table lcd_init_focuslcd[];
fsp_err_t dsi_layer_configure_peripheral(void);
#define MIPI_DSI_DISPLAY_CONFIG_DATA_DELAY_FLAG ((mipi_dsi_cmd_id_t) 0xFE)
#define MIPI_DSI_DISPLAY_CONFIG_DATA_END_OF_TABLE ((mipi_dsi_cmd_id_t) 0xFD)2、添加board_init.h/c
#include "board_init.h"
#include "lvgl.h"
#include "common_data.h"
#if LV_USE_DRAW_DAVE2D
#define DIRECT_MODE 1
#else
#define DIRECT_MODE 0
#endif
void board_init(void)
{
/* Need to initialise the Touch Controller before the LCD, as only a Single Reset line shared between them */
//touch_init();
#if DIRECT_MODE
fsp_err_t err;
err = RM_LVGL_PORT_Open(&g_lvgl_port_ctrl, &g_lvgl_port_cfg);
if (FSP_SUCCESS != err)
{
__BKPT(0);
}
#else
static uint8_t partial_draw_buf[64*1024] BSP_PLACE_IN_SECTION(".dtcm_bss") BSP_ALIGN_VARIABLE(1024);
lv_display_t * disp = lv_renesas_glcdc_partial_create(partial_draw_buf, NULL, sizeof(partial_draw_buf));
#endif
#if DIRECT_MODE
lv_display_set_default(g_lvgl_port_ctrl.p_lv_display);
#else
lv_display_set_default(disp);
#endif
}#pragma once void board_init(void);
3、添加lcd配置文件dsi_configuration_data.c
#include "dsi_layer.h"
/* This table of commands was adapted from sample code provided by FocusLCD
* Page Link: https://focuslcds.com/product/4-5-tft-display-capacitive-tp-e45ra-mw276-c/
* File Link: https://focuslcds.com/content/E45RA-MW276-C_init_code.txt
*/
LCD_setting_table lcd_init_focuslcd[] =
{
{2, {0x11, 0x00}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_0_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xF0, 0xC3}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xF0, 0x96}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x36, 0x48}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x3A, 0x55}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xB4, 0x01}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
//0xB5, VFP=2,VBP=6, HBP=48
// {5, {0xB5, 0x02,0x06,0x00,0x30}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{4, {0xB6, 0x8A, 0x07, 0x3B}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
// {9, {0xB6, 0x8A, 0x8A, 0x00,0x00,0x29,0x19,0xA5,0x33}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xB7, 0xC6}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{3, {0xB9, 0x02,0xE0}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{3, {0xC0, 0xC0,0x64}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xC1, 0x1D}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xC2, 0xA7}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xC5, 0x18}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{9, {0xE8, 0x40, 0x8A, 0x00,0x00,0x29,0x19,0xA5,0x33},/*0x25,0x0A,0x38,0x33},*//*0x29,0x19,0xA5,0x33},*/ MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
//0xE0, positive gamma 控制
{15, {0xE0, 0xF0, 0x0B, 0x12,0x09,0x0A,0x26,0x39,0x54,0x4E,0x38,0x13,0x13,0x2E,0x34}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
//0xE1, negative gamma 控制
{15, {0xE1, 0xF0, 0x10, 0x15,0x0D,0x0C,0x07,0x38,0x43,0x4D,0x3A,0x16,0x15,0x30,0x35}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xF0, 0x3C}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0xF0, 0x69}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x35, 0x00}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
// {1, {0x29}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
// {1, {0x21}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_1_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x29, 0x00}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_0_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x21, 0x00}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_0_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{5, {0x2A, 0x00, 0x31, 0x01,0x0E}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{5, {0x2B, 0x00, 0x00, 0x01,0xDF}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
// {5, {0x2B, 0x00, 0x02, 0x01,0xE1}, MIPI_DSI_CMD_ID_DCS_LONG_WRITE, MIPI_DSI_CMD_FLAG_LOW_POWER},
{2, {0x2C, 0x00}, MIPI_DSI_CMD_ID_DCS_SHORT_WRITE_0_PARAM, MIPI_DSI_CMD_FLAG_LOW_POWER},
{0x00, {0}, MIPI_DSI_DISPLAY_CONFIG_DATA_END_OF_TABLE, (mipi_dsi_cmd_flag_t)0},
};4、修改hal_entry.c
#include "hal_data.h"
//#include "board_sdram.h"
#include "board_init.h"
//#include "lvgl/lvgl/lvgl.h"
#include "demos/lv_demos.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
/* TODO: add your own code here */
lv_init();
board_init();
#if (1 == LV_USE_DEMO_BENCHMARK)
lv_demo_benchmark();
#endif
#if (1 == LV_USE_DEMO_MUSIC)
lv_demo_music();
#endif
#if (1 == LV_USE_DEMO_KEYPAD_AND_ENCODER)
lv_demo_keypad_encoder();
#endif
#if (1 == LV_USE_DEMO_STRESS)
lv_demo_stress();
#endif
#if (1 == LV_USE_DEMO_WIDGETS && 0 == LV_USE_DEMO_BENCHMARK)
// lv_demo_widgets();
#endif
lv_demo_widgets();
while (1)
{
lv_timer_handler();
R_BSP_SoftwareDelay(3, BSP_DELAY_UNITS_MILLISECONDS);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
/*******************************************************************************************************************//**
* This function is called at various points during the startup process. This implementation uses the event that is
* called right before main() to set up the pins.
*
* @param[in] event Where at in the start up process the code is currently at
**********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
if (BSP_WARM_START_RESET == event)
{
#if BSP_FEATURE_FLASH_LP_VERSION != 0
/* Enable reading from data flash. */
R_FACI_LP->DFLCTL = 1U;
/* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
* C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
}
if (BSP_WARM_START_POST_C == event)
{
/* C runtime environment and system clocks are setup. */
/* Configure pins. */
R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
#if BSP_CFG_SDRAM_ENABLED
/* Setup SDRAM and initialize it. Must configure pins first. */
R_BSP_SdramInit(true);
#endif
// bsp_sdram_init();
}
}
#if BSP_TZ_SECURE_BUILD
FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{
}
FSP_CPP_FOOTER
#endif编译后下载到开发板。可以看到成功的运行了demo

【添加自定义工程】
使用guiguider设计一个基于lvgl9的窗口:

生成工程后,拷贝generated到工程中,并添加工程文件/目录

【实验效果】

【总结】
对于其他的MCU系列来说,RA的生态现在非常好了,通过图形化的配置,可以快速的创建工程,并验证开发板的功能。
我要赚赏金
