ZYNQ中两个CPU分别跑linux和裸机代码AMP
1.问题
学习正点原子ZYNQ的时候发现了AMP这个东西,分别可以实现两个cpu跑两个不同的系统,可以实现CPU0跑linux,CPU1跑裸机或者RTOS,于是开始根据正点原子给的文档尝试实现linux+裸机的AMP。
跟着教程的时候发现这么几个问题:
1.分配设备树memory后linux分配的内存仍为最大,导致linux驱动加载时程序卡死,出现跳转空指针现象。
2.CPU1裸机代码无法调用AXI总线,导致程序卡死。但在uboot、加载kernel之前能够正常运行CPU0和CPU1代码。
3.加载linux驱动失败。
2.ZYNQ镜像编译
zynq的uboot、kernel、dtb、rootfs均是参考正点原子ZYNQA盘《3_领航者ZYNQ之嵌入式Linux开发指南_V2.2.pdf》的第二十章 另一种方式编译ZYNQ镜像
3.AMP搭建
linux搭建参考正点原子ZYNQA盘\9_增值资料\2,扩展资料\正点原子ZYNQ双核AMP通信示例_V1.0.pdf
4.问题解决
问题1:
发现过程
我手上的的是一块ZYNQ7010的板子,我将DDR的前256MB分配给了linux,剩下的分配给了裸机代码。
按照[3.AMP搭建](## 3.AMP搭建)中的3.2 制作 BOOT.BIN 启动开发板修改memory设备树之后
memory {
device_type = "memory";
reg = <0x0 0x10000000>;
};
insmod命令加载文档中的驱动,发现kernel报错指向空指针,kernel崩溃,板子卡死。
后面在驱动程序中debug,发现程序中的share_meme_addr
share_meme_addr = ioremap(SHARE_MEM_ADDR, 4); // 将共享内存物理地址转换为虚拟地址
虚拟地址映射后返回为NULL空指针,重新复位开机。
通过命令free -m
查看到linux内存分配仍为最大内存
前面修改的设备树memory节点并没有生效,且查看设备树文件夹下memory节点
root@Petalinux_uboot:/proc/device-tree/memory# xxd reg
00000000: 0000 0000 2000 0000 .... ...
查看到memory节点的大小仍为0x2000 0000,也就是 512MB大小,并没有通过设备树获取,这是因为内核解析数据的时候使用的是uboot传入的memory数据
内存信息生效的优先级:ATAG_CMDLINE类型的tag > ATAG_MEM类型的tag > 设备树"/memory"节点
具体文章参考:linux内存管理——内存大小、起始地址的解析与修改文中详细提到了memory解析顺序
这导致了在ioremap时出现了内存冲突,虚拟内存映射失败,返回空指针
解决方法
1.在uboot的bootargs中添加
mem=256M
2.在设备树中的bootargs添加mem=256M
chosen {
bootargs = "mem=250M console=ttyPS0,115200 maxcpus=1 earlyprintk root=/dev/mmcblk0p2 rw rootwait";
stdout-path = "serial0:115200n8";
};
开机后再次启动驱动能够正常分配内存
问题2:CPU1无法使用PL端的AXI接口
发现过程
开机之后当程序运行到
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED);
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, LED);
程序卡死
后续发现当没有启动kernel的时候是能正常运行CPU0和CPU1的,且CPUI读写axi接口正常,一启动kernel就会卡死在上面的两个函数中。
查询了网上能查到的所有信息都没类似问题的解决方案,于是开始排除kernel配置问题
看到了kernel默认打开了功耗管理(上图中已经关闭了所有功率管理的选项),在kernel中 power management
打开后,系统会自动管理没有用到模块的时钟,或关闭时钟或减小运行频率,由于linux一开始并没有调用axi的资源,于是linux默认关闭了axi的时钟。参考文档:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841827/Zynq-7000+Power+Management
这导致CPU1对AXI读写数据是,由于AXI没有分配时钟或者时钟频率不对,导致读写出错卡死。
解决方法
关闭power management
中所有的选项,重新保存退出,编译zImage
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j10
重启开发板,CPU1正常使用AXI资源。
问题3
发现问题
insmod加载.ko驱动文件时报错
unknown symbol in module or invalid parameter
解决问题
编译驱动时
KERN_DIR := /home/user/kernel/linux-xlnx-xilinx-v2018.3
obj-m := axi_gpio.o
all:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` clean
1.可能编译驱动时的内核版本和板载的驱动版本不一致,重新修改makefile为与板载一致的内核源码
2.可能是修改内核之后编译之后的板载配置和驱动编译时的板载配置不一致导致的,重新编译驱动文件即可。