前言
ZYNQ实现CAN总线功能是项目A中关键部分,具体如何实现相关功能还需要在实践中思考。前期主要采用Opencores的CAN开源资源,但是在搭建系统过程中发现不少问题,比如无法编绎。目前的verilog设计和调试经验不足,因此选择CAN IP方案。通过QQ群途径购买了IP资源后,开始尝试使用现有的ZYNQ开发板实现基础功能(前期使用FPGA+microblaze)
- 1 学习小梅哥视频,了解zynq简单工作搭建的流程,比如点亮LED。
- 2 了解ZYNQ添加CAN软核流程,实现CAN简单收发
- 3 了解CAN中断功能,使用CANBUS等实现基本功能测试
- 4 总线协议转换功能【预期】
- 5以太网与CAN协议转换【预期】
1 ZYNQ-GPIO 功能
参考小梅哥的视频搭建ZYNQ-PS应用系统,vitis没有出现ps7_gpio_0这个硬件。这导致vitis软件编程时无法识代码中的XPAR_GPIO_0_BASEADDR 。于是考虑重新梳理流程,将问题定位到某个流程中。
zynq Block Design框图打勾:
缺少模块,没有添加PS端的GPIO。在点击vivado diagram中的zynq模块时,会出现如下定制化框图。如果选中GPIO,相应的位置会打上钩。值得注意的是,在keil中初始化stm32时,在配置GPIO时需要明确GPIO是否复用;而在ZYNQ中,所有的MIO与GPIO是对应的。此外,ZYNQ中的所有GPIO时钟是统一的,甚至不用在初始化中单独指定。以上说明PS系统的搭建流程比较简单,外设初始化可以图形参数化设计。
out-of-data字符提示
更新zynq系统的硬件文件后,hardware specification显示ps7_gpio_0命名,说明GPIO添加成功。但是,system- can-wrapper右侧出现out-of-date标记。尝试右键点击update没有效果,直到点出build project。这个操作说明wrapper project与application project不同,需要单独编译。这个操作意味着,只要修改一处PS硬件工程,就需要做出添加、修改模块–validate design–generate bitsteam–program device–export hardware–update hardwate specification–build project等七个基本操作。这些繁琐的流程直接影响调试效率,因此在设计系统时需要细心检查问题,避免后期大量修改浪费精力。
Makefile42 error
编绎之后,出现error错误,内容如下图。由于前面主要是针对include-xgpiops.h出现引用问题,但是现在这个警告消失,因此暂时不处理error问题。问题在于,当准备run configuration 时,配置菜单缺少xilinx C/C++ Application(GDB)选项。这直接导致无法运行程序。后来发现,这个错误可能是前期编绎产生的问题。尝试重新更新系统、编绎软件之后,问题消失。
针对缺少GDB选项问题,在这个帖子中发现,system debugger本身就是选择项。这意味着面对很多软件问题,可以选择直接路过,而不是陷入其中。
DONE pin no high
在使用system debugger时,出现DONE pin no high错误。一篇文章提醒我,可以先在vivado 下载bit流,结果测试成功。这说明vitis软件稳定性不好,后期也选择使用SDK。
QSPI启动模式
在下载程序后,LED可以闪烁。但是随后发现,在修改程序之后,LED的闪烁频率也不变。最后调整C语言逻辑为**只点亮不闪烁**,LED仍然闪烁,这个现象说明程序下载出现问题。后来猜测是**下载配置**问题,因为小梅哥板子在启动时,需要设置为**QSPI模式**,方便测试板子功能。在JTAG模式下,才能下载用户程序。这意味着,没有熟悉开发板的特点,盲目使用是不合适的。
在设置为JTAG启动模式后,run as配置选项并没有出现。在点击explorer的菜单时,发现两级目录的run as是不同的。最高一级的CAN system是系统层级,针对两个cpu模块的整体调试对象,下一层级是应用层级,主要针对单个cpu的应用。
no target found with
经历以上几轮问题,现在似乎不存在什么问题。但是,当运行程序时,还是出现了新的APU错误。初步检索网页,没有实际帮助,程度也无法进行下去。问题已经起到死胡同,于是不得不到群里发帖求助。同时回顾整个流程,发掘可能存在问题的地方,这又是一番时间。
资讯的观点有两个。一是软件兼容性问题,需要更换当前使用的vitis为sdk,相当于要使用2018版本的vivado。二是DDR和platform设置问题。在回顾搭建流程,我确实发现DDR的编号选择错误。由于我做事容易忽略对象的细节,所以这种错误发生频率比较高。于是再重新选择DDR编号后,我再次更新了所有搭建流程。
现实是,重新更新hardware platform后,程序虽然可以下载而且没有之前的APU错误,但是LED仍然没有任何变化。目前假设硬件没有问题,主要定位问题到软件逻辑等。
bug as
原本下载程度的问题一直存在,程序也是用得小梅哥的资源,无法定位问题。突然想到stm32编程时,当无法定位软件问题时,会使仿真功能定位软件位置,比如发现是否程序进入main主循环。于是我点击页面的bug控件,同时选择了bug as功能。搞笑的是,我不会使用相关功能,甚至不知道如何添加断点。转机之外在于,当我删除多余的窗口时,又好奇的重新run as,没有想到程序又成功了!在更新了几次程序的sleep函数时间间隔后,LED发生相应的变化,说明程序工作。
这次问题的解决让人很是迷惑,不明白到底是哪里问题。目前的解释是debugger功能打破了某种程序下载bug。这个问题只是暂时解决,后期可能还会出现。不过目前权当休息,可以继续接下来的安排。【以后定位软件问题时,需要养成记录软件调整的习惯。】
gpio功能测试
注意到利用逻辑分析仪可以检测GPIO口信号,同时修改C语言程序,看看是否能够更改GPIO控制,于是重新用回逻辑分析仪。结果显示,xilinx的usleep函数延时精度较高,不超过1ms。后期,在测试板子uart和CAN总线功能时,逻辑分析仪的作用都会比较大。
库函数使用
考虑到后期编写程序会使用库函数,尤其CAN外设这种比较复杂的对象【以前确实无法理解驱动结构体指针】,所以将寄存器代码调整为库函数代码。编码过程中,发现非常容易出现小细节问题。比如MIO7是LED引脚号,但是函数中我将数字写为6,明显没有注意到mio6。
//u32 reg_val = 0;
//u32 Data = 0;
//设置IO方向,bit7的方向为输出
//reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR+XGPIOPS_DIRM_OFFSET);
//Data = reg_val |(1<<8);
//Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR+XGPIOPS_DIRM_OFFSET,Data);
//初始化GPIO驱动结构体
XGpioPs_CfgInitialize(&GPIO,XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID),XPAR_PS7_GPIO_0_BASEADDR);
XGpioPs_SetDirectionPin(&GPIO,8,1);
XGpioPs_SetOutputEnablePin(&GPIO,8,1);
//XGpioPs_SetDirection(XPAR_PS7_GPIO_0_BASEADDR,);
//设置输出便能,bit7输出使能
//reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR+XGPIOPS_OUTEN_OFFSET);
//Data = reg_val |(1<<8);
//Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR+XGPIOPS_OUTEN_OFFSET,Data);
while(1)
{
//Data = ((~(1<<8))<<16)|(1<<8);
//Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,Data);
XGpioPs_WritePin(&GPIO,8,1);
usleep(600000);
//Data = ((~(1<<8))<<16)&(~(1<<8));
//Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,Data);
XGpioPs_WritePin(&GPIO,8,0);
usleep(600000);
}
PL 软核添加和控制
章节1中的GPIO控制LED是PS系统内的外设,系统搭建和应用流程比较简单。为了能够使用CAN IP软核,需要将软核添加入ZYNQ的PL内。这个流程比较繁锁,因此 需要先熟悉简单的对象,比如在PL端添加GPIO外设。在此基础上,再添加CAN IP等模块。如此,后期测试时能够有个基本的参照对象。
AXI GPIO 软核
在上文BD系统基础上,按照小梅哥流程添加AXI—GPIO后,出现了如下问题:
PS硬件工程:添加AXI GPIO后,生成Bitsteam并更新硬件Specification。在vitis按照库函数使用方法,初始化AXI—GPIO。但是发现,现有的程序既无法点亮PL端的LED,也无法点亮PS端的LED:即硬件更新后,上文中的例程也无法正常工作。
由于ZYNQ系统分成硬件和软件两个部分,当定位问题时不得不先从硬件入手。首先为了排除是库函数调用问题,采用寄存器函数,结果程序无法运行。这说明添加AXI GPIO后,硬件系统影响了软件的工作。上次出现这种问题,最后是莫明其妙解决。这次需要了解调试的基本方法,从而明白程序是否执行,以及没有工作是程序卡在什么地方?或者是完全没有工作?
在调试程序时,程序直接卡在中断向量表**-boot处。此文章指出这种问题是最小系统问题,需要从时钟频率设置、复位以及DDR配置等方面入手。在vivado面板中定位问题时,发现vivado 中IO Planning**的 I/O Std出现红色字符。于是猜想问题可能出在此外。
red IO Std
在检索问题时,文章1和2都指出一个情况:vivado版本更换后,才出现这个问题。后来,在xilinx评论区发现这篇
文章,文中AMD员工提出了一些IO标准规范,其中尤其强调如下内容:
vivado中,T14确实还在HR内。矛盾之外在于,小梅哥板子上使用的就是T14,板子QSPI程序也能正常驱动LED。不过,以上评论区确实也指出这个问题出现比较久,具体原因不明。由于更改IO为其它仍然显示红色,所以目前还是决定暂时搁置问题。
为了验证红IO问题是否值得关注,我将AXI GPIO删除。在IO Planning中依然可以见到大量的红IO,但是因为这个工程是可运行的,所以可以认为红IO并不是造成工程无法工作的原因。于是,问题又回到原点。在速览vivado界面时,我发现messages界面中包含62warning。考虑到如何再无法定位问题,我就需要更换vivado系统,我于是开始逐一分析这些warning的含义。
message warning:
令人困惑的是,许多message具有误导性。在这个过程中,由于前面出现过删除AXI-GPIO更新系统的操作,因此我无意识地就又update hareware specifition。换言之,内心觉得可能是之间修改GPIO命名的问题,或者流程出现差错。没有想到,在update之后,首先运行寄存器函数例程成功了,接下来我又运行了库函数,也成功了!两个LED同时亮起来,让人内心感觉喜悦,双手兴趣欢呼!!