前言
目前已经实现zynq的PS-CAN和PL-CAN功能。串口-CAN协议转换是实现以太网-CAN功能的过渡,通过这个流程能够减少后期以太网工程出现问题的频率。阶段性功能目标如下:
- 实现数据在CAN调试助手和串口调试助手之间的来回转换,从而了解中断机制和协议转换的基本流程。
- 实现串口信号协议解析,将数据发送到特定CAN。此时搭建的BD系统中可以添加8个CAN。
- 实现zynq以太网功能。此处问题较多,2021年出现大量的细节问题没有解决。如果问题较大,选择野火开发板熟悉基本流程。
- 按照上面的串口逻辑,实现以太网-CAN转换流程。如此,第一阶段的功能预期就完成。
这些目标是灵活的,可以依照需求中途调整。目前以上功能的实现主要是帮助梳理一些设计流程。
1串口-CAN总线
首先实现CAN中断功能,按照example提供例程学习。在中断中解析CAN帧后,提取出特定数据并通过print函数打印即可。这个流程是最为简单的。与之相对,串口数据无法通过print获取。需要学习串口上位机数据传输流程,从而提取出数据。
导入工程后,出现中断向量号的红标问题。由于CAN IP中的中断引脚一直没有连接,所以这个问题出现也不意外。但是,这个引脚并非如microblaze一样接入AXI interrupt controller,而是在ZYNQ中的Interrupts进行配置。
pin property FREQ_HZ does not match between
此帖指出直接删除端口再添加就能同步。结果虽然符合预期,但是这个变化本身是FCLK的频率出错造成的。下图显示,FCLK1的actual frequency 15.873016与设定的16Mhz不同。即使修改时钟源,偏差仍然存在。由于这个时钟频率偏差是软件界面显示结果,可能是软件稳定性造成,考虑先搁置这个问题。测试发现,对于波特率匹配没有影响。
中断向量ID错误
奇怪的是,比特流生成后,SDK端仍然无法检测到中断向量号。尝试如下三个操作:1查看hdf文件时间;2删除并重新导入CAN中断例程;3,RTL和wrapper图中中断相关信号;4查看注释说明。其中操作4似乎说明此外问题只是SDK的CAN驱动出现的更新错误,没有正确命名。由于61的值,以及注释中scugic的说明与实际相符。同时,代入数值后没有出现错误,基本可以判断是驱动更新问题。
/******************************************************************/
/* Definitions for Fabric interrupts connected to ps7_scugic_0 */
#define XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR 61U
XScuGic_SetPriorityTriggerType(&InterruptController, CAN_INTR_VEC_ID,
0xA0, 0x3);
/*
* Connect the interrupt handler that will be called when an
* interrupt occurs for the device.
*/
Status = XScuGic_Connect(&InterruptController, CAN_INTR_VEC_ID,
(Xil_ExceptionHandler)XCan_IntrHandler,
InstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Can device.
*/
XScuGic_Enable(&InterruptController, CAN_INTR_VEC_ID);
/******************************************************************/
刚修改完程序,发现LED自动闪烁,存在问题。于是检查了run as,发现需要建立一个新的application GDB。这是一个常见的问题,可以习惯性得点开选项,或者设置快捷键即可(没有找到)。结果,中断正常运行。
数据顺序错乱
按照以下的接收转发逻辑,ECanTool发送的数据能够发送到串口调试助手。问题在于,数据顺序是错乱的,也不是倒序。
if (RxFrame[0] == XCan_CreateIdValue(TEST_MESSAGE_ID, 0, 0, 0, 0)) {
print("rx id right \r\n");
}
FramePtr = (u8 *)(&RxFrame[2]);
for(Index = 0; Index<8; Index++)
{
rxuart[Index] = *FramePtr++;
}
xil_printf("rx can data:%d,%d,%d,%d,%d,%d,%d,%d\r\n",rxuart[0],rxuart[1],rxuart[2],rxuart[3],rxuart[4],rxuart[5],rxuart[6],rxuart[7]);
查看CAN IP接收FIFO结构,可以看到结构存在一种一一对应关系。考虑大端和小端,在指针赋值以及数据赋值时,需要注意数据存储的顺序关系。只能假设FIFO中的DB顺序与CAN数据是一致的。由于这个内容不是目前重点,且对大端和小端的概念比较模糊,所以后期再处理。[逻辑直觉确实较慢,在几个对象中来回跳跃]
FramePtr = (u8 *)(&RxFrame[2]);
for(Index = 0; Index<8; Index++)
{
rxuart[Index] = *FramePtr++;
}
到此CAN到串口的发送就完成了,接下来就进行串口到CAN。在此之前,先自己用最直接的程序,将流程重新梳理一遍。