0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

讲讲RK3568开发板上的多核加载流程

jf_NsPBt3VS 来源:风火轮技术团队 2024-03-06 18:17 次阅读

YY3568主板基于 Rockchip RK3568 芯片平台,四核 64位 Cortex-A55 核,主频最高达 2GHz,集成双核心架构GPU以及高效能NPU,芯片性能优异。开发板功能接口丰富,多媒体性能强悍、可在物联网工业控制、智慧交通、轻量级人工智能等领域发挥独特优势。

板载有 2路DSI、1路HDMI 和 1路edp显示接口。支持双屏异显输出和4K分辨率。强大的显示性能,并且适配了自研的7寸mipi屏和edp屏。在多屏广告机、电子站牌、自助服务机、工业HMI等领域可发挥强大优势以及更低的成本。

板载 2 路千兆 以太网,可通过双网口访问和传输内外网的数据。拥有WIFI/BT,PCIE 3.0接口及 SIM 座,可接 4G 通信模块,提高网络传输效率。满足NVR、工业网关等多网口产品需求。

板载 5路 串口,能够大大降低通信成本。2 路IIC,可接多个IIC设备。1路CAN,能够满足汽车电子领域需求。

板载PCIE3.0和SATA接口,支持固态硬盘M.2,SATA硬盘,可扩展大容量硬盘。

YY3568多核启动方案

瑞芯微官方提供了4种多核软件方案。但是启动流程的大致方案是一致的。其方案为:

方案 说明
3kernel + 1hal 0~2核心:Linux(SMP),3核心:裸机
3kernel + 1RT-Thread 0~2核心:Linux(SMP),3核心:RT-Thread(RTOS)
1kernel + 3hal 0核心:Linux,1~3核心:裸机(每一个核心跑一个裸机)
2kernel + 3RT-Thread 0核心:Linux,1~3核心:RT-Thread(每一个核心跑一个RTOS)

YY3568多核启动分析

我们在风火轮科技的YY3568开发板上验证的方案:3kernel(SMP) + 1RT-Thread

启动配置

多核启动配置文件路径:device/rockchip/rk3568/rk3568_amp_linux.its。

rk3568_amp_linux.its配置文件格式,其以设备树的格式存在。所以操作其内容的方法可以通过操作设备树一样。

多核启动主要分为两个核心节点:

①conf节点描述:描述需要启动那些子核心(节点:loadables),linux内核启动参数(节点:linux)。

②images节点描述:描述需要启动子核心的参数,如:架构,指令集,分区首地址,核启动延迟等。

/{
description="FITsourcefileforrockchipAMP";
#address-cells=<1>;

images{
amp3{
description="bare-mental-core3";
data=/incbin/("cpu3.bin");//打包前的固件位置,一般不需要
type="firmware";
compression="none";
arch="arm";//固件的指令架构,当前只支持arm
cpu=<0x300>;//mpidr
thumb=<0>;//0:armorthumb2;1:thumb
hyp=<0>;//0:el1/svc;1:el2/hyp
load=<0x02800000>;//内存分区起始地址
udelay=<10000>;//启动下一个核心的延迟时间
hash{
algo="sha256";
};
};
};

configurations{
default="conf";
conf{
description="RockchipAMPimages";
rollback-index=<0x0>;
loadables="amp3";

signature{
algo="sha256,rsa2048";
padding="pss";
key-name-hint="dev";
sign-images="loadables";
};

/*-runlinuxoncpu0
*-itisbroughtupbyamp(thatrunonU-Boot)
*-itisbootentrydependsonU-Boot
*/
linux{
description="linux-os";
arch="arm64";
cpu=<0x000>;
thumb=<0>;
hyp=<0>;
udelay=<0>;
};
};
};
};

内存分区

描述了每个核心的内存起始地址以及内存分区大小。

我们采用的方案:3kernel(SMP) + 1RT-Thread,所以RT-Thread的内存位置为:CPU3_MEM_BASE=0x02800000。

# Linux + HAL/RTT形式的内存资源分区示例:
CPU0_MEM_BASE=0x03000000
CPU1_MEM_BASE=0x01800000
CPU2_MEM_BASE=0x02000000
CPU3_MEM_BASE=0x02800000
CPU0_MEM_SIZE=0x00800000
CPU1_MEM_SIZE=0x00800000
CPU2_MEM_SIZE=0x00800000
CPU3_MEM_SIZE=0x00800000

amp固件打包

RK3568的amp固件,其包含的内容:启动配置信息(rk3568_amp_linux.its) + 从核的代码。

它是通过mkimage将两者打包一起的,工具路径:device/rockchip/common/mkimage。

打包命令:mkimage -f amp.its -E -p 0xe00 amp.img,其中:

0xe00:它是its在固件的大小,如果its文件大小不足对应大小,则补0。

从核的代码追加在其后面。

2a092f62-dba1-11ee-a297-92fbcf53809c.png

源码分析

内核启动流程--准备工作

RK3568的多核启动是由uboot来管理的,所以我们主要剖析uboot的源码。

多核启动流程的代码路径:uboot/drivers/cpu/rockchip_amp.c。

多核启动的函数入口:int amp_cpus_on(void)。

启动核心的程序,需要提前准备4个动作:

获取设备的启动设备,我们YY3568目前采用的是EMMC,所以这里描述的就是EMMC设备;然后从启动设备获取AMP分区。

申请存放头信息的空间,从AMP分区中获取头信息(即多核启动配置信息:rk3568_amp_linux.its);检测its的合法性,并获取其大小。

申请固件的内存,从AMP分区获取从核心的内容。

通过头部信息,解析可加载项。然后调用brought_up_all_amp()启动所有核心。

intamp_cpus_on(void)
{
....省略

dev_desc=rockchip_get_bootdev();
....省略

if(part_get_info_by_name(dev_desc,AMP_PART,&part)< 0)       // ①
 ....省略

 hdr = memalign(ARCH_DMA_MINALIGN, FIT_HEADER_SIZE);
 ....省略

 /* get totalsize */
 offset = part.start;
 cnt = DIV_ROUND_UP(FIT_HEADER_SIZE, part.blksz);
 if (blk_dread(dev_desc, offset, cnt, hdr) != cnt) {
 ....省略

 if (fdt_check_header(hdr)) {
 ....省略

 if (fit_get_totalsize(hdr, &totalsize)) {           // ②
 ....省略

 /* load image */
 fit = memalign(ARCH_DMA_MINALIGN, ALIGN(totalsize, part.blksz));
 ....省略

 offset += cnt;
 cnt = DIV_ROUND_UP(totalsize, part.blksz) - cnt;
 if (blk_dread(dev_desc, offset, cnt, fit + FIT_HEADER_SIZE) != cnt) {   // ③
 ....省略

 ret = parse_os_amp_dispatcher();
 ....省略

 /* Load loadables */
 memset(&images, 0, sizeof(images));
 images.fit_uname_cfg = "conf";
 images.fit_hdr_os = fit;
 images.verify = 1;
 ret = boot_get_loadable(0, NULL, &images, IH_ARCH_DEFAULT, NULL, NULL);     // ④
 ....省略

 /* Wakeup */
 ret = brought_up_all_amp(images.fit_hdr_os, images.fit_uname_cfg); //⑤
 ....省略
}

内核启动流程--加载项获取

核心启动分为两部分:Linux内核启动部分 + 非Linux内核(RT-Thread)启动部分。

Linux内核启动部分:从rk3568_amp_linux.its配置中获取Linux节点。然后调用brought_up_amp()启动内核。

2a141558-dba1-11ee-a297-92fbcf53809c.jpg

非Linux内核(RT-Thread)启动部分:从rk3568_amp_linux.its配置中获取loadables节点,遍历节点成员,获取对应的加载项的配置信息,然后调用调用brought_up_amp()启动内核。

2a23ef3c-dba1-11ee-a297-92fbcf53809c.jpg

staticintbrought_up_all_amp(void*fit,constchar*fit_uname_cfg)
{
....省略

g_bootcpu.boot_on=1;

linux_noffset=fdt_subnode_offset(fit,conf_noffset,"linux");//①
if(linux_noffset>0){
ret=brought_up_amp(fit,linux_noffset,&g_bootcpu,1);
if(ret)
returnret;
}

for(loadables_index=0;//②
uname=fdt_stringlist_get(fit,conf_noffset,
FIT_LOADABLE_PROP,loadables_index,NULL),uname;
loadables_index++){
cpu_noffset=fit_image_get_node(fit,uname);
if(cpu_noffset< 0)
   return cpu_noffset;

  ret = brought_up_amp(fit, cpu_noffset, &g_bootcpu, 0);
  if (ret)
   return ret;
 }

    ....省略

 return 0;
}

内核启动流程--核心配置参数获取

我们获取了加载项节点之后,从节点中获取其加载参数,获取方式跟设备树树获取一致。

通过smc_cpu_on()启动核心

staticintbrought_up_amp(void*fit,intnoffset,
boot_cpu_t*bootcpu,intis_linux)
{

....省略

desc=fdt_getprop(fit,noffset,"description",NULL);
cpu=fit_get_u32_default(fit,noffset,"cpu",-ENODATA);
hyp=fit_get_u32_default(fit,noffset,"hyp",0);
thumb=fit_get_u32_default(fit,noffset,"thumb",0);
entry=load=fit_get_u32_default(fit,noffset,"load",-ENODATA);
us=fit_get_u32_default(fit,noffset,"udelay",0);
boot_on=fit_get_u32_default(fit,noffset,"boot-on",1);
fit_image_get_arch(fit,noffset,&arch);
fit_image_get_type(fit,noffset,&type);
fit_image_get_data_size(fit,noffset,&data_size);
memset(&args,0,sizeof(args));

....省略

/*bootnow*/
ret=smc_cpu_on(cpu,pe_state,entry,&args,is_linux);
if(ret)
returnret;
exit:
if(us)
udelay(us);

return0;
}

内核启动流程--内核启动

检测pe状态,如果目标pe状态是默认的arch状态,则直接给cpu通电

如果非Linux系统则跳转到finish下,直接启动启动内核。

如果是Linux系统需要设置启动参数,然后再启动内核。

staticintsmc_cpu_on(u32cpu,u32pe_state,u32entry,
boot_args_t*args,boolis_linux)
{
....省略

/*iftargetpestateisdefaultarchstate,powerupcpudirectly*/
if(is_default_pe_state(pe_state))
gotofinish;

ret=sip_smc_amp_cfg(AMP_PE_STATE,cpu,pe_state,0);
if(ret){
AMP_E("smcpe-state,ret=%d
",ret);
returnret;
}

/*onlylinuxneedsbootargs*/
if(!is_linux)
gotofinish;

ret=sip_smc_amp_cfg(AMP_BOOT_ARG01,cpu,args->arg0,args->arg1);
if(ret){
AMP_E("smcbootarg01,ret=%d
",ret);
returnret;
}

ret=sip_smc_amp_cfg(AMP_BOOT_ARG23,cpu,args->arg2,args->arg3);
if(ret){
AMP_E("smcbootarg23,ret=%d
",ret);
returnret;
}

finish:
ret=psci_cpu_on(cpu,entry);
if(ret){
printf("cpuupfailed,ret=%d
",ret);
returnret;
}
printf("OK
");

return0;
}

多核启动效果

多核方案:3kernel(SMP) + 1RT-Thread

我们需要准备两个串口,一个为Linux端的终端信息打印(UART2),一个为RT-Thread端的终端信息打印(UART4)

YY3568已经将所有的串口引出,所以我们调试很方便,接线图如下:

2a2f738e-dba1-11ee-a297-92fbcf53809c.png

运行效果:

2a3bd1ba-dba1-11ee-a297-92fbcf53809c.jpg





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 以太网
    +关注

    关注

    40

    文章

    5076

    浏览量

    166234
  • 固态硬盘
    +关注

    关注

    11

    文章

    1356

    浏览量

    56496
  • PCIe接口
    +关注

    关注

    0

    文章

    111

    浏览量

    9529
  • Rockchip
    +关注

    关注

    0

    文章

    66

    浏览量

    18312
  • RK3568
    +关注

    关注

    4

    文章

    433

    浏览量

    4126

原文标题:YY3568多核异构(Linux+RT-Thread)--启动流程

文章出处:【微信号:风火轮技术团队,微信公众号:风火轮技术团队】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请教一下RK3568开发板的启动流程是怎样的呢

    请教一下RK3568开发板的启动流程是怎样的呢?
    发表于 03-02 06:50

    RK3568开发板如何支持NFS服务呢

    硬件平台:OK3568-C开发板 操作系统: Linux4.19.206本文硬件平台采用飞凌嵌入式RK3568开发板,主要讲解RK3568
    发表于 11-25 16:04

    RK3568开发板Linux系统如何修改异显呢

    本文硬件平台采用飞凌嵌入式RK3568开发板,主要讲解Linux系统 RK3568开发板如何修改异显。RK3568 Linux 修改异显使用
    发表于 12-13 17:14

    toybrick_RK3568X开发板:跑通 android 开发流程

    前段时间买了一块官方的开发板,瑞芯微的 RK3568 芯片的 toybrick TB-RK3568X 开发板,配置是 4G 内存,32G 存储,想用这个
    发表于 11-16 21:30

    RK3568开发板数据手册

    RK3568 开发板主控采用的是瑞芯微 A55 64 位四核处理器 RK3568,其主频高达 2.0 GHz。集成了 Mali G52 2EE 图形处理器,支持 4K 解码和 1080P 编码
    发表于 08-30 11:56 23次下载

    【ROC-RK3568-PC开发板试用体验】Firefly ROC-RK3568-PC开发板初探

    本文来源电子发烧友社区,作者:ouxiaolong, 帖子地址: https://bbs.elecfans.com/jishu_2303714_1_1.html ROC-RK3568-PC开发板
    的头像 发表于 10-18 16:11 3050次阅读
    【ROC-<b class='flag-5'>RK3568</b>-PC<b class='flag-5'>开发板</b>试用体验】Firefly ROC-<b class='flag-5'>RK3568</b>-PC<b class='flag-5'>开发板</b>初探

    瑞芯微rk3568开发板原理图

    瑞芯微rk3568 开发板 原理图工程文件AD格式
    发表于 04-24 14:12 66次下载

    RK3568开发板借助 U 盘或 TF 卡拷贝程序到开发板

    RK3568开发板借助 U 盘或 TF 卡拷贝程序到开发板
    的头像 发表于 05-20 18:01 715次阅读
    <b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>借助 U 盘或 TF 卡拷贝程序到<b class='flag-5'>开发板</b>上

    瑞芯为RK3568开发板搭建NFS服务器

    瑞芯为RK3568开发板搭建NFS服务器
    的头像 发表于 05-24 14:10 799次阅读
    瑞芯为<b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>搭建NFS服务器

    迅为RK3568开发板实现的NVR/XVR方案

    迅为RK3568开发板实现的NVR/XVR方案
    的头像 发表于 06-14 18:00 804次阅读
    迅为<b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>实现的NVR/XVR方案

    【教程上新】基于迅为iTOP-RK3568开发板的OpenCV开发手册

    【教程上新】基于迅为iTOP-RK3568开发板的OpenCV开发手册
    的头像 发表于 02-08 15:22 549次阅读
    【教程上新】基于迅为iTOP-<b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>的OpenCV<b class='flag-5'>开发</b>手册

    瑞芯微RK3568主板开发板PET_RK3568_P01简述

    瑞芯微RK3568主板开发板PET_RK3568_P01简述
    的头像 发表于 08-08 11:41 1764次阅读
    瑞芯微<b class='flag-5'>RK3568</b>主板<b class='flag-5'>开发板</b>PET_<b class='flag-5'>RK3568</b>_P01简述

    迅为RK3568开发板GPIO之外接模块

    迅为RK3568开发板GPIO之外接模块
    的头像 发表于 08-24 17:41 667次阅读
    迅为<b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>GPIO之外接模块

    迅为RK3568开发板可实现多屏异显控方案

    迅为RK3568开发板可实现多屏异显控方案
    的头像 发表于 07-15 17:30 1324次阅读
    迅为<b class='flag-5'>RK3568</b><b class='flag-5'>开发板</b>可实现多屏异显控方案

    RK3568开发板规格书

    RK3568开发板规格书
    发表于 03-23 15:28 64次下载