计划1阶段达成目标
- cpu0跑Linux、cpu1跑裸机程序
- cpu1的程序由cpu0启动linux后再进行加载,这样方便日后的版本管理
- cpu0和cpu1各控制一个串口,便于调试
- cpu0和cpu1之间应当进行至少一次通信用于验证
- 基于openamp框架
基于硬件为黑金alinx开发板,板载由ps_uart0/ps_uart1用于验证,软件环境为2018.2
开始
硬件环境准备
vivado构建一个用于验证的最小系统,包含uart0/1、eth、sd、gpio即可
然后,export hardware用于petalinux开发cpu0,launch sdk用于开发cpu1的裸机程序
cpu0环境
- 软件的整体框架基于openamp进行参考ug1186
https://china.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug1186-zynq-openamp-gsg.pdf
petalinux导入硬件等等不再赘述,参照文档设备树中增加如下,bootargs增加在启动阶段只启动一个核心的操作
/ {
chosen {
bootargs = "console=ttyPS0,115200 maxcpus=1 clk_ingore_unused earlyprintk";
stdout-path = "serial0:115200n8";
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
rproc_0_reserved: rproc@3e000000 {
no-map;
reg = <0x3e000000 0x01000000>;
};
};
amba {
elf_ddr_0: ddr@0 {
compatible = "mmio-sram";
reg = <0x3e000000 0x400000>;
};
};
remoteproc0: remoteproc@0 {
compatible = "xlnx,zynq_remoteproc";
firmware = "firmware";
vring0 = <15>;
vring1 = <14>;
srams = <&elf_ddr_0>;
};
};
其他的rootfs的配置参考文档ug1186-->Building Linux Application that uses RPMsg in kernel space章节
cpu0的debug口在petalinux中配置为uart1
linux下的demo代码位于
https://github.com/Xilinx/meta-openamp
需要说明的是这个demo基于内核module编译的将其添加到petalinux的app中编译就可以了
直接gcc的话需要解决一堆依赖
此外还需在内核的配置中加入
备注1 重要,这个操作应该会增加一部分功耗,但是如果不禁掉power管理的话,cpu1的裸核无法进行cpu0没初始化外设的使用,后续再看这个问题
xsdk的裸核开发
直接参照ug1186的-->Building Remote Applications in Xilinx SDK章节就可以了
点击配置打印裸机使用uart0,或者直接更改xparameters.h的参数也可以
build生成 .elf可执行文件
上机验证
参考ug1186-->Running the Echo Test章节
这块是一个基于echo_test的简单改动,cpu0将hello amp周期发送给cpu1,cpu1将受到的数据直接原样返回
找到了备注1的解决方案
在裸机中重新对时钟初始化,没有找到API,直接撸的datasheet,对寄存器进行的配置
int uart_init(void)
{
u32 RegValue;
/* ps7_clock_init_data_3_0 */
RegValue = Xil_In32(0xF8000008);
RegValue &= ~0x0000FFFF;
RegValue |= 0x0000DF0D;
Xil_Out32(0xF8000008, RegValue);
/* Only Enable Uart1 Reference Clock */
RegValue = Xil_In32(0xF8000154);
RegValue &= ~0x00003F33;
RegValue |= 0x00000A03;
Xil_Out32(0xF8000154, RegValue);
RegValue = Xil_In32(0xF800012C);
RegValue &= ~0x01FFCCCD;
RegValue |= 0x017D444D;
Xil_Out32(0xF800012C, RegValue);
RegValue = Xil_In32(0xF8000004);
RegValue &= ~0x0000FFFF;
RegValue |= 0x0000767B;
Xil_Out32(0xF8000004, RegValue);
return XST_SUCCESS;
}