You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ATSAME51 CAN驱动无编译优化正常,开启优化后出现格式错误

问题描述

在Microchip IGAT开发板上为ATSAME51编写了CAN驱动,无编译优化时程序可正常收发数据;开启任意等级编译优化后,总线报错(Error Passive、Error Warning、Bus Off位均置位),协议状态寄存器(PSR)的Last Error Code(LEC)为0x2(格式错误:接收帧的固定格式部分格式错误)。

已排查CAN寄存器、GCLK寄存器、IO复用寄存器,无编译优化和开启优化时这些寄存器状态一致;FIFO地址处于系统RAM前64KB的有效区域,且调试确认can_tx_immediate函数已将数据正确写入FIFO,目前无法定位问题,寻求技术帮助。

相关代码

main.c

#include "sam.h"
#include "drivers/drivers.h"

int main(void)
{
    system_config_all_clk();
    
    io_set_pin_mux(PORTB, PORT_PB12, SET_PIN_MUX_H);
    io_set_pin_mux(PORTB, PORT_PB13, SET_PIN_MUX_H);
    can_init(CAN1);
    
    /* Replace with your application code */
    while (1) 
    {
        can_test();
    }
}

canbus.c

#define CAN_TX_FIFO_SIZE        2
#define CONF_CAN1_BTP_TSEG2     2
#define CONF_CAN1_BTP_TSEG1     13
#define CONF_CAN1_BTP_BRP       1
#define CONF_CAN1_BTP_SJW       1


volatile static uint8_t can1_rx_fifo[CAN1_RX_FIFO_ELEMENTS * 16] __attribute__((__aligned__(4)));
volatile static uint8_t can1_tx_fifo[CAN1_RX_FIFO_ELEMENTS * 16] __attribute__((__aligned__(4)));

void can_init(Can* canbus)
{
        /*Unlocks CAN1 for editing.*/
    canbus->CCCR.bit.INIT = 1;
    while (canbus->CCCR.bit.INIT != 1) {}
    canbus->CCCR.bit.CCE = 1;
    
    /*Defines memory priority for message RAM access as not sensitive operation (lowest priority).*/
    canbus->MRCFG.reg = CAN_MRCFG_QOS_DISABLE;
    
    /*Sets up the time quanta timing for normal speed operation (1Mbps).*/
    canbus->NBTP.reg = CAN_NBTP_NBRP(CONF_CAN1_BTP_BRP - 1) | CAN_NBTP_NTSEG1(CONF_CAN1_BTP_TSEG1 - 1)                                    
                    | CAN_NBTP_NTSEG2(CONF_CAN1_BTP_TSEG2 - 1) | CAN_NBTP_NSJW(CONF_CAN1_BTP_SJW - 1);
                    
    /*RX FIFO 0 configuration, blocking mode, watermark interrupt disabled, sets buffer size and start address.*/
    canbus->RXF0C.reg = CAN_RXF0C_F0S(CAN1_RX_FIFO_ELEMENTS) | CAN_RXF0C_F0SA((uint32_t)can1_rx_fifo);
    
    /*Sets the size of data field for the RX/TX FIFO, operating in CAN2.0B not FD, so this is always 8 bytes.*/
    canbus->RXESC.reg = CAN_RXESC_F0DS_DATA8;
    canbus->TXESC.reg = CAN_TXESC_TBDS_DATA8;
    
    /*Sets the size and start address of the TX FIFO.*/
    canbus->TXBC.reg = CAN_TXBC_TFQS(CAN1_RX_FIFO_ELEMENTS) | CAN_TXBC_TBSA((uint32_t)can1_tx_fifo);
    
    /*Reset the CCE and INIT bits to start CAN operation.*/
    canbus->CCCR.bit.CCE = 0;
    canbus->CCCR.bit.INIT = 0;
    while (canbus->CCCR.bit.INIT != 0) {}
}

int32_t can_tx_immediate(Can* canbus, can_tx_fifo_entry_t* message)
{
    volatile can_tx_fifo_entry_t* f = NULL;
    uint32_t put_index;

    /*Check if FIFO is full.*/
    if (canbus->TXFQS.bit.TFQF != 0) {
        return -1;
    }

    /*Determine which index to put the new msg at.*/
    put_index = canbus->TXFQS.bit.TFQPI;

    if (canbus == CAN1) {
        /*Set the address of f based on the put index.*/
        f = (can_tx_fifo_entry_t*)(can1_tx_fifo + put_index * 16);
    }

    if (f == NULL) {
        return -1;
    }

    /*Copy into FIFO.*/
    memcpy(f, message, 16);

    /*Request the transmission.*/
    canbus->TXBAR.reg = 1 << put_index;
}

void can_test()
{
    volatile can_tx_fifo_entry_t new_msg;
    
    /*Initialize these to zero.*/
    new_msg.T0.val = 0;
    new_msg.T1.val = 0;
    
    new_msg.data[0] = 0x00;
    new_msg.data[1] = 0x01;
    new_msg.data[2] = 0x02;
    new_msg.data[3] = 0x03;
    new_msg.T0.bit.ESI = 0;
    new_msg.T0.bit.XTD = 0;             //Standard length ID.
    new_msg.T0.bit.RTR = 0;             //Standard frame.
    new_msg.T0.bit.ID  = 0x69 << 18;    //Standard length ID needs to be passed down 18 bits.
    new_msg.T1.bit.DLC = 4;             //4 bytes of data.
    new_msg.T1.bit.FDF = 0;             //Not FD mode.
    new_msg.T1.bit.BRS = 0;             //No bit rate switching.
    new_msg.T1.bit.EFC = 0;             //Dont store events.
    can_tx_immediate(CAN1, &new_msg);   
}

总线状态对比

无编译优化时CAN总线运行状态

CAN总线无编译优化运行状态

开启编译优化时CAN总线运行状态

开启优化后总线会进入Bus Off模式,Error Passive、Error Warning、Bus Off位均置位,LEC为0x2。
CAN总线开启编译优化运行状态

内容的提问来源于stack exchange,提问作者Alex Jegers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:44:52