嵌入式技术论坛
直播中

贾飞世

7年用户 1815经验值
私信 关注
[经验]

调试RT-Thread CAN通讯导致出现异常的原因整理

近几天在调试RT的CAN,发现了一些问题,会导致CAN通讯异常,整理了一下分享给大家

1、针对于APB1总线为42M的时钟配置,会导致波特率异常

会有这样一种情况,比如使用了F429的芯片,但是外部配了个8M XTAL,所以过了锁相环之后一般是168M的sys_clock,这样会导致APB1总线为42M,而RT在做CAN的波特率的时候针对于APB1时钟42M和45M的配置是不一样的。

如下图

#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\

defined(STM32F401xC) || defined(STM32F401xE) || 1 /* 42MHz(max) */

static const struct stm32_baud_rate_tab can_baud_rate_tab[] =

{

{CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_4TQ | 3)},

{CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_5TQ | 4)},

{CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_4TQ | 6)},

{CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 12)},

{CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 24)},

{CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 30)},

{CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 60)},

{CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 150)},

{CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 300)}

};

#else /* APB1 45MHz(max) */

static const struct stm32_baud_rate_tab can_baud_rate_tab[] =

{

{CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 3)},

{CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ  | CAN_BS2_5TQ | 4)},

{CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 6)},

{CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 12)},

{CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 24)},

{CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 30)},

{CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 60)},

{CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 150)},

{CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ  | CAN_BS2_5TQ | 300)}

};

#endif

当然原来RT的42M的时钟配置不是这样的,(官方给的42M的时钟配置和45M的是完全一样的,我的RT是4.0.3)以上代码是改过后的42M的时钟配置

2、RT的CAN设备的使用会导致当前线程会被阻塞,CAN设备有时也会被阻塞

该问题主要是由于drv_can.c里的底层的错误状态导致进入无效循坏。当然这个问题在论坛里好多大神进行过讨论,亲测注释掉错误标志是最为有限的方法,其余的包括开启自动重发等等,皆试过,没有任何用,改后的代码在下方,仅供参考

static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)

{

CAN_HandleTypeDef *hcan;

hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle;

struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;

CAN_TxHeaderTypeDef txheader = {0};

HAL_CAN_StateTypeDef state = hcan->State;

/* Check the parameters */

RT_ASSERT(IS_CAN_DLC(pmsg->len));

if ((state == HAL_CAN_STATE_READY) ||

        (state == HAL_CAN_STATE_LISTENING))

{

    /*check select mailbox  is empty */

    switch (1 << box_num)

    {

    case CAN_TX_MAILBOX0:

        if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0) != SET)

        {

            /* Change CAN state */

// hcan->State = HAL_CAN_STATE_ERROR;

/* Return function status */

            return -RT_ERROR;

        }

        break;

    case CAN_TX_MAILBOX1:

        if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1) != SET)

        {

            /* Change CAN state */

// hcan->State = HAL_CAN_STATE_ERROR;

/* Return function status */

            return -RT_ERROR;

        }

        break;

    case CAN_TX_MAILBOX2:

        if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2) != SET)

        {

            /* Change CAN state */

// hcan->State = HAL_CAN_STATE_ERROR;

/* Return function status */

            return -RT_ERROR;

        }

        break;

    default:

        RT_ASSERT(0);

        break;

    }

    if (RT_CAN_STDID == pmsg->ide)

    {

        txheader.IDE = CAN_ID_STD;

        RT_ASSERT(IS_CAN_STDID(pmsg->id));

        txheader.StdId = pmsg->id;

    }

    else

    {

        txheader.IDE = CAN_ID_EXT;

        RT_ASSERT(IS_CAN_EXTID(pmsg->id));

        txheader.ExtId = pmsg->id;

    }

    if (RT_CAN_DTR == pmsg->rtr)

    {

        txheader.RTR = CAN_RTR_DATA;

    }

    else

    {

        txheader.RTR = CAN_RTR_REMOTE;

    }

    /* clear TIR */

    hcan->Instance->sTxMailBox[box_num].TIR &= CAN_TI0R_TXRQ;

    /* Set up the Id */

    if (RT_CAN_STDID == pmsg->ide)

    {

        hcan->Instance->sTxMailBox[box_num].TIR |= (txheader.StdId << CAN_TI0R_STID_Pos) | txheader.RTR;

    }

    else

    {

        hcan->Instance->sTxMailBox[box_num].TIR |= (txheader.ExtId << CAN_TI0R_EXID_Pos) | txheader.IDE | txheader.RTR;

    }

    /* Set up the DLC */

    hcan->Instance->sTxMailBox[box_num].TDTR = pmsg->len & 0x0FU;

    /* Set up the data field */

    WRITE_REG(hcan->Instance->sTxMailBox[box_num].TDHR,

              ((uint32_t)pmsg->data[7] << CAN_TDH0R_DATA7_Pos) |

              ((uint32_t)pmsg->data[6] << CAN_TDH0R_DATA6_Pos) |

              ((uint32_t)pmsg->data[5] << CAN_TDH0R_DATA5_Pos) |

              ((uint32_t)pmsg->data[4] << CAN_TDH0R_DATA4_Pos));

    WRITE_REG(hcan->Instance->sTxMailBox[box_num].TDLR,

              ((uint32_t)pmsg->data[3] << CAN_TDL0R_DATA3_Pos) |

              ((uint32_t)pmsg->data[2] << CAN_TDL0R_DATA2_Pos) |

              ((uint32_t)pmsg->data[1] << CAN_TDL0R_DATA1_Pos) |

              ((uint32_t)pmsg->data[0] << CAN_TDL0R_DATA0_Pos));

    /* Request transmission */

    SET_BIT(hcan->Instance->sTxMailBox[box_num].TIR, CAN_TI0R_TXRQ);

    return RT_EOK;

}

else

{

    /* Update error code */

    hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;

    return -RT_ERROR;

}

}

原作者:jia868

更多回帖

发帖
×
20
完善资料,
赚取积分