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

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

3天内不再提示

YY3568多核异构(Linux+RT-Thread)--启动流程

Rice嵌入式开发技术分享 来源:Rice嵌入式开发技术分享 作者:Rice嵌入式开发技术 2024-03-07 08:41 次阅读

概要

上一篇文章,介绍了多核异构的方案,RPmsg-lite多核通信框架的内容。--《多核异构通信框架(RPMsg-Lite)》

本篇文章我们主要来讲讲RK3568上的多核加载流程,实验的板子:风火轮科技的YY3568开发板。

7989081c-dc1b-11ee-b759-92fbcf53809c.jpg

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。

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

79983cce-dc1b-11ee-b759-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()启动内核。

79a39182-dc1b-11ee-b759-92fbcf53809c.jpg

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

79b0c384-dc1b-11ee-b759-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=%dn",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=%dn",ret); returnret; } ret=sip_smc_amp_cfg(AMP_BOOT_ARG23,cpu,args->arg2,args->arg3); if(ret){ AMP_E("smcbootarg23,ret=%dn",ret); returnret; } finish: ret=psci_cpu_on(cpu,entry); if(ret){ printf("cpuupfailed,ret=%dn",ret); returnret; } printf("OKn"); return0; }

多核启动效果

我们多核的方案:3kernel(SMP) + 1RT-Thread,

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

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

79b52b9a-dc1b-11ee-b759-92fbcf53809c.png

运行效果:

79b9ba48-dc1b-11ee-b759-92fbcf53809c.jpg

5. 视频演示

审核编辑 黄宇

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

    关注

    87

    文章

    10990

    浏览量

    206738
  • RT-Thread
    +关注

    关注

    31

    文章

    1149

    浏览量

    38906
收藏 人收藏

    评论

    相关推荐

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

    YY3568主板基于 Rockchip RK3568 芯片平台,四核 64位 Cortex-A55 核,主频最高达 2GHz,集成双核心架构GPU以及高效能NPU,芯片性能优异。
    的头像 发表于 03-06 18:17 2004次阅读
    讲讲RK<b class='flag-5'>3568</b>开发板上的<b class='flag-5'>多核</b>加载<b class='flag-5'>流程</b>

    JH-7110现已支持AMP双系统(Linux + RT-Thread

    Linux + RT-Thread)的演示示例。 核间通信方式 两核通信使用标准的virtio-base的RPMsg(Remote Processor Messaging)协议,它定义了异构
    发表于 01-27 15:11

    使用YY3568开发板部署AI能力

    YY3568开发板是 「风火轮科技」 基于Rockchip RK3568 芯片平台设计的开发板,四核 64Cortex-A55 核,主频最高达 2GHz,集成双核心架构GPU以及高效能NPU,芯片
    的头像 发表于 11-28 10:59 1299次阅读
    使用<b class='flag-5'>YY3568</b>开发板部署AI能力

    【风火轮YY3568开发板免费体验】+ YY3568安装运行Home-Assistant服务端

    按照wiki教程刷入Debian镜像,根据硬件配置选择了ds0+wifi的配置。 插入USB鼠标键盘,设置无线网络。 在PC电脑上登录路由器的管理页面,查看YY3568的IP地址,如图
    发表于 11-14 11:49

    【风火轮YY3568开发板免费体验】+ YY3568安装运行Unity的自制游戏教程范例

    YY3568的Android系统安装三维游戏引擎Unity的2D/3D入门教程 Beginner’s Tutorial YY3568已经适配好了的Android-11的系统,并能流畅运行App。由于
    发表于 11-14 11:44

    【风火轮YY3568开发板免费体验】第五章:在 Solus 上运行 npu 例程并搭建 nfs 环境实现在 YY3568 上实际运行 npu 例程

    经过前面几章的铺垫,接下来的章节就开始进入到 NPU 相关的开发测试了。本章呢,记录下我分别在 Solus 上对 npu 相关例程的仿真以及实际在 YY3568 上进行的 npu 例程测试,本章
    发表于 09-11 15:44

    【风火轮YY3568开发板免费体验】第二章:YY3568 ffmpeg 编译以及 nanogui 移植

    on YY3568, but crashed: xdg_surface@31: error 3: xdg_surface must not have a buffer at creation 后来采用
    发表于 09-11 15:29

    【风火轮YY3568开发板免费体验】第六章:在Solus上运行自定义模型并迁移到YY3568对比测试

    本章介绍如何使用自己的模型并迁移到YY3568上面。
    的头像 发表于 08-27 00:55 765次阅读
    【风火轮<b class='flag-5'>YY3568</b>开发板免费体验】第六章:在Solus上运行自定义模型并迁移到<b class='flag-5'>YY3568</b>对比测试

    【风火轮YY3568开发板免费体验】第五章:在 Solus 上运行 npu 例程并搭建 nfs 环境实现在 YY3568 上实际运行 npu 例

    YY3568 NPU 相关的环境搭建以及示例测试
    的头像 发表于 08-19 02:41 1383次阅读
    【风火轮<b class='flag-5'>YY3568</b>开发板免费体验】第五章:在 Solus 上运行 npu 例程并搭建 nfs 环境实现在 <b class='flag-5'>YY3568</b> 上实际运行 npu 例

    【风火轮YY3568开发板免费体验】使用之二:系统测试安卓

    开发板,如下图所示: 按住设备上的 RECOVERY (恢复)键并保持接上电源 大约两三秒钟后,松开 RECOVERY 键 UART DEBUG测试: YY3568
    发表于 08-09 21:01

    【风火轮YY3568开发板免费体验】第一章:开发环境搭建,系统替换为原生Linux

    记录编译sdk并替换YY3568出厂安卓系统的笔记。
    的头像 发表于 08-09 18:11 990次阅读
    【风火轮<b class='flag-5'>YY3568</b>开发板免费体验】第一章:开发环境搭建,系统替换为原生<b class='flag-5'>Linux</b>

    【风火轮YY3568开发板免费体验】开箱篇 -----最好的RK3568开发板赏析

    风火轮YY3568开发板采用RK3568芯片设计,RK3568明星芯片是一款瑞芯微电子定位中高端的通用型SoC。该芯片采用了先进的22nm工艺,拥有四个Cortex-A55核心和一个
    发表于 08-07 10:00

    【新品体验】风火轮YY3568开发板免费体验

    YY3568主板基于 Rockchip RK3568 芯片平台,四核 64位 Cortex-A55 核,主频最高达 2GHz,集成双核心架构GPU以及高效能NPU,芯片性能优异。开发板功能接口丰富
    发表于 06-25 14:35

    多核CPU的启动方式

    多核 CPU 的启动方式 嵌入式系统的启动的基本流程是先运行 bootloader ,然后由 bootloader 引导启动 kernel
    的头像 发表于 06-22 10:04 1150次阅读

    风火轮科技又发新品啦--YY3568开发板

    风火轮近来又推出一款新的嵌入式主板YY3568,它是一款基于瑞芯微RK3568 4核处理器的ARM主板,性价比极高;现在瑞芯微的旗舰款是rk3588主打性能,这个rk3568是主打性价比的定位,接口
    的头像 发表于 05-05 16:41 643次阅读
    风火轮科技又发新品啦--<b class='flag-5'>YY3568</b>开发板