这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 基于瑞萨CPK-RA8D1的lvgl移植

共1条 1/1 1 跳转至页

基于瑞萨CPK-RA8D1的lvgl移植

菜鸟
2026-10-13 11:07:57     打赏

参加瑞萨活动申请到一块RA8D1开发板 开发板由这么两部分组成:

  • CPKCOR-RA8D1B核心板:搭载RA8D1 MCU、32 MB SDRAM、16 MB QSPI Flash、板载J-Link调试器和MicroSD卡槽。

  • CPKEXP-EKRA8x1扩展板:提供百兆以太网、板载LCD、CAN-FD、USB和多种扩展接口。

微信图片_20260924232305_288_6.jpg

不过看起来图片有些小,不要太在意

先介绍一下相关的具体参数吧 RA8D1:

  • 480MHz Arm® Cortex®-M85 搭载 Helium™ MVE

    1MB - 2MB 闪存和 1MB SRAM,包括 TCM

  • 32KB I/D 高速缓存和 12KB 数据闪存

  • 带 RGB 和 MIPI-DSI I/F 的图形 LCD 控制器

  • 2D 绘图引擎,16 位 CEU 摄像头 I/F

  • 32/16/8 位外部存储器接口 (CS/SDRAM)

可谓是性能十分的强大 本次我主要评测的内容相关联的参数 第一个就是helium 

Helium 支持 SIMD/DSP,对 int8 量化模型很友好,配合 CMSIS-NN / TFLite Micro 能加速人脸检测

SDRAM接口对跑lvgl十分重要 帧率能不能上去真的靠它了 还有CEU摄像头并行采集摄像头数据 本次 我将用它来采集人脸

自带mipi接口直接驱动即可 官方也给了相关的配置文件 下面我先把屏幕点亮一下 大家跟着我的操作 即可

本次采用集成开发环境和编译器:e2studio v2025-01 + llvm 18.1.3         FSP版本:FSP 5.8.0

本次需要的资料和demo bsp包大家自行下载安装里面都有
git clone https://gitee.com/ramcu/cpk_examples.git

首先我们打开e2studio 创建C/C++工程 选择第一个

ScreenShot_2026-09-24_234602_593.png

然后我们点下一步 会让我们输入名称 我们直接输入一个名称 然后下一步

ScreenShot_2026-09-24_234733_115.png

我们选择对应的bsp包然后创建一个freertos工程

这里我们选择blinky和minimal都行 blinky就是初始化了个freertos线程控制led灯

接下来我们直接导入一下mipi的引脚配置文件 因为个人手动配置太麻烦了 

ScreenShot_2026-09-25_000028_198.png

我们先设置一下时钟 (写了一半了刚发现时钟忘配置了)

ScreenShot_2026-09-25_004058_601.png


然后我们使能一下SDRAM data cache以及Stack 和 Heap 的大小:

ScreenShot_2026-09-25_000402_046.png

之后我们在 Stacks 界面配置一下外设的堆栈,点击右上角的 New Stack 新建 LVGL、FreeRTOS Heap 4,新建 LVGL 后需要添加 MIPI 的驱动:

有报错正常,我们下面解决

ScreenShot_2026-09-25_000725_101.png

因为使用了freertos 所以我们创建一个新线程 让他去负责lvgl的显示

ScreenShot_2026-09-25_000810_828.png

然后我们进行一些配置 让报错消失掉 先设置一下头用户自定义文件名 和 足够的内存空间运行

ScreenShot_2026-09-25_002047_981.png

ScreenShot_2026-09-25_002348_199.png

接下来我们配置一下Graphics LCD 根据屏幕的分辨率设置输入图层的参数。输出信号和输出数据格式也根据屏幕的分辨率也需要进行相应的修改。

先设置一下屏幕输入数据的大小 下面两个是设置屏幕输出时钟信号参数 最下面是设置输出图像数据的格式

ScreenShot_2026-09-25_003416_731.png

最后呢我们设置一下lvgl初始化和运行应用程序的线程 这样 我们的工程就没有报错 可以正常生成了

ScreenShot_2026-09-25_003818_282.png

Ctrl+S保存配置文件,点击Generate Project Content生成代码。

然后我们再根据【瑞萨RA8D1 LVGL评测】1、MIPI DSI屏幕使用lvgl实现多界面切换和LED控制_lvgl屏幕控制-CSDN博客这位大佬的帖子 添加一下硬件描述代码来实现屏幕显示功能

扩展板上的显示屏的驱动芯片为ST7796,需要通过特定的初始化序列对屏幕进行初始化,初始化序列如下。

#include "dsi_layer.h"

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},


};

MIPI DSI接口的回调函数 和相关的事件处理函数

#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;
}

最后添加Hello World示例程序,看一下屏幕显示内容

void LVGL_thread_entry(void *pvParameters)
{
    FSP_PARAMETER_NOT_USED (pvParameters);

    /* TODO: add your own code here */
    lv_init();
    board_init();

    /*Change the active screen's background color*/
    lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);

    /*Create a white label, set its text and align it to the center*/
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "Hello world");
    lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

    while (1)
    {
        lv_timer_handler();
        vTaskDelay(1);
    }
}

编译下载我们可以看到屏幕显示内容如下图

QQ20261013-110124.png

第一次用瑞萨的板子遇到些许问题 靠ai神力仍未解决 自己能力有限但仍会继续

接下来 我将根据站内大佬的帖子移植lwip和实现ota升级功能

参考文章【瑞萨RA8D1 LVGL评测】1、MIPI DSI屏幕使用lvgl实现多界面切换和LED控制_lvgl屏幕控制-CSDN博客

【CPKCOR-RA8D1】2、运行LVGL - 瑞萨单片机论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛!

感谢大佬的文章











关键词: RA8D1     lvgl移植     瑞萨     单片机    

共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]