• ZYNQ:串口-CAN协议转换


    前言

    目前已经实现zynq的PS-CAN和PL-CAN功能。串口-CAN协议转换是实现以太网-CAN功能的过渡,通过这个流程能够减少后期以太网工程出现问题的频率。阶段性功能目标如下:

    1. 实现数据在CAN调试助手和串口调试助手之间的来回转换,从而了解中断机制和协议转换的基本流程。
    2. 实现串口信号协议解析,将数据发送到特定CAN。此时搭建的BD系统中可以添加8个CAN。
    3. 实现zynq以太网功能。此处问题较多,2021年出现大量的细节问题没有解决。如果问题较大,选择野火开发板熟悉基本流程。
    4. 按照上面的串口逻辑,实现以太网-CAN转换流程。如此,第一阶段的功能预期就完成。

    这些目标是灵活的,可以依照需求中途调整。目前以上功能的实现主要是帮助梳理一些设计流程。


    1串口-CAN总线

    首先实现CAN中断功能,按照example提供例程学习。在中断中解析CAN帧,通过print函数打印字节数据。这个流程是比较简单。与之相对,串口数据无法通过print获取。需要学习串口上位机数据传输流程,从而提取出数据。
    在这里插入图片描述
    导入工程后,define中断向量号红标。原因是,BD图中CAN IP ip2bus_intrevent引脚没有连接ZYNQ的引脚IRQ_F2P,而这个引脚需要在ZYNQ中单独配置。不同的是,在microblazeip2bus_intrevent引脚是接入AXI interrupt controller

    在搭建ZYNQ硬件系统时,需要认真对待每个IP的引脚。因为忽略CAN IP的中断引脚和CAN-CLK时钟引脚,都导致调试系统耗费不小精力

    在这里插入图片描述在这里插入图片描述


    pin property FREQ_HZ does not match between

    在这里插入图片描述
    此帖指出,直接删除端口再添加:结果可行。错误原因是,FCLK1的actual frequency 15.873016与设定的16Mhz不同。

    尝试修改时钟源,偏差仍然存在。由于这个时钟频率偏差是软件界面显示的结果,猜想是软件稳定性造成,因此打算搁置这个问题。测试发现,此错误不影响波特率匹配。

    后来,采用CAN-CLK引脚与FCK1引脚直连方式,这个问题没有再出现。
    在这里插入图片描述


    中断向量ID错误

    更新硬件后,SDK仍然无法检测中断向量号。尝试如下四个操作:

    1. 查看hdf文件时间;
    2. 删除并重新导入CAN中断例程;
    3. RTL和wrapper图中中断相关信号;
    4. 查看注释说明。

    在操作4,CAN中断向量名可能出现更新错误,没有正确命名。因为,XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR宏定义与XScuGic函数中CAN_INTR_VEC_ID定义冲突,声明无法跳转。尝试代入数值61U,错误消失,可以判断是驱动更新问题。
    在这里插入图片描述

    /******************************************************************/
    
    /* 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);
    
    /******************************************************************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    修改完程序,LED自动闪烁,与程序逻辑冲突。尝试检查run as,发现默认ELF文件是intr example。重新生成测试程序的debugger后,程序中断正常运行。

    run as操作是常见的问题,可以习惯性点开Launch on hardware选项,避免出现默认操作。
    在这里插入图片描述
    在这里插入图片描述


    数据顺序错乱

    CAN口接收转发逻辑如下,ECanTool发送的CAN数据发送到串口调试助手。结果是,数据顺序错乱,也不是倒序。

    明确"结果是什么?“和"预期是什么”,能够更加高效发现两者之间的区别。

    	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]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    在这里插入图片描述
    查看CAN IP接收FIFO结构,四个字长度存在映射对应关系。从大端和小端角度出发,在指针赋值以及数据赋值时,需要注意数据存储的顺序关系。假设FIFO中的DB顺序与CAN数据是一致的。

    逻辑直觉确实较慢,意识在几个概念对象中来回跳跃。此内容不是目前重点,且对大端和小端的概念比较模糊,所以后期再深入分析。

    FramePtr = (u8 *)(&RxFrame[2]);
    	for(Index = 0; Index<8; Index++)
    	{
    		rxuart[Index] = *FramePtr++;
    		
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述


    expected declaration specifiers or

    打开工程时,出现expected declaration specifiers or ‘…’ before '错误,后来在数字61U前添加一个空格就好了。
    在这里插入图片描述
    在编程时,出现如下两个错误。原先此处正常,不知是修改什么内容影响。too few arguments不合理:因为参数已经全部添加盲点是,直接命名错误,即混淆
    XScuGic
    ScuGic,代入XScuGic到函数中。

    在编程过程中,这种马虎的细节问题经常发生,一般需要自己细致检查才能发现这个问题。原因是,意识模糊,聚焦没有发现盲点
    在这里插入图片描述

    按照如下逻辑运行程序,发送CAN帧,LED没有正常闪烁。尝试如下两个操作,定位问题:

    1. 测试CAN帧发送:正常
    2. 对比例程代码:缺少exception部分内容;
    //配置can波特率500K,频率为16Mhz
        XCan_EnterMode(&Can, XCAN_MODE_CONFIG);
        XCan_SetBaudRatePrescaler(&Can, 3);
        XCan_SetBitTiming(&Can, 2, 1, 4);
        XCan_EnterMode(&Can, XCAN_MODE_NORMAL);
    //配置中断控制
        XCan_SetHandler(&Can, XCAN_HANDLER_RECV, (void *)RecvHandler ,(void *)&Can);
    
        ScuGicCfg = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
        XScuGic_CfgInitialize(&ScuGic, ScuGicCfg, ScuGicCfg->CpuBaseAddress);
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, 0xA0, 0x3);
        XScuGic_Connect(&ScuGic,XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, (Xil_ExceptionHandler)XCan_IntrHandler, &Can);
        XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR);
    
        XCan_InterruptEnable(&Can, XCAN_IXR_RXNEMP_MASK);
        while(1)
        {
        	if(flag)
        	{
            	XGpioPs_WritePin(&Gpio, 7, 1);
            	sleep(1);
            	XGpioPs_WritePin(&Gpio, 7, 0);
            	sleep(1);
        	}
        }
    
        cleanup_platform();
        return 0;
    }
    
    static void RecvHandler(void *CallBackRef)
    {
    	flag = 1;
    
    	return ;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    添加以上代码,再次出现too few arguments to function错误。原因是,xil是小写。删除中间参数的括号内容后,才区分xilXil

    此类参数命名操作,容易忽略命名命名正确性和对应关系,需要从以上两个角度检查:大小写、命名对象和对象映射关系
    在这里插入图片描述


    can接收中断持续触发

    因为程序能够正常发送CAN帧,尝试把接收中断修改为发送中断。LED正常闪烁,但是在中断中添加print函数后,接收中断一直处于触发状态,意味着CAN帧接收存在问题。
    在这里插入图片描述
    修改中断类型之后、删除所有中断触发类型,持续触发消失。这意味着,不能一次性打开所有中断。参照Uart例程,CAN外设帧发送失效,代码如下。删除新增的UART代码,程序又正常运行,猜想UART代码某个函数停留在while逻辑。可以进入debug模式,定位while逻辑点。但是在检查代码时,观察到持续进入中断会造成程序无法进入。因此,有必要先选择UART的发送模式,看看实际效果:结果可以正常发送数据,仍然无法进入发送中断

     XCan_InterruptEnable(&Can, XCAN_IXR_TXOK_MASK|XCAN_IXR_RXNEMP_MASK);
    
    • 1
    //参数初始化
    	flag = 0;
    
        init_platform();
    //配置gpio-ps
        GpioCfg = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
        XGpioPs_CfgInitialize(&Gpio, GpioCfg, GpioCfg->BaseAddr);
        XGpioPs_SetDirectionPin(&Gpio, 7, 1);
        XGpioPs_SetOutputEnablePin(&Gpio, 7, 1);
    
    //初始化配置串口
        UartCfg = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);
        XUartPs_CfgInitialize(&Uart, UartCfg , UartCfg->BaseAddress);
        //修改点++XUartPs_SetBaudRate(&Uart, 115200);
        print("Hello World count:12\n\r");
    
    
    //配置测试can-pl
        status = XCan_Initialize(&Can,XPAR_CAN_0_DEVICE_ID);
        if(status != XST_SUCCESS)
        {
        	print("can init error \r\n");
        }
    
    //配置can波特率500K,频率为16Mhz
        XCan_EnterMode(&Can, XCAN_MODE_CONFIG);
        XCan_SetBaudRatePrescaler(&Can, 3);
        XCan_SetBitTiming(&Can, 2, 1, 4);
        XCan_EnterMode(&Can, XCAN_MODE_NORMAL);
    //CAN帧发送测试
        FramePtr[0] = XCan_CreateIdValue(11, 0, 0, 0, 0);
        FramePtr[1] = XCan_CreateDlcValue(8);
    
        ptr = (u8 *)(&FramePtr[2]);
        for(i = 0; i<8; i++)
        {
        	*ptr++ = 10;
        }
    
    
    //配置pl-cant和uart中断控制
    
        //pl-can
        XCan_SetHandler(&Can, XCAN_HANDLER_RECV, (void *)RecvHandler ,(void *)&Can);
        XCan_SetHandler(&Can, XCAN_HANDLER_SEND, (void *)SendHandler ,(void *)&Can);
        XCan_InterruptEnable(&Can, XCAN_IXR_TXOK_MASK);
        //ps-uart
        XUartPs_SetHandler(&Uart, (XUartPs_Handler)Handler, (void *)&Uart);
        XUartPs_SetInterruptMask(&Uart,XUARTPS_IXR_RXFULL);
        XUartPs_SetOperMode(&Uart, XUARTPS_OPER_MODE_NORMAL);
        XUartPs_SetRecvTimeout(&Uart, 8);
    
    
    
        //scugic配置
        ScuGicCfg = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
        status = XScuGic_CfgInitialize(&ScuGic, ScuGicCfg, ScuGicCfg->CpuBaseAddress);
        if(status != XST_SUCCESS)
        {
        	print("scugic init error \r\n");
        }
    
        //优先级
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, 0xA0, 0x3);
        //XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_XUARTPS_1_INTR, 0xA0, 0x3);
        //中断控制连接
        XScuGic_Connect(&ScuGic,XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, (Xil_ExceptionHandler)XCan_IntrHandler, &Can);
        XScuGic_Connect(&ScuGic,XPAR_XUARTPS_1_INTR, (Xil_ExceptionHandler)XUartPs_InterruptHandler, &Uart);
        //使能控制
        XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR|XPAR_XUARTPS_1_INTR);
    
        //配置 xil exception对象
        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &ScuGic);
        Xil_ExceptionEnable();
    
    
    //can帧发送测试
        XCan_Send(&Can, FramePtr);
        while(1)
        {
        	if(1)
        	{
            	XGpioPs_WritePin(&Gpio, 7, 1);
            	sleep(1);
            	XGpioPs_WritePin(&Gpio, 7, 0);
            	sleep(1);
        	}
        }
    
    
        cleanup_platform();
        return 0;
    }
    
    static void RecvHandler(void *CallBackRef)
    {
    	int status;
    	XCan *CanPtr = (XCan *)CallBackRef;
    
    	status = XCan_Recv(CanPtr, RxFrame);
    	if(status != XST_SUCCESS)
    	{
    		print("XCan_Recv\r\n");
    	}
    
    	//flag = 1;
    	print("recv ok \r\n");
    
    
    	return ;
    }
    
    static void SendHandler(void *CallBackRef)
    {
    	flag = 1;
    	print("send ok \r\n");
    	return ;
    }
    
    void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
    {
    
    	print("uart intr ok\r\n");
    	return ;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126

    无法进入uart接收和发送中断

    程序流程比较繁杂,回调函数使用频率较高,于是再次细致梳理程序流逻辑。

    观察到,两种使能方式产生的现象不同。位与方式会导致无法发送CAN帧,修改程序为前者,程序正常工作。

    XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR);
    XScuGic_Enable(&ScuGic, XPAR_XUARTPS_1_INTR);XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR|XPAR_XUARTPS_1_INTR);
    
    • 1
    • 2
    • 3
    • 4

    注意到,uart的中断特点与我预期不同。比如,CAN发送成功存在中断,uart没有这种中断分类。尝试修改中断设置为XUARTPS_IXR_MASK时,程序正常进入中断!这意味着,区分uart每种中断的特点,才能正常触发中断。

    XUartPs_SetInterruptMask(&Uart,XUARTPS_IXR_MASK);
    
    #define XCAN_IXR_TXOK_MASK	0x00000002  /**< TX Successful Interrupt Mask */
    
    #define XUARTPS_IXR_RBRK	0x00002000U /**< Rx FIFO break detect interrupt */
    #define XUARTPS_IXR_TOVR	0x00001000U /**< Tx FIFO Overflow interrupt */
    #define XUARTPS_IXR_TNFUL	0x00000800U /**< Tx FIFO Nearly Full interrupt */
    #define XUARTPS_IXR_TTRIG	0x00000400U /**< Tx Trig interrupt */
    #define XUARTPS_IXR_DMS		0x00000200U /**< Modem status change interrupt */
    #define XUARTPS_IXR_TOUT	0x00000100U /**< Timeout error interrupt */
    #define XUARTPS_IXR_PARITY 	0x00000080U /**< Parity error interrupt */
    #define XUARTPS_IXR_FRAMING	0x00000040U /**< Framing error interrupt */
    #define XUARTPS_IXR_OVER	0x00000020U /**< Overrun error interrupt */
    #define XUARTPS_IXR_TXFULL 	0x00000010U /**< TX FIFO full interrupt. */
    #define XUARTPS_IXR_TXEMPTY	0x00000008U /**< TX FIFO empty interrupt. */
    #define XUARTPS_IXR_RXFULL 	0x00000004U /**< RX FIFO full interrupt. */
    #define XUARTPS_IXR_RXEMPTY	0x00000002U /**< RX FIFO empty interrupt. */
    #define XUARTPS_IXR_RXOVR  	0x00000001U /**< RX FIFO trigger interrupt. */
    #define XUARTPS_IXR_MASK	0x00003FFFU /**< Valid bit mask */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    CAN帧数据转换逻辑

    虽然串口数据的发送单位是字节,但是UART的数据存储单位是RxFIFO。中断和操作也是围绕这个FIFO来进行的,UART也没有所谓接收中断。与之相对,接收单个CAN帧可以触发中断,同时相关数据也存储在一组连续的地址中。
    在这里插入图片描述
    简单为先,采取以下转换方式:接收8个字节数据,即发送一个CAN帧。换言之,串口调试助手发送8个HEX数据,CAN端口就会发送一帧CAN。这种形式简单,逻辑表达方便。

    观察到,数据接收正常,但是数据顺序和位次存在异常。发送内容是字符”3“的HEX,接收为10,13,10,13,这与ASCII表中映射关系不符合。此贴比较深入分析了如何将实数通过串口发送,满足协议要求。这提醒我,这种串口协议转发是可行的,但是需要注意其中的转换细节。
    在这里插入图片描述
    理想转换思路是串口调试助手发送字符’321’,十六进制数是0x31 0x32 0x33三个字节。RxFIFO接收三个字节数据,触发FIFO非空中断。XUartPs_Recv函数提取三个字节数据,并装入CAN总线帧中。按照这种逻辑,每点击一次发送数据ECanTools就能够接收到一帧CAN。结果是,可以正常接收数据,但是数据顺序存在异常。猜想是,前面发送的串口数据偏短,导致里面的数据错位。
    在这里插入图片描述
    猜想原因是,串口调试助手实际发送数据与发送框内的数据相关,而非上面的发送框(31-32-33那排)。这种字符顺序错位问题,应该不是当前重点,可以先考虑后面的关键内容。前期学习的重点是,通过实现主体功能来了解基本代码流程,否则就会除入到各种字符转换的繁杂逻辑中。
    在这里插入图片描述


    2串口信号协议解析

    章节1主要实现了CAN-串口的上行和下行数据收发,了解双向数据接收中中断机制和中断类型特点。章节2主要目标是,解析串口协议判断数据发送到什么CAN口。当CAN口数量较多,串口协议数据具有指向性时,可以定向发送。比如设置串口trigger为8,前面一个字节是CAN口位,比如0x55是can0,0x66是can1等。注意,这个阶段目标需要注意协议发送的正确性,这是上个阶段没有的特征。通过这种有节奏的设定目标,可以增加每个阶段目标的吸引力。如果一个阶段目标太长,一直陷在单个问题里,动力就会大幅减少。

    
    int main()
    {
    	u32 status;
    	u32 FramePtr[4];
    	u8 i;
    	u8 *ptr;
    //参数初始化
    	flag = 0;
    	uartRxFlag = 0;
    
        init_platform();
    //配置gpio-ps
        GpioCfg = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
        XGpioPs_CfgInitialize(&Gpio, GpioCfg, GpioCfg->BaseAddr);
        XGpioPs_SetDirectionPin(&Gpio, 7, 1);
        XGpioPs_SetOutputEnablePin(&Gpio, 7, 1);
    
    //初始化配置串口
        UartCfg = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);
        XUartPs_CfgInitialize(&Uart, UartCfg , UartCfg->BaseAddress);
        XUartPs_SetBaudRate(&Uart, 115200);
        print("Hello World count:13\n\r");
    
    
    //配置测试can-pl
        status = XCan_Initialize(&Can,XPAR_CAN_0_DEVICE_ID);
        if(status != XST_SUCCESS)
        {
        	print("can init error \r\n");
        }
    
    //配置can波特率500K,频率为16Mhz
        XCan_EnterMode(&Can, XCAN_MODE_CONFIG);
        XCan_SetBaudRatePrescaler(&Can, 3);
        XCan_SetBitTiming(&Can, 2, 1, 4);
        XCan_EnterMode(&Can, XCAN_MODE_NORMAL);
    //CAN帧发送测试
        FramePtr[0] = XCan_CreateIdValue(11, 0, 0, 0, 0);
        FramePtr[1] = XCan_CreateDlcValue(8);
    
        ptr = (u8 *)(&FramePtr[2]);
        for(i = 0; i<8; i++)
        {
        	*ptr++ = 10;
        }
    
    
    //配置pl-cant和uart中断控制
    
        //pl-can
        XCan_SetHandler(&Can, XCAN_HANDLER_RECV, (void *)RecvHandler ,(void *)&Can);
        XCan_SetHandler(&Can, XCAN_HANDLER_SEND, (void *)SendHandler ,(void *)&Can);
        XCan_InterruptEnable(&Can, XCAN_IXR_TXOK_MASK|XCAN_IXR_RXNEMP_MASK);
        //ps-uart
        XUartPs_SetHandler(&Uart, (XUartPs_Handler)Handler, (void *)&Uart);
    
        XUartPs_SetFifoThreshold(&Uart, 8);	//修改中断发送满以及上限值;是接收阈值
        XUartPs_SetInterruptMask(&Uart,XUARTPS_IXR_RXOVR|XUARTPS_IXR_RXFULL); //TP12 修改中断状态
        XUartPs_SetOperMode(&Uart, XUARTPS_OPER_MODE_NORMAL);
        //XUartPs_SetRecvTimeout(&Uart, 8);
    
    //    for(i = 0; i<100; i++)
    //    {
    //    	TxUartBuffrt[i] = (i % 26) + 'A';
    //    }
    
    
    
        //scugic配置
        ScuGicCfg = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
        status = XScuGic_CfgInitialize(&ScuGic, ScuGicCfg, ScuGicCfg->CpuBaseAddress);
        if(status != XST_SUCCESS)
        {
        	print("scugic init error\r\n");
        }
    
        //优先级
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, 0xA0, 0x3);
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_XUARTPS_1_INTR, 0xA8, 0x2);
        //中断控制连接
        XScuGic_Connect(&ScuGic,XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, (Xil_ExceptionHandler)XCan_IntrHandler, &Can);
        XScuGic_Connect(&ScuGic,XPAR_XUARTPS_1_INTR, (Xil_ExceptionHandler)XUartPs_InterruptHandler, &Uart);
        //使能控制
        XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR);// |XPAR_XUARTPS_1_INTR忽略中断使能,加入uart中断,can帧都无法发送
        XScuGic_Enable(&ScuGic, XPAR_XUARTPS_1_INTR);//单独使能看看运行效果
    
        //配置 xil exception对象
        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &ScuGic);
        Xil_ExceptionEnable();
    
    
    //can帧发送测试
        XCan_Send(&Can, FramePtr);
    //    XUartPs_Send(&Uart, TxUartBuffrt, 100);
        XUartPs_Recv(&Uart, RxUartBuffrt, 10);
    
        while(1)
        {
        	if(1)
        	{
            	XGpioPs_WritePin(&Gpio, 7, 1);
            	sleep(1);
            	XGpioPs_WritePin(&Gpio, 7, 0);
            	sleep(1);
        	}
        	//串口帧装入CAN帧
        	if(uartRxFlag)
        	{
        		   FramePtr[0] = XCan_CreateIdValue(10, 0, 0, 0, 0);
        		   FramePtr[1] = XCan_CreateDlcValue(8);
    
        		    ptr = (u8 *)(&FramePtr[2]);
        		    for(i = 0; i<8; i++)
        		    {
        		    	*ptr++ = RxUartBuffrt[i];
        		    }
        		    XCan_Send(&Can, FramePtr);
        		    uartRxFlag = 0;//注意清除标志位
        	}
        }
    
        cleanup_platform();
        return 0;
    }
    
    static void RecvHandler(void *CallBackRef)
    {
    	//中断数据接收是必要的,否则影响功能或者led闪烁
    	int status;
    	XCan *CanPtr = (XCan *)CallBackRef;
    
    	status = XCan_Recv(CanPtr, RxFrame);
    	if(status != XST_SUCCESS)
    	{
    		print("XCan_Recv\r\n");
    	}
    
    	//flag = 1;
    	print("recv ok \r\n");
    
    
    	return ;
    }
    
    static void SendHandler(void *CallBackRef)
    {
    	flag = 1;
    	print("send ok \r\n");
    	return ;
    }
    
    void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
    {
    //
    	XUartPs *UartPtr = (XUartPs *)CallBackRef;
    
    
    	if(Event == XUARTPS_EVENT_RECV_DATA	)
    	{
    		print("event sent \r\n");
    	}
    	XUartPs_Recv(UartPtr, RxUartBuffrt,8);
    	uartRxFlag = 1;//uart接收中断信号
    
    	print("uart intr ok\r\n");
    	return ;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170

    多can口bd系统

    在搭建此系统前,存在两个方面问题:

    1. 接口引脚映射,can-clk无法直接接入FCLK1,需要修改wrapper文件生成。后期测试表明,可以直接连接
    2. PL IO口映射,明确36通用标准IO口中能够用于CAN总线通信的引脚。从功能、bank、差分、MBG等方面考虑。因此,在RTL的IO planning中有意从这几个方面配置IO,判断那些搭配是可行的。
      在这里插入图片描述
      测试 PL-IO组合如下表:7020引脚分配表
    can0
    G17  IO_L16P_T2_35            2                  35    NA            NA                  HR        NA
    G18  IO_L16N_T2_35            2                  35    NA            NA                  HR        NA
    can1-特殊ad功能
    L15  IO_L22N_T3_AD7N_35       3                  35    NA            NA                  HR        NA rx
    H15  IO_L19P_T3_35            3                  35    NA            NA                  HR        NA tx
    can2-期望任何接近的引脚可用,不同功能也可:dqs不是ad
    E17  IO_L3P_T0_DQS_AD1P_35    0                  35    NA            NA                  HR        NA rx
    E18  IO_L5P_T0_AD9P_35        0                  35    NA            NA                  HR        NA tx 
    can3
    D20  IO_L4N_T0_35             0                  35    NA            NA                  HR        NA rx
    E19  IO_L5N_T0_AD9N_35        0                  35    NA            NA                  HR        NA tx 
    can4 不同mbg
    J19  IO_L10N_T1_AD11N_35      1                  35    NA            NA                  HR        NA rx
    G19  IO_L18P_T2_AD13P_35      2                  35    NA            NA                  HR        NA tx 
    can5 不同bank和mbg
    P19  IO_L13N_T2_MRCC_34       2                  34    NA            NA                  HR        NA rx 
    J16  IO_L24N_T3_AD15N_35      3                  35    NA            NA                  HR        NA tx 
    can6  无MBG
    K14  IO_L20P_T3_AD6P_35       3                  35    NA            NA                  HR        NA rx
    G14  IO_0_35                  NA                 35    NA            NA                  HR        NA tx 
    can7
    F16  IO_L6P_T0_35             0                  35    NA            NA                  HR        NA rx
    D18  IO_L3N_T0_DQS_AD1N_35    0                  35    NA            NA                  HR        NA tx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. CAN0正常,说明原先的接线方式是可行的。RTL图也是显示连接状态。区分错误CAN数据和CANID两个值
    2. CAN1没有反应
    3. CAN2没有反应【为了避免是其它问题,重新连上G17和G18,能够发送】
    4. CAN3没有反应
    5. CAN4可以,难道是AD引脚原因?不过MBG似乎不影响功能。按照这个规律can5-can6-can7都不可以,因为是不同功能引脚,或者通用引脚。
    6. CAN5没有反应【小梅哥指出emio-pscan没有出现这个问题】
    7. CAN6没有反应
    8. CAN7没有反应

    总结:以上内容说明不同功能引脚可能影响CAN信号,以及EMIO不影响;为了测试这种差异,添加以下类别引脚:ps-emio引脚测试,AD功能引脚-区分P和N端,DQS功能以及MRCC功能等。表格如下:

    can1  测试CAN4类型
    L15  IO_L22N_T3_AD7N_35       3                  35    NA            NA                  HR        NA rx
    E19  IO_L5N_T0_AD9N_35        0                  35    NA            NA                  HR        NA tx
    can2 测试P和N因素
    K14  IO_L20P_T3_AD6P_35       3                  35    NA            NA                  HR        NA rx
    J16  IO_L24N_T3_AD15N_35      3                  35    NA            NA                  HR        NA tx 
    can3 测试SRCC功能
    N20  IO_L14P_T2_SRCC_34       2                  34    NA            NA                  HR        NA
    P20  IO_L14N_T2_SRCC_34       2                  34    NA            NA                  HR        NA
    CAN5  相同ad功能
    D20  IO_L4N_T0_35             0                  35    NA            NA                  HR        NA
    F16  IO_L6P_T0_35             0                  35    NA            NA                  HR        NA
    CAN6 相同ad功能
    J20  IO_L17P_T2_AD5P_35       2                  35    NA            NA                  HR        NA
    H20  IO_L17N_T2_AD5N_35       2                  35    NA            NA                  HR        NA
    can7  
    L19  IO_L9P_T1_DQS_AD3P_35    1                  35    NA            NA                  HR        NA
    K16  IO_L24P_T3_AD15P_35      3                  35    NA            NA                  HR        NA
    ps-can0
    E17  IO_L3P_T0_DQS_AD1P_35    0                  35    NA            NA                  HR        NA
    H15  IO_L19P_T3_35            3                  35    NA            NA                  HR        NA
    ps-can1
    E18  IO_L5P_T0_AD9P_35        0                  35    NA            NA                  HR        NA
    K19  IO_L10P_T1_AD11P_35      1                  35    NA            NA                  HR        NA
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    更新系统时,再次出现FCLK频率问题。这意味着,切换为原来的直接连接线路比较好。但是wrapper文件一直无法正常更新:vivado2018的同步问题一直存在,CAN3与其它CAN接线相同,但是只有它多余了CLK信号。
    在这里插入图片描述
    在这里插入图片描述

    poor placement for routing错误

    上个阶段,虽然已经添加了七个引脚,但是没有出现place问题。可是这次又是添加EMIO,又是更换引脚,变动不小。
    在这里插入图片描述
    此帖提示CLK信号问题,即CAN3的时钟信号外接普通IO。Unplace此引脚,supress unconstrained错误后,没有效果。于是,尝试断开重连BD中的所有CAN-CLK,重新生成wrapper,引脚输出正常。
    在这里插入图片描述
    测试结果:

    1. CAN0无法正常接收。奇怪
    2. CAN1无法接收。奇怪!
    3. 连前期正常的CAN0都无法正常工作,因此可能是其它问题!

    vivado RTL图编译错误

    原先猜想是,vivado编译存在问题。检查BD图后,观察到CAN-CLK错误接入到FCLK0【粗心】。这提醒我,以后编译时,通过RTL图检查关键信号的路径。
    在这里插入图片描述
    奇怪的是,首次出现auto-pc错误。猜想原因是,当时出现一个M08_AXI接口时直接删除。这意味着,不能直接删除BD图的模块,需要慎重调整。目前相关修改没有效果,只有选择删除所有对象、重新搭建BD系统。
    在这里插入图片描述
    在这里插入图片描述
    与预期不同,重新配置BD图时间不多,生成的RTL中CAN-CLK的传送路径也是正常的。观察到,在比特流编译成功时,Vivado软件中的错误message仍然存在。
    在这里插入图片描述
    测试结果如下:

    1. CAN0测试成功
    2. CAN1测试成功
    3. CAN2测试成功
    4. CAN3测试成功
    5. CAN5测试成功,CAN4上轮测试过
    6. CAN6测试成功
    7. CAN7测试成功。这说明前期的判断失误,CAN口无法发送可能是BD系统搭建错误造成!一般的IO口都能正常使用,如果使用到特殊接口,可以再测试下。

    串口协议逻辑思考

    目前8CAN-PL和2CAN-PS的BD系统已经搭建完成。接下来问题是,如何设计协议来转换串口数据和CAN帧。

    面对这么多的外设对象,不知如何管理:这些CAN外设是用来干什么、数据的特点是什么、准备用来干什么?如果没有具体讨论这些问题,则整个系统无的放矢,缺少具体研究对象。换言之,系统模型是残缺的。此时,又过度联想到freeRTOS或者linux等,思维头绪也越来越混乱。

    协议转换的策略调度,没有任何进展,于是决定首先实现部分串口-can协议转换功能。在构思SDK软件程序逻辑过程中,意识到思维比较混乱。

    3层注释逻辑和优化

    以程序中的ScuGic配置为例,分三个层级说明程序注释:

    1. 说明整体逻辑,函数名基本相同,**//**处于贴最右边;
    2. 与函数左对齐,是整体逻辑的子逻辑。换言之,一个大逻辑分为几个小逻辑;
    3. 位于每段程序右边,具体说明这个函数的作用以及注意事项。

    明确注释逻辑的意义在于,引入过去写作的习惯,迁移去年投入写作的状态。这种相似感,可以增强写作编程的熟悉感。同时,编程反馈比较强,写出的内容能够比较快在电脑端进行测试;与之相对,个人观点写作只是表达自己想法,很少能够获得观点反馈。这种差异能够进一步激活编程表达的动力。此外,SDK中的编程提示可以进一步创造这种流畅感,减少那种编程只是一步一步机械写出逻辑的消极感受。

    //scugic配置
        
        //初始化
        ScuGicCfg = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
        status = XScuGic_CfgInitialize(&ScuGic, ScuGicCfg, ScuGicCfg->CpuBaseAddress);
        if(status != XST_SUCCESS)
        {
        	print("scugic init error\r\n");
        }
    
        //优先级
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, 0xA0, 0x3);
        XScuGic_SetPriorityTriggerType(&ScuGic, XPAR_XUARTPS_1_INTR, 0xA8, 0x2);
        //中断函数连接
        XScuGic_Connect(&ScuGic,XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR, (Xil_ExceptionHandler)XCan_IntrHandler, &Can);
        XScuGic_Connect(&ScuGic,XPAR_XUARTPS_1_INTR, (Xil_ExceptionHandler)XUartPs_InterruptHandler, &Uart);
        //使能控制
        XScuGic_Enable(&ScuGic, XPAR_FABRIC_CAN_0_IP2BUS_INTREVENT_INTR);// |XPAR_XUARTPS_1_INTR忽略中断使能,加入uart中断,can帧都无法发送
        XScuGic_Enable(&ScuGic, XPAR_XUARTPS_1_INTR);//单独使能看看运行效果
    
        //配置 xil exception对象
        Xil_ExceptionInit();
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &ScuGic);
        Xil_ExceptionEnable();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    双CAN口协议转换

    为了简单,首先测试双CAN口。逻辑是用ID区分CAN口,CAN0路接收的数据取首个,CAN1数据取第二个。这个简单逻辑也容易测试。首先直接编写CAN0逻辑,然后在此基础上添加CAN1。

    问题是,CAN0能够正常进入中断,但是接收的CAN帧ID IF 逻辑出现错误。结果是,**RxFrame[0]**才是存储ID的数据结构马虎
    在这里插入图片描述
    在这里插入图片描述
    继续添加CAN1代码,实现相应逻辑。CAN结构体设定为结构体数组,方便管理。但是,程序运行之后 没有反应,led也没闪烁。

    现象是,串口有输出,但是主while逻辑中的点灯逻辑没有工作。首次定位BUG如下:1,**XCan_Initialize(&Can[i],0)**初始化对象出错,没有设定为i。但是这种现象,一般是程序进入while逻辑造成。否则,什么逻辑问题会造成这种程序现象的发生?

    	XCan Can[8];//修改为结构体数组
    
    • 1

    print工作,主while和CAN发送失效

    存在如下现象:

    1. 主程度逻辑如下,但是程序运行后,既没有LED闪烁也没串口发送数据;
    2. 参数初始化化后,print函数正常打印。

    原因猜想如下:

    1. 程序运动过程中卡在某个while逻辑中;
    2. 程序运行到某个节点路飞,这个情况曾经出现过。
        while(1)
        {
        	print("test\r\n");
        	sleep(1);
        	if(1)
        	{
            	XGpioPs_WritePin(&Gpio, 7, 1);
            	sleep(1);
            	XGpioPs_WritePin(&Gpio, 7, 0);
            	sleep(1);
        	}
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    调试过程中,程序卡在can外设中断配置的xil_assert中,而assert中包含一个while循环。这意味着,XCan_SetHandler函数存在问题。但是在重新relaunch后,程序出现如下错误:No source available for “0x100000”

        //pl-can0
          XCan_SetHandler(&Can[0], XCAN_HANDLER_RECV, (void *)RecvHandler ,(void *)&Can[0]);
          XCan_SetHandler(&Can[0], XCAN_HANDLER_SEND, (void *)SendHandler ,(void *)&Can[0]);
          XCan_InterruptEnable(&Can[0], XCAN_IXR_RXNEMP_MASK);
        //pl-can1
          XCan_SetHandler(&Can[1], XCAN_HANDLER_RECV, (void *)RecvHandler1 ,(void *)&Can[1]);
          //XCan_SetHandler(&Can[1], XCAN_HANDLER_SEND, (void *)SendHandler ,(void *)&Can[1]);
          XCan_InterruptEnable(&Can[1], XCAN_IXR_RXNEMP_MASK);
          
    int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType,
    		    void *CallBackFunc, void *CallBackRef)
    {
    	Xil_AssertNonvoid(InstancePtr != NULL);
    	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
    
    #define Xil_AssertNonvoid(Expression)             \
    {                                                  \
        if (Expression) {                              \
            Xil_AssertStatus = XIL_ASSERT_NONE;       \
        } else {                                       \
            Xil_Assert(__FILE__, __LINE__);            \
            Xil_AssertStatus = XIL_ASSERT_OCCURRED;   \
            return 0;                                  \
        }                                              \
    }
    void Xil_Assert(const char8 *File, s32 Line)
    {
    	/* if the callback has been set then invoke it */
    	if (Xil_AssertCallbackRoutine != 0) {
    		(*Xil_AssertCallbackRoutine)(File, Line);
    	}
    
    	/* if specified, wait indefinitely such that the assert will show up
    	 * in testing
    	 */
    	while (Xil_AssertWait != 0) {
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    No source available for “0x100000”

    问题奇怪之外在于,原本程序可以正常debug,但是在调试一遍后,就发生这样的问题。尝试点击resume后,指针直接停在_boot处。切换调试模式为system debugger模式,指针仍然停留在_boot处。

    尝试直接进入行动模式,定位问题。首先,测试让两个CAN一同发送CAN帧,发现只有CAN0帧显示在ECanTool。猜想原因是,CAN1初始化问题导致中断配置中进入while的assert循环。为了测试是否是结构化数组造成初始化问题,尝试单独初始化CAN0和CAN1。

    for(i = 0;i < 2;i++)
        {
    		status = XCan_Initialize(&Can[i],i); //此逻辑唯一与CANx绑定,注意中断号
    		if(status != XST_SUCCESS)
    		{
    			xil_printf("can[%d] init error \r\n",i);
    		}
    
    		//can波特率:500K,频率为16Mhz
    		XCan_EnterMode(&Can[i], XCAN_MODE_CONFIG);
    		XCan_SetBaudRatePrescaler(&Can[i], 5);
    		XCan_SetBitTiming(&Can[i], 2, 1, 4);
    		XCan_EnterMode(&Can[i], XCAN_MODE_NORMAL);
    		//CAN发送:组帧  can0和can1
    		FramePtr[0] = XCan_CreateIdValue(13, 0, 0, 0, 0);
    		FramePtr[1] = XCan_CreateDlcValue(8);
    
    		FramePtr1[0] = XCan_CreateIdValue(8, 0, 0, 0, 0);
    		FramePtr1[1] = XCan_CreateDlcValue(8);
    
    		ptr = (u8 *)(&FramePtr[2]);
    		for(i = 0; i<8; i++)
    		{
    			*ptr++ = 6;
    		}
    
    		ptr = (u8 *)(&FramePtr1[2]);
    		for(i = 0; i<8; i++)
    		{
    			*ptr++ = 7;
    		}
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    测试时候,才意识到ECanTool的界面是单独对两个通道进入测试,即为了看CAN1是否接收CAN帧,需要单独点出相应的页面。此外,此上位机无法同时接收两路信号,需要分别接收。单独测试后,CAN0和CAN1实现了正常发送。

    在这里插入图片描述
    尝试把所有CAN[0]命名改为CAN0,CAN[1]命名改变CAN1。如果中断程序正常运行,则说明数组结构体命名存在一定问题。命名修改后,CAN0和CAN1中断都顺利进入,基本CAN口的中断流程实现。

    数组结构体使用存在盲点。面对没有实践过的内容,默认存在末知问题。

    3总结

    为什么考虑采用freeRTOS管理外设?
    实现多路CAN口协议转换时,需要针对每个CAN口设计对应的中断函数逻辑。这些中断逻辑可能存在不同的优化级,不同的内存管理区域以及不同的复用特点。为了同时管理如此多路CAN口数据,同时提升CAN口的响应效率,需要增加DMA、内存管理和映射策略等办法。或者为了更好管理每路CAN口,有必要采用freertos管理。

    为什么需要明确系统具体需求?
    按照如下的测试逻辑,可以顺利8个CAN口的收发中断逻辑,无论上行还是下行。但是这只是搭建了一个基本的系统,系统没有任何需要处理的特征数据或者任务。这就需要明确自己系统的目标和具体任务,尤其是这个系统所处环境的数据特征等。如果无法明确每路CAN口的CAN帧数据周期控制特性,整个系统的建立就缺少实际意义。因此,仍然需要明确系统要解决的问题,这个有必要具体思考相关问题。

    小的发现

    1. 粗心:在测试每路CAN口时,确实存在粗心问题。在此心态下,经常性混淆不同对象之间的映射关系,比如代码中的不同外设对象命名和处理区别。

    2. 测试技巧:LED闪烁是测试程序功能的一个简便方法,可以在设计数据节点板卡时,添加相应的LED闪烁功能,从而判断程序进入的状态。毕竟板子上的LED闪烁是非常直观的一种现象。

    3. 结构化表达:碰到技术问题的特殊现象,分析原因,修正问题,额外内容补充。按照一定的分析流程,能够减少犹豫,更加高效定位问题。

  • 相关阅读:
    Spring中的注解01
    关于集群和分布式部署
    Java认识异常(超级详细)
    grafana 使用指南 —— geomap 地图组件
    java+php+python的公文审批系统-办公系统
    MPI简谈
    从文件读取和转换编程
    机械设计制造,设计行业图纸透明加密保护。防止内部终端核心文件数据、资料外泄
    计算机毕业设计Java学科竞赛管理系统(源码+系统+mysql数据库+Lw文档)
    C++程序文件的目录结构
  • 原文地址:https://blog.csdn.net/jpyjpy123/article/details/136292960