SylixOS CAN总线初始化流程解析

  1. 概述

    本文档是在AT91SAM9X25平台上进行SylixOS CAN总线驱动开发时,对CAN总线初始化流程的分析。

    适用于正在学习CAN总线开发的技术工程师。

  2. 技术实现

    CAN总线的初始化流程可以分成两个部分:

    一部分是CAN总线通道资源初始化,主要工作是对通道相关的管脚和中断以及总线编程时需要的时钟等资源的初始化;另一部分是CAN总线的硬件初始化,主要工作是对总线的波特率的设置、接收和发送数据邮箱(相当于缓存区)的初始化以及接收中断和错误中断的使能。

  3. CAN总线通道资源初始化

    在AT91SAM9X25平台上,CAN总线通道资源初始化如图 21所示。CAN总线的TX管脚、RX管脚和时钟的使能以及中断服务函数的绑定是CAN总线在初始化时必须做的工作。CAN总线的通信需要绑定CAN总线上层回调函数,这些上层回调函数由开发者实现,用做应用层和底层的通信。时钟的获取是总线工作需要用到的数据,我们在总线初始化时先将其获取存在全局结构体变量中。

    图 21 CAN总线通道资源初始化流程图

    具体的代码实现如程序清单 21所示。

    程序清单 21 CAN总线通道资源初始化

    /*********************************************************************************************************
    ** 函数名称: __canChanDataInit
    ** 功能描述: 初始化通道数据(资源)相关
    ** 输  入  : uiChannel :通道号
    ** 输  出  : ERROR_CODE
    ** 全局变量:
    ** 调用模块:
    *********************************************************************************************************/
    static INT __canChanDataInit (UINT  uiChannel)
    {
        __PCAN_CHANNEL    pChannel;
        ULONG             ulVector;
        UINT              uiInputClock;
        INT               iRet;
    
        static CPCHAR  pcCanIsrName[] = {"can_isr0", "can_isr1"};           /*  const char类型的can中断名称 */
    
        if (uiChannel >= CAN_CHAN_NUMS) {
            printk("channel invalid.\n");
            return  PX_ERROR;
        }
    
        pChannel   = &__GCanChannels[uiChannel];                            /*  定义一个全局通道类型结构体  */
    
        __canIomuxConfig(uiChannel);                                        /*  管脚复用                    */
        uiInputClock = __at91sam9X25SysClkGet(MCK);                         /*  获取系统时钟                */
    
        pChannel->CANCH_uiInputClock      = uiInputClock;
        pChannel->CANCH_canchan.pDrvFuncs = &__GCanDrvFuncs;                /*  绑定CAN 总线上层回调函数    */
        pChannel->CANCH_uiMb0Id           = 0x7FF;
        API_AtomicSet(0, &pChannel->CANCH_atomicRef);                       /*  原子赋值操作                */
    
        ulVector = pChannel->CANCH_ulVector;                                /*  中断号                      */
        iRet     = (INT)API_InterVectorConnect(ulVector,                    /*  绑定中断服务函数            */
                                               (PINT_SVR_ROUTINE)__canIrq,
                                               (PVOID)pChannel,
                                                pcCanIsrName[uiChannel]);
        if (iRet != ERROR_NONE) {
            printk("interrupt vector connect error.\n");
            return PX_ERROR;
        }
    
        API_InterVectorEnable(pChannel->CANCH_ulVector);                    /*  使能对应中断                */
    
        return ERROR_NONE;
    }
     
  4. CAN总线硬件初始化

    在AT91SAM9X25平台上,CAN总线硬件初始化如图 22所示。中断使能和波特率设置是每个CAN总线都需要做的工作。CAN总线波特率是根据具体使用情况和芯片的硬件特性决定的,需要配置相关寄存器来实现。消息邮箱是AT91SAM9X25平台特有的用来接收和发送消息的一组寄存器,相当于发送和接收缓存区。这些邮箱可以根据开发者的需求来配置成接收或者发送模式。

    图 22 CAN总线硬件初始化流程图

    具体代码实现如程序清单 22所示。

    程序清单 22 CAN总线硬件初始化

    /*********************************************************************************************************
    ** 函数名称: __canChanHwInit
    ** 功能描述: 硬件初始化
    ** 输  入  : pChannel :通道对象
    ** 输  出  : ERROR_CODE
    ** 全局变量:
    ** 调用模块:
    *********************************************************************************************************/
    static INT __canChanHwInit (__PCAN_CHANNEL  pChannel)
    {
        UINT  uiRegIer;
    
        writel(AT91_IRQ_ALL, REG_CAN_IDR(CHANNEL));                         /*  禁用所有中断                */
        writel(readl(REG_CAN_MR(CHANNEL)) & ~AT91_MR_CANEN,                 /*  CAN 总线失能                */
               REG_CAN_MR(CHANNEL));
        __canSetBaudRate(pChannel, CAN_MAX_BAUDRATE);                       /*  设置CAN波特率               */
        __canSetMailboxes(pChannel);                                        /*  配置消息邮箱                */
    
        writel(AT91_MR_CANEN, REG_CAN_MR(CHANNEL));                         /*  CAN 总线使能                */
    
        uiRegIer = (AT91_MB_MASK(TX_FIRST) & (~AT91_MB_MASK(TX_FIRST)))     /*  0-5邮箱中断位               */
                    | AT91_IRQ_ERRP                                         /*  被动错误中断使能            */
                    | AT91_IRQ_ERR_FRAME;                                   /*  帧错误中断使能              */
        writel(AT91_IRQ_ALL, REG_CAN_IDR(CHANNEL));                         /*  禁用所有中断                */
    
        writel(uiRegIer, REG_CAN_IER(CHANNEL));                             /*  使能错误中断和0-5邮箱中断   */
    
        return  ERROR_NONE;
    }
     
  5. 免责声明

    内部交流文档,仅针对AT91SAM9X25相关平台,若发现相关错误或者建议,请及时联系文档创建者进行修订和更新。

猜你喜欢

转载自my.oschina.net/u/3249576/blog/881248