本文重點(diǎn)介紹RK3568內(nèi)置的MCU與AP之間的通信功能,首先介紹RPMsg的框架,然后介紹MCU端RPMSG的構(gòu)建方法,最后介紹AP端的RPMSG的配置方法,并進(jìn)行MCU和AP之間通信的演示。
RK3568 MCU開發(fā)的入門介紹可以參考筆者的上一篇文章。
硬件準(zhǔn)備
首先介紹一下硬件。主板為風(fēng)火輪科技的YY3568開發(fā)板,主控RK3568。此開發(fā)板的相關(guān)介紹可以參考
https://wiki.youyeetoo.cn/zh/YY3568
RK3568的MCU核心需要使用串口調(diào)試,筆者這里使用的是UART4,這里也可以選擇其他的,不要跟AP核心的調(diào)試串口UART2沖突就行。 UART4的位置如下
RPMsg框架介紹
RPMsg(Remote Processor Messaging)是一種基于virtio的消息傳遞總線,專為異構(gòu)處理器系統(tǒng)之間的通信設(shè)計(jì)。其定義了一個(gè)標(biāo)準(zhǔn)化的通信接口,使得不同架構(gòu)的核心能夠方便地進(jìn)行通信。
RK3568上面有ARM核心和RISCV核心,需要使用RPMsg這種標(biāo)準(zhǔn)化的接口,這樣可以不用考慮大小端轉(zhuǎn)換等兼容問題。在RK3568上面,AP核心是RPMSG的master端,而MCU核心則是remote端。
使用RPMSG通信時(shí),通常會(huì)從VirtIo-Ring緩沖區(qū)中申請(qǐng)一塊buffer,然后將這個(gè)buffer作為共享內(nèi)存,在兩個(gè)核心之間傳輸數(shù)據(jù)。另外二者之間通信時(shí),還需要中斷通知對(duì)方有數(shù)據(jù)到達(dá)。以master向remote發(fā)數(shù)據(jù)為例,
1. Master Core發(fā)送時(shí),從 vring0中取得一塊 buffer,再將消息按照 RPMsg協(xié)議填充
2.將處理好的內(nèi)存 buffer鏈接到vring1
3.觸發(fā)中斷通知 Remote Core有數(shù)據(jù)處理待處理
這個(gè)通信流程如下圖所示
反過來(lái)也是一樣的
在RK3568,可以選擇軟中斷,或者mailbox實(shí)現(xiàn)這個(gè)中斷,通常的做法是選擇mailbox,這樣還可以在觸發(fā)中斷時(shí)額外附帶少量信息。
MCU端RPMSG適配
RK SDK里面提供了兩個(gè)可選的rpmsg組件,分別是由NXP主導(dǎo)開發(fā)的rpmsg-lite,以及openamp項(xiàng)目下面的rpmsg。前者比較簡(jiǎn)單,不需要太多額外的組件,因此選擇前者。其工程路徑為
external/hal/middleware/rpmsg-lite
如果想要進(jìn)一步了解rpmsg-lite,其原始的git項(xiàng)目地址為
https://github.com/nxp-mcuxpresso/rpmsg-lite
原始的rpmsg-lite工程僅支持NXP的異構(gòu)處理器,如imx6/imx7/imx8等,RK在此基礎(chǔ)上增加了RK3562/RK3568/RK3588等處理器的支持。
不過RK3568僅支持AP運(yùn)行這個(gè)rpmsg-lite,因此,這里我們要添加支持RK3568 MCU的相關(guān)源碼。具體步驟如下
1、打開external/hal/middleware/rpmsg-lite/lib/include/rpmsg_compiler.h,增加riscv處理器的MEM_BARRIER實(shí)現(xiàn)
RISCV處理器使用fence作為內(nèi)存屏障指令,功能類似ARM的dsb指令。
2、屏蔽rpmsg-lite/lib/init/platform/RK3568/rpmsg_init.c中的功能,這個(gè)源文件中的API專門用于AP運(yùn)行bare-metal時(shí)使用rpmsg-lite的,這里使用MCU,需要將其禁用
3、接下來(lái)修改
rpmsg-lite/lib/rpmsg_lite/porting/platform/RK3568/rpmsg_platform.c
文件。這個(gè)文件就是實(shí)現(xiàn)上述rpmsg的傳輸流程,即通過mbox觸發(fā)中斷,然后用virtio來(lái)傳輸數(shù)據(jù)。其中virtio傳輸數(shù)據(jù)的功能已經(jīng)由rpmsg-lite實(shí)現(xiàn)了,這里只需要調(diào)用。
platform_init platform_deinit函數(shù)是用于平臺(tái)初始化的,在rpmsg功能init和deinit的時(shí)候會(huì)調(diào)用這兩個(gè)函數(shù),保持跟原來(lái)的一致即可
platform_map_mem_region
platform_cache_all_flush_invalidate
platform_cache_disable
platform_vatopa
platform_patova
幾個(gè)函數(shù)在MCU上沒有特殊實(shí)現(xiàn),保持跟原來(lái)的一致
platform_interrupt_enable
platform_interrupt_disable
兩個(gè)函數(shù)用于開啟和關(guān)閉mbox中斷,RISCV和ARM中斷控制器不同,需要將原來(lái)的GIC的API換成INTMUX的API。此外,此處要選擇一個(gè)mbox通道,筆者選用ch3,后續(xù)AP Linux端也要配置同樣的通道。
platform_notify函數(shù)為virtqueue的回調(diào)函數(shù),用于在接收數(shù)據(jù)的時(shí)候產(chǎn)生一個(gè)中斷。這里實(shí)現(xiàn)是要通過mbox應(yīng)答AP,這樣AP才認(rèn)為收到了數(shù)據(jù)
platform_init_interrupt用于平臺(tái)初始化中斷,這里的實(shí)現(xiàn)則是初始化mbox,具體修改如下
platform_global_isr_disable
platform_global_isr_enable
用于開啟和關(guān)閉全局中斷,這里使用默認(rèn)的實(shí)現(xiàn)即可
然后要定義mbox的通道信息
rpmsg_remote_cb函數(shù)屬于rpmsg的回調(diào),具體由上述的rpmsg_mbox_isr調(diào)用,這兩個(gè)函數(shù)實(shí)現(xiàn)如下
修改完上面的rpmsg之后,還需要實(shí)現(xiàn)一個(gè)測(cè)試demo,對(duì)前一篇文章介紹的external/hal/project/rk3568-mcu目錄做修改
1.增加mcu對(duì)rpmsg的共享內(nèi)存區(qū)域的訪問。rpmsg使用的共享內(nèi)存區(qū)域由AP端Linux指定,作為預(yù)留內(nèi)存。修改GCC目錄下面的 Makefile,改用自定義的ld文件。這里同步打開rpmsg-lite的mk文件編譯
這個(gè)ld文件可以從lib/CMSIS/Device/RK3568/Source/Templates/GCC復(fù)制一個(gè)過來(lái),然后添加如下內(nèi)容
2.修改testdemo,增加rpmsg測(cè)試功能
這個(gè)測(cè)試demo實(shí)現(xiàn)的功能是remote端收到數(shù)據(jù)后,就給master端發(fā)送一條固定內(nèi)容的數(shù)據(jù)
先增加如下所示宏定義
然后添加一個(gè)名為 rpmsg_linux_test的測(cè)試函數(shù)
實(shí)現(xiàn)如下
這里使用rpmsg_lite_remote_init初始化,這個(gè)初始化會(huì)調(diào)用上述rpmsg_platform.c中實(shí)現(xiàn)的API,就是初始化mbox和中斷
然后使用rpmsg_lite_wait_for_link_up,這個(gè)API會(huì)循環(huán)等待AP Linux端的mbox初始化完成才返回
然后使用rpmsg_ns_bind指定rpmsg回調(diào)函數(shù)為rpmsg_ns_cb。下面看下rpmsg_ns_cb的實(shí)現(xiàn),在進(jìn)入此回調(diào)之后,同時(shí)會(huì)向master端,也就是AP Linux端發(fā)送一條數(shù)據(jù)
然后使用rpmsg_lite_send發(fā)送一條數(shù)據(jù)給master端,發(fā)起第一次通信
到這里,mcu端的修改就完成了,按照上一篇文章介紹的方法編譯,下載到板上。
AP端RPMSG適配
AP端的Linux上已經(jīng)有完整的rpmsg框架了,這里只需要修改下配置即可。首先在defconfig文件中打開如下內(nèi)容,這里將支持mbox觸發(fā)rpmsg相關(guān)中斷的源碼編譯進(jìn)內(nèi)核,將測(cè)試demo編譯為模塊
然后在設(shè)備樹打開rpmsg的配置,注意rpmsg-tx的通道需要為3,跟上面MCU配置的一樣
完成這些配置之后,編譯出內(nèi)核,然后燒錄到板上,同時(shí)將kernel/drivers/rpmsg/rockchip_rpmsg_test.ko通過adb/ssh等方式推到板上。
MCU與AP rpmsg通信演示
按上面的步驟燒錄amp和kernel后,重啟板子,可以看到MCU端串口有如下打印信息
AP端的dmesg log有如下信息
然后在AP端加載 rockchip_rpmsg_test.ko
可以看到這個(gè)信息跟源碼里面配置的是一致的
說明MCU確實(shí)有收到AP的數(shù)據(jù),并且發(fā)送的數(shù)據(jù)能被AP正確接收
總結(jié)
本文介紹RK3568內(nèi)置的MCU與AP之間的通信功能,MCU端使用rpmsg-lite組件,AP端使用Linux自帶的rpmsg框架,中斷依靠mbox實(shí)現(xiàn),此種方式可以在異構(gòu)核之間可靠傳輸大量數(shù)據(jù)。
審核編輯 黃宇
-
mcu
+關(guān)注
關(guān)注
146文章
17148瀏覽量
351186 -
ARM
+關(guān)注
關(guān)注
134文章
9094瀏覽量
367540 -
RISC-V
+關(guān)注
關(guān)注
45文章
2277瀏覽量
46158 -
RK3568
+關(guān)注
關(guān)注
4文章
514瀏覽量
5048
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論