精华内容
下载资源
问答
  • 计算机教材中关于CPU总线周期时序描述的原理性错误.pdf
  • CAN总线错误分析方法

    万次阅读 2018-05-23 16:39:51
    我们先简单总结一下CAN的错误处理与故障界定: 1.CAN控制器记录发生在发送/接收过程...位于主动错误的节点,在检测到错误时,可以发送主动错误标志(6位显性位),告知总线上所有节点发生了总线错误,之后进行正...

        我们先简单总结一下CAN的错误处理与故障界定:

        1.CAN控制器记录发生在发送/接收过程中,总线数据出现错误的总数(位错误,CRC错误等)。

        2.CAN控制器根据总线出错数量由低到高,依次处于主动错误状态,被动错误状态,以及总线关闭状态。

        3.位于主动错误的节点,在检测到错误时,可以发送主动错误标志(6位显性位),告知总线上所有节点发生了总线的错误,之后进行正常的收发操作。保证如果总线CAN_H与CAN_L出现短路等会影响整个总线通讯的问题时,各个控制器会迅速反应。

           当随着发送/接收错误总数的增加,节点将位于被动错误状态,当检测到总线发生错误的时候,将等待总线出现被动错误帧(连续6位隐性位),之后才可正常进行收发操作。保证如果总线因为线长或者节点数增大,远处的节点干扰严重,则干扰严重的节点将不会影响其余节点的正常通信。

            如果发送错误总数达到了255,则进入bus-off状态,处于这种状态的节点将会与总线隔离,直到检测到128 次出现11 个连续“隐性”位后,才可以恢复错误主动状态,错误计数器 也清零。

    1.Linux SocketCAN

        Linux 4.17.0-RC6 内核网络部分增加了SocketCAN,用于Linux的CAN协议的一种实现。以前的嵌入式开发板的CAN驱动是以基于字符串设备的驱动注册到内核中,新的内核使用Berkeley套接字API,Linux网络堆栈并将CAN设备驱动程序作为网络接口来实现。CAN套接字API的设计与TCP / IP协议尽可能相似,以便熟悉网络编程的程序员轻松使用CAN套接字进行CAN通信。具体详细的特性介绍详见https://www.kernel.org/doc/html/latest/networking/can.html。其中章节“Network Problem Notifications中介绍了一种CAN总线错误的记录机制,SocketCAN将所有总线上的错误包装成一个“错误帧”,注意这块的“错误帧”不是CAN总线上实际跑的错误帧,而是驱动部分将控制器或者总线上的检测的错误,包装成一个CAN帧,上报给基于网络层之上的用户程序。

        我们在linux4.9内核E:\linux-4.9\linux-4.9\drivers\net\can目录下的Makefile中看到内核支持了包括SJA1000,以及赛灵思的开发板的CAN驱动支持,我们比较关心的CAN错误的定义呢,在E:\linux-4.9\linux-4.9\include\uapi\linux\can中定义了所有CAN总线可能上报给用户层的错误信息具体的关系图如下:

        

    三个能展开的三级目录分别如下:

       

         这其中我们举个例子来说明这个伪造的错误帧是如何产生的,以AT91的驱动为例,下面的描述均来自内核源码。首先在设备的Open函数处注册了中断处理函数at91_irq,函数在发生终端时候,判断中断类型为错误中断,调用at91_irq_err处理设备错误信息,细分中断源来定义当前新状态为bus-off、报警、主动错误状态还是被动错误状态,如果状态发生了变化,则调用at91_irq_err_state形成错误帧进行上报。假如这个时候如果原状态为主动错误,而新的状态为RX/TX错误计数达到报警状态,则会更新设备当前状态,并向上层监听端口的用户程序发送一个表示控制器错误-->RX/TX错误计数达到报警状态的错误帧。用户程序就可以知道CAN总线发生了这样的错误,并检查干扰源。

    2.STM32F10x bxCAN

        工业现场的总线上一般有两种设备,一种为普通的can节点设备,他们在整条总线上按需分布,反馈一些即时的信息(传感器信息或者摁键等),另一种设备一般一根CAN总线上就一台这样的设备,它负责将CAN总线上的数据转发到以太网接口,WIFI,或者zigbee等通信接口,或者它本身带有屏幕,显示各个节点上报的信息并进行统一的控制。这种类似‘网关’的设备一般会上嵌入式实时操作系统,或者linux内核裁剪一下拿QT做做界面,或者直接就安卓了。

        反观线上多数的设备,一般为了压低成本等原因,会采用STM32来进行开发,而总线上的状态,往往是这些处于总线远端的设备能更好的体现,并且出问题的设备也大概率会是这些设备,但是这些设备往往没有实时操作系统,业务开发起来比较缓慢且不易多人维护,导致往往对于异常的处理不足,关注实现往往大于功能实现的效率以及质量。而其更没有Linux比较完善的官方驱动支持,如上文一样可以给用户程序主动报一些总线上的错误。所以,基于STM32开发CAN的时候,更应该借鉴Linux的驱动实现方式,对总线上的错误进行记录,方便查询。

        我们首先来分析一下STM32 bxCAN的错误中断源:

        

        由上图可知,ERRIE为错误中断的总使能位,EWGIE为错误警告中断使能,当接收/发送的错误数到达报警标准之后触发此中断,EPVIE为错误被动中断使能,当接收/发送的错误数到达被动错误标准时触发此中断,BOFIE为离线中断使能,当接收/发送的错误数到达离线标准时触发此错误,LECIE为上次错误号中断使能,当接收/发送出现错误的时候,且与上次错误不同,触发此中断,错误号根据手册能表示一下错误:000: No Error,001: Stuff Error,010: Form Error,011: Acknowledgment Error,100: Bit recessive Error,101: Bit dominant Error,110: CRC Error,111: Set by software。

        在发送过程,bxCan有三个发送mailbox,STM32的库函数CAN_Transmit负责将数据放到mailbox中并触发发送(若没有空闲的mailbox则返回错误),由手册可知,可根据TME来判断mailbox是否可能,库函数CAN_TransmitStatus封装好能够直接获得当前mailbox的状态,这里建议对CAN控制器的CAN_NART配置为DISABLE,使能报文重传功能,这样报文如果发送失败,将在SCHEDULED和TRANSMIT两个状态切换,直到发送完毕,才会释放邮箱。除非你的应用需要报文发送的准确时间点进行记录,并且你的应用实时性要求也不高,能够腾出时间去处理报文重传(如果你把CAN控制器的报文重传功能去掉了,那你必然要自己实现)。从这个流程中可以看出,我们可以将发送溢出(邮箱占满),以及发送仲裁丢失作为控制器的错误记录下来。

        在接收过程中,就有接收溢出的中断可供记录接收溢出错误。

        综上所述,STM32F10x bxCAN提供的寄存器能够满足类似Linux的除了收发器其余的所有错误记录,通过库函数能够很方便的将CAN控制器的状态变化以及总线上的错误记录下来,从而可以分析现场CAN总线的状态。

        

    展开全文
  • CAN总线错误分析与解决

    万次阅读 多人点赞 2017-04-12 00:41:23
    CAN总线错误分析与解决 ...这篇不打算CAN的错误处理机制做进一步的探讨,而是从实际工作中碰到的具体问题来分析一些常见的CAN总线错误和解决办法。 CAN节点数据收发过程 了解CAN节点在总线上数据上的收发

    CAN总线错误分析与解决

    1. 背景

    写这篇文章是因为我看到网上介绍CAN总线错误处理的文章,清一色的都是生搬照抄教科书或是数据文档的内容,特别是国内很难找到一些有价值的内容,这让一些真正有需要的人很苦恼,包括我自己。这篇不打算对CAN的错误处理机制做进一步的探讨,而是从实际工作中碰到的具体问题来分析一些常见的CAN总线错误和解决办法。

    1. CAN节点数据收发过程

    了解CAN节点在总线上数据上的收发过程很重要,之前的一篇文章讲解了一些CAN总线的错误处理机制,但是那些都是理论上的东西,如果不深入了解CAN总线上的数据收发过程,理解那些理论的东西难免有些晦涩。

    我们知道CAN总线上的每个节点往总线上发送数据的同时会同时读取总线上的数据,并与自己发送的数据作对比。

    CAN信息发送成功后,在这个间隙内,接收节点可以准备要回复的信息,也就是把应答场填充为显性0,在发送时其为隐性1应答过程可能如下:当信息传输到ACK前的Del时,可以认为信息已经传输完毕,接收节点也接收到了足够的信息来检测接收的信息是否正确,所以这时接收节点就会检测信号是否正确,如果正确,就将ACK置位为显性0,注意这时,发送节点因为还在发送而接收节点又将ACK信息置位为1,所以它就会在回读时检测到ACK为0,判断接收成功。注意:这其中有个接收节点用显性覆盖隐性---覆盖ACK位的过程,覆盖+回读。

    ACK前后各加一个Del,就是为了考虑到时间误差,让接收节点有足够的时间对ACK确认。这个过程说明,CAN发送是个双向互动的过程,发送节点一边发送,一边对节点进行回收确认数据正确,而接收节点也时刻接收,并在正确的时间将ACK设置为1。

    1. CAN总线错误

    CAN总线错误分别有发送和接收错误计数,计数达到一定的累计以后就会产生CAN BUS OFF, 这说明CAN总线上出现了严重的错误。如下图CAN总线产生错误后的状态转换机制:

    如果出现了BUS OFF,总线上的节点需要做一些动作,例如重启CAN控制器或是重新上电,但是这些都只是一些补救措施,最根本的还是需要找到引起BUS OFF的根源。

    CAN总线分析的一些工具和文档:

    • CAN分析仪或者逻辑分析仪
    • 数字示波器
    • 相关的软件debug工具
    • CAN控制器芯片数据手册,这很重要
    • 硬件电路图
    • CAN协议文档
    • 相关版本的Linux内核源码

     

    1. CAN节点发送错误不成功

      1. 问题描述与分析

    挂载在CAN总线上的一个节点向总线上发送数据不成功,用逻辑分析仪也看不到任何波形。PS: 这应该是我碰到的最坑爹的事情了。下面具体来看看怎么不成功。于是调试中断查看CAN_STATUS即CAN状态寄存器显示0xE5, 查看CPU数据手册:

     

    CAN总线状态直接进入了BUS OFF状态,这意味着错误计数已经超限,查看CPU收发寄存器的收发错误计数显示发送错误计数TEC达到248, 接收错误计数为0;这很明显,数据压根没有发送到总线上。

    再进一步查看寄存器值LEC即LAST ERROR CODE 最后一个错误代码, 显示是BIT0 ERROR:

    查看上面的错误代码表可知,BIT0错误也就是在发送数据期间,虽然CAN节点设备想要发送一个显性位,也就是逻辑0,但是CAN总线同时监听到总线上的数据位为隐性位,即逻辑1。这意味着CAN core往总线上发送的数据第一位就已经出错了,压根没有将数据经过CAN收发器传送到CAN总线上。

    一直在使用CAN总线的我厂和我从来没遇到这等奇事,但是由于是新的CPU的开发所以在怀疑硬件的问题的同时也在排查软件问题,但是经过一阵排查,没有发现软件上的问题。回头再分析硬件,又经过一阵排查溯源,发现CPU的CAN收发线与CAN收发气的收发线接反,直接崩溃(PS: 硬件的大哥你能不能不要坑小弟):

    1. 总结

    CAN节点发送数据不成功,首先分析是不是CAN控制器本身的问题,查看CPU中的CAN core的状态寄存器,分析是否有BUS OFF, 如果存在BUS OFF, 则进一步查看具体的错误信息,是主动的错误还是被动的错,发送错误计数有没有超限,最后一次发生的错误状态是什么,查看是位填充错误还是格式错误等其他错误,然后具体问题具体分析。这种错误一般是有硬件发送线路出现问题引起,例如光隔次边不导通,发送接口接触不良等,再则是一些奇葩的错误,例如本例,收发线直接接反了,坑爹啊!

     

    1. CAN Socket 的CAN节点检测到错误帧

      1. 问题描述

    我们看到以下的CAN Socket日志,在38秒内的三个错误帧,但是并没有引起总线的BUS OFF,这说明总线上检测到了错误,有可能受到了干扰,也有可能是数据发送太密集导致的总线过载,但是在这38秒内出现错误,但是期间又恢复正常。

    CAN ID : 0x20000004 = 10 0000 0000 0000 0000 0000 0000 0100, 即仲裁域的值。

    1. Linux内核源码分析

    因为出现此错误的是我厂的CAN控制器CPU TI 公司的AM3352, 内核版本为Linux 3.2.0

    所以我们通过内核来看内核CAN错误can_id的定义:

    1. /* error class (mask) in can_id */  
    2.   
    3. #define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */  
    4.   
    5. #define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */  
    6.   
    7. #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */  
    8.   
    9. #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */  
    10.   
    11. #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */  
    12.   
    13. #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */  
    14.   
    15. #define CAN_ERR_BUSOFF 0x00000040U /* bus off */  
    16.   
    17. #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */  
    18.   
    19. #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */  
    /* error class (mask) in can_id */
    
    #define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
    
    #define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
    
    #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
    
    #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
    
    #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
    
    #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
    
    #define CAN_ERR_BUSOFF 0x00000040U /* bus off */
    
    #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
    
    #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
    

    由错误帧CAN ID : 0x20000004 = 10 0000 0000 0000 0000 0000 0000 0100, 去除最高为的1(SOFZ帧起始位?),因为仲裁位是29位,所以应该是0 0000 0000 0000 0000 0000 0000 0100 =0x00000004,既不是CAN_ERR_BUSOFF也不是CAN_ERR_BUSERROR, 而是CAN_ERR_CTRL, 即CAN控制器的问题,而我们在看data[1]描述的CAN 控制器错误类型描述:

    1. /* error status of CAN-controller / data[1] */  
    2.   
    3. #define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */  
    4.   
    5. #define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */  
    6.   
    7. #define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */  
    8.   
    9. #define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */  
    10.   
    11. #define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */  
    12.   
    13. #define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */  
    14.   
    15. #define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */  
    /* error status of CAN-controller / data[1] */
    
    #define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
    
    #define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
    
    #define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
    
    #define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
    
    #define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
    
    #define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
    
    #define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
    

    我们再看我们截取的错误帧数据报文中显示data[1] = 0x04,如下图所示:

    即具体错误为:

    #define CAN_ERR_CRTL_RX_WARNING  0x04 /* reached warning level for RX errors */

    也就是说CAN 控制器接收错误计数达到了警告的级别,需要提出警告,如果再这样下去CAN控制器就要过载了,甚至会引起总线的BUS OFF.

    我们再回头看内核源码对此错误的处理:产生data[1] = CAN_ERR_CRTL_RX_WARNING 错误的内核源函数为:

    1. static int ti_hecc_error(struct net_device *ndev, int int_status,  
    2.   
    3. int err_status)  
    static int ti_hecc_error(struct net_device *ndev, int int_status,
    
    int err_status)
    

    HECC也就是TI公司高速终端CAN控制器的简称,用以上的函数描述TI CAN core的错误处理,如下,我们可以看到也就是CAN控制器接收错误计数REC大于96的时候内核就会报此错误

    1. if (int_status & HECC_CANGIF_WLIF) { /* warning level int */  
    2.         if ((int_status & HECC_CANGIF_BOIF) == 0) {  
    3.             priv->can.state = CAN_STATE_ERROR_WARNING;  
    4.             ++priv->can.can_stats.error_warning;  
    5.             cf->can_id |= CAN_ERR_CRTL;  
    6.             if (hecc_read(priv, HECC_CANTEC) > 96)  
    7.                 cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;  
    8.             if (hecc_read(priv, HECC_CANREC) > 96)  
    9.                 cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;  
    10.         }  
    11.         hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);  
    12.         dev_dbg(priv->ndev->dev.parent, "Error Warning interrupt\n");  
    13.         hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);  
    14.     }  
    if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
            if ((int_status & HECC_CANGIF_BOIF) == 0) {
                priv->can.state = CAN_STATE_ERROR_WARNING;
                ++priv->can.can_stats.error_warning;
                cf->can_id |= CAN_ERR_CRTL;
                if (hecc_read(priv, HECC_CANTEC) > 96)
                    cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
                if (hecc_read(priv, HECC_CANREC) > 96)
                    cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
            }
            hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
            dev_dbg(priv->ndev->dev.parent, "Error Warning interrupt\n");
            hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
        }
    

    1. 总结

    出现这个错误警告的原因很可能是:

    1. CAN总线上有干扰,导致CAN控制器发生接收错误,CAN总线上的信号经过收发器转化为差分电平信号,此时信号容易受到外界干扰,这样容易使CAN控制器发生接收错误,接收错误寄存器接收错误计数累计到一定值后会报此错误,如果错误计数达到一定程度甚至会导致总线关闭也就是BUS OFF. 如果最终确认是由于干扰引起的错误计数累计,则应该排查干扰源,然后增加抗干扰措施。
    2. CAN节点经过消息滤波后仍然需要接收大量的消息,导致CPU中的CAN控制器接收出错,并且错误计数达到了错误警告的上限。但是庆幸的是总线仍然没有过载,总线还可以正常收发数据,没有引起BUS OFF。但是对于一个安全可靠控制系统,这样的警告是绝对不允许的。我们需要通过一些手段去避免这样的问题出现,例如降低总线数据并发量,降低总线负载。

       

    1. CAN总线设备离线与错误恢复

    这种问题同样很诡异,但是似乎又是比较常见的问题,这样的问题出现的情况往往比较多,例如CAN节Power off也就是电断了,总线上也就肯定监听不到此CAN节点的心跳,或是CAN总线节点没有及时发送心跳,阻塞在任务处理里,又或是此CAN节点物理接线和总线断开,等等原因很多。

    我这里要说的一种情况是我厂碰到的另一种问题。

    1. 问题描述

    在整个系统重启后发现CAN总线上的某一个Cortex M0设备节点丢失,而其他的设备,也是同样M0架构的MCU和相同控制软件的设备则没有出现丢失的情况。

    未完待续。

    
    展开全文
  • 错误信息引起这两种错误的源代码错误并没有作简单的解释,上面的信息并未提供如何从代码中寻找错误的线索,而且两者之间的区别也并不是十分清楚,时至今日依然如此。 错误就是操作系统所检测到的异常,而这个异常...

    C 总线错误 (bus error) - 段错误 (segmentation fault)

    两个常见的运行时错误

    • bus error (core dumped) - 总线错误 (信息已转储)
    • segmentation fault (core dumped) - 段错误 (信息已转储)

    错误信息对引起这两种错误的源代码错误并没有作简单的解释,上面的信息并未提供如何从代码中寻找错误的线索,而且两者之间的区别也并不是十分清楚,时至今日依然如此。

    错误就是操作系统所检测到的异常,而这个异常是尽可能地以操作系统方便的原则来报告的。总线错误和段错误的准确原因在不同的操作系统版本上各不相同。这里所描述是运行于 SPARC 架构的 SunOS 出现的这两类错误以及产生错误的原因。

    当硬件告诉操作系统一个有问题的内存引用时,就会出现这两种错误。操作系统通过向出错的进程发送一个信号与之交流。信号就是一种事件通知或一个软件中断,在 UNIX 系统编程中使用很广,但在应用程序编程中几乎不使用。在缺省情况下,进程在收到总线错误段错误信号后将进行信息转储并终止。不过可以为这些信号设置一个信号处理程序 (signal handler),用于修改进程的缺省反应。

    信号是由于硬件中断而产生的。对中断的编程是非常困难的,因为它们是异步发生的 (其发生时间是不可预测的)。阅读信号的主文档和头文件 usr/include/sys/signal.h

    1. 在 PC 上捕捉信号

    信号处理函数是 ANSI C 的一部分,与 UNIX 一样,它也同样适用于 PC。例如 PC 程序员可以使用 signal() 函数来捕捉 Ctrl-Break 信号,防止用户用这种方法中断程序。

    在任何使用信号的源文件中,都必须在文件前面增加一行 #include <singal.h>

    这条信息的 core dumped 部分来源于很早的过去,那时所有的内存都是由铁氧化物圆环 (也就是 core,指磁心) 制造的。半导体成为内存的主要制造材料的时间已经超过十五年,但 core 这个词仍然被用作内存的同义词。

    core [kɔː(r)]:n. 核心,要点,果心,磁心 vt. 挖...的核
    

    2. 总线错误 (bus error)

    事实上,总线错误几乎都是由于未对齐的读或写引起的。它之所以称为总线错误,是因为出现未对齐的内存访问请求时,被堵塞的组件就是地址总线。对齐 (alignment) 的意思就是数据项只能存储在地址是数据项大小的整数倍的内存位置上。在现代的计算机架构中,尤其是 RISC 架构,都需要数据对齐,因为与任意的对齐有关的额外逻辑会使整个内存系统吏大且更慢。通过迫使每个内存访问局限在一个 Cache 行或一个单独的页面内,可以极大地简化 (并加速) 如 Cache 控制器和内存管理单元这样的硬件。

    我们表达数据项不能跨越页面或 Cache 边界规则的方法多少有些问接,因为我们用地址对齐这个术语来陈述这个问题,而不是直截了当说是禁止内存跨页访问,但它们说的是同一回事。例如,访问一个 8 字节的 double 数据时,地址只允许是 8 的整数倍。所以一个 double 数据可以存储于地址 24、8008 或 32768,但不能存储于地址 1006 (因为它无法被 8 整除)。页和 Cache 的大小是经过精心设计的,这样只要遵守对齐规则就可以保证一个原子数据项不会跨越一个页或 Cache 块的边界。

    2.1 引起总线错误的程序

    //============================================================================
    // Name        : main
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
    	union union_name
    	{
    		char a[10];
    		int i;
    	} union_object;
    
    	printf("argc = %d\n", argc);
    
    	for (int idx = 0; idx < argc; ++idx)
    	{
    		printf("argv[%d] --> %s\n", idx, argv[idx]);
    	}
    
    	printf("argv[argc] = %p\n\n", (void*)argv[argc]);
    
    	int *pt = (int *)&(union_object.a[1]);
    	int *pi = (int *)&(union_object.i);
    
    	*pt = 17;
    
    	printf("*pt = %d\n", *pt);
    	printf("pt = %p\n", pt);
    	printf("pi = %p\n", pi);
    
    	return 0;
    }
    
    argc = 1
    argv[0] --> D:\visual_studio_workspace\yongqiang\Debug\yongqiang.exe
    argv[argc] = 00000000
    
    *pt = 17
    pt = 008FFA39
    pi = 008FFA38
    请按任意键继续. . .
    

    在这里插入图片描述

    pt 中未对齐的地址会引起一个总线错误!
    在实际的运行中并没有出现错误,运行环境如下:
    在这里插入图片描述

    x86 体系结构,如果没有默认对齐的话,访问速度会降低。读一个 int 本来只读一次的,没有对齐的话要读 2 次才行,把第一次的尾巴和第二次的头拼起来。如果在代码中将对齐检查功能打开,运行后能显示 bus error

    这可能导致一个总线错误,因为数组和 int 的联合确保数组 a 是按照 int 的 4 字节对齐的,a+l 的地址肯定未按 int 对齐。我们试图往这个地址存储 4 个字节的数据,但这个访问只是按照单字节的 char 对齐,这就违反了规则。一个好的编译器发现不对齐的情况时会发出警告,但它并不能检测到所有不对齐的情况。

    编译器通过自动分配和填充数据 (在内存中) 来进行对齐。当然,在磁盘或磁带上并没有这样的对齐要求,所以程序员对它们可以很偷快地不必关心数据对齐。但是,当他们把一个 char 指针转换为 int 指针时,就会出现神秘的总线错误。几年前,当检测到一个内存奇偶检验错误时也会产生总线错误。现在,内存芯片已经非常可靠,而且很好地得到了错误检测和修正电路的保护,所以在应用程序编程这一级,奇偶检验错误几乎不再听闻。总线错误也可能由于引用一块物理上不存在的内存引起。如果不遭遇一个淘气的驱动程序,你恐怕不大可能遭遇这种不幸。

    //============================================================================
    // Name        : main
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    
    int main(int argc, char **argv)
    {
    #if defined(__GNUC__)
    #if defined(__i386__)
    	/* Enable Alignment Checking on x86 */
    	__asm__("pushf\norl $0x40000,(%esp)\npopf");
    #elif defined(__x86_64__)
    	/* Enable Alignment Checking on x86_64 */
    	__asm__("pushf\norl $0x40000,(%rsp)\npopf");
    #endif
    #endif
    
    	union
    	{
    		char a[10];
    		int i;
    	} u;
    
    	int *p = (int*) &(u.a[1]);
    	*p = 17;
    
    	return 0;
    }
    
    
    16:26:55 **** Build of configuration Debug for project yongqiang_example ****
    make all 
    Building file: ../src/yongqiang.c
    Invoking: GCC C Compiler
    gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/yongqiang.d" -MT"src/yongqiang.o" -o "src/yongqiang.o" "../src/yongqiang.c"
    Finished building: ../src/yongqiang.c
     
    Building target: yongqiang_example
    Invoking: GCC C Linker
    gcc  -o "yongqiang_example"  ./src/yongqiang.o   
    Finished building target: yongqiang_example
     
    
    16:26:56 Build Finished (took 524ms)
    
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ pwd
    /home/strong/eclipse-work/yongqiang_example/Debug
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ ll
    total 56
    drwxrwxr-x 3 strong strong  4096 Mar 30 16:26 ./
    drwxrwxr-x 5 strong strong  4096 Mar 28  2018 ../
    -rw-rw-r-- 1 strong strong  1009 Mar 30 16:26 makefile
    -rw-rw-r-- 1 strong strong   231 Mar 30 16:26 objects.mk
    -rw-rw-r-- 1 strong strong   392 Mar 30 16:26 sources.mk
    drwxrwxr-x 2 strong strong  4096 Mar 30 16:26 src/
    -rwxrwxr-x 1 strong strong 29720 Mar 30 16:26 yongqiang_example*
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ 
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ ./yongqiang_example 
    Bus error (core dumped)
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$
    

    3. 段错误 (segmentation fault)

    段错误或段违规 (segmentation violation)。在 Sun 的硬件中,段错误是由于内存管理单元 (负责支持虚拟内存的硬件) 的异常所致,而该异常则通常是由于解除引用一个未初始化或非法值的指针引起的。如果指针引用一个并不位于你的地址空间中的地址,操作系统便会对此进行干涉。

    一个小型的会引起段错误的程序如下:

    	int *pt = 0;
    	*pt = 17;
    
    //============================================================================
    // Name        : main
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
    	printf("argc = %d\n", argc);
    
    	for (int idx = 0; idx < argc; ++idx)
    	{
    		printf("argv[%d] --> %s\n", idx, argv[idx]);
    	}
    
    	printf("argv[argc] = %p\n\n", (void*)argv[argc]);
    
    	int *pt = 0;
    	*pt = 17;
    
    	printf("*pt = %d\n", *pt);
    	printf("pt = %p\n", pt);
    
    	return 0;
    }
    
    
    16:31:07 **** Build of configuration Debug for project yongqiang_example ****
    make all 
    Building file: ../src/yongqiang.c
    Invoking: GCC C Compiler
    gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/yongqiang.d" -MT"src/yongqiang.o" -o "src/yongqiang.o" "../src/yongqiang.c"
    Finished building: ../src/yongqiang.c
     
    Building target: yongqiang_example
    Invoking: GCC C Linker
    gcc  -o "yongqiang_example"  ./src/yongqiang.o   
    Finished building target: yongqiang_example
     
    
    16:31:08 Build Finished (took 571ms)
    
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ pwd
    /home/strong/eclipse-work/yongqiang_example/Debug
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ 
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ ll
    total 56
    drwxrwxr-x 3 strong strong  4096 Mar 30 16:31 ./
    drwxrwxr-x 5 strong strong  4096 Mar 28  2018 ../
    -rw-rw-r-- 1 strong strong  1009 Mar 30 16:31 makefile
    -rw-rw-r-- 1 strong strong   231 Mar 30 16:31 objects.mk
    -rw-rw-r-- 1 strong strong   392 Mar 30 16:31 sources.mk
    drwxrwxr-x 2 strong strong  4096 Mar 30 16:31 src/
    -rwxrwxr-x 1 strong strong 29680 Mar 30 16:31 yongqiang_example*
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ 
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$ ./yongqiang_example 
    argc = 1
    argv[0] --> ./yongqiang_example
    argv[argc] = (nil)
    
    Segmentation fault (core dumped)
    strong@foreverstrong:~/eclipse-work/yongqiang_example/Debug$
    

    一个微妙之处是导致指针具有非法的值通常是由于不同的编程错误所引起的。和总线错误不同,段错误更像是一个间接的症状而不是引起错误的原因。

    一个更糟糕的微妙之处是,如果未初始化的指针恰好具有未对齐的值 (对于指针所要访问的数据而言),它将会产生总线错误,而不是段错误。对于绝大多数架构的计算机而言确实如此,因为 CPU 先看到地址,然后再把它发送给 MMU。

    violation [ˌvaɪəˈleɪʃn]:n. 违反,妨碍,侵害,违背,强奸
    

    在你的代码中,对非法指针值的解除引用操作可能会像上面这样显式地出现,也可能在库函数中出现 (传递给它一个非法值)。令人不快的是,你的程序如果进行了修改 (如在调试状态下编译或增加额外的调试语句),内存的内容便很容易改变,于是这个问题被转移到别处或干脆消失。段错误是非常难于解决的,而且只有非常顽固的段错误才会一直存在。当你看到同事们神色严峻地带着逻辑分析器和示波器进入测试实验室时,便知道他们肯定遇到了真正的麻烦。

    通常导致段错误的几个直接原因:

    • 解除引用一个包含非法值的指针。
    • 解除引用一个空指针 (常常由于从系统程序中返回空指针,并未经检查就使用)。
    • 在未得到正确的权限时进行访问,例如,试图往一个只读的文本段存储值就会引起段错误。
    • 用完了堆栈或堆空间 (虚拟内存虽然巨大但绝非无限)。

    下面这个说法可能过于简单,但在绝大多数架构的绝大多数情况下,总线错误意味着 CPU 对进程引用内存的一些做法不满,而段错误则是 MMU 对进程引用内存的一些情况发出抱怨。

    以发生频率为序,最终可能导致段错误的常见编程错误是:

    1. 坏指针值错误:在指针赋值之前就用它来引用内存,或者向库函数传送一个坏指针 (不要上当!如果调试器显示系统程序中出现了段错误,并不是因为系统程序引起了段错误,问题很可能还存在于自己的代码中)。第三种可能导致坏指针的原因是对指针进行释放之后再访问它的内容。可以修改 free 语句,在指针释放之后再将它置为空值。
      free(p); p = NULL;

    这样,如果在指针释放之后继续使用该指针,至少程序能在终止之前进行信息转储。

    1. 改写 (overwrite) 错误:越过数组边界写入数据,在动态分配的内存两端之外写入数据,或改写一些堆管理数据结构 (在动态分配的内存之前的区域写入数据就很容易发生这种情况)。
      p = malloc(256); p[-1] = 0; p[256] = 0;

    2. 指针释放引起的错误:释放同一个内存块两次,或释放一块未曾使用 malloc 分配的内存,或释放仍在使用中的内存,或释放一个无效的指针。一个极为常见的与释放内存有关的错误就是在 for(p = start; p; p = p-> next) 这样的循环中迭代一个链表,并在循环体内使用 free(p) 语句。这样,在下一次循环迭代时,程序就会对己经释放的指针进行解除引用操作,从而导致不可预料的结果。

    //============================================================================
    // Name        : main
    // Author      : Yongqiang Cheng
    // Version     : Version 1.0.0
    // Copyright   : Copyright (c) 2019 Yongqiang Cheng
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
    	printf("argc = %d\n", argc);
    
    	for (int idx = 0; idx < argc; ++idx)
    	{
    		printf("argv[%d] --> %s\n", idx, argv[idx]);
    	}
    
    	printf("argv[argc] = %p\n\n", (void*) argv[argc]);
    
    	int *pt = NULL;
    
    	free(pt);
    
    	printf("pt = %p\n", pt);
    
    	return 0;
    }
    
    
    argc = 1
    argv[0] --> /home/strong/eclipse-work/yongqiang_example/Debug/yongqiang_example
    argv[argc] = (nil)
    
    pt = (nil)
    
    

    在遍历链表时正确释放元素的方法是使用临时变量存储下一个元素的地址。这样就可以安全地在任何时候释放当前元素,不必担心在取下一个元素的地址时还要引用它,代码如下:

    	struct node *p, *start, *tmp;
    	for (p = start; p; p = tmp)
    	{
    		tmp = p->next;
    		free(p);
    	}
    

    3.1 程序空间是否足够?

    如果你的程序所需的内存超过了操作系统所能提供给它的数量,程序就会发出一条段错误信息并终止。可以用一种简单的方法把这种段错误与其他基于 Bug 的段错误区分开来。

    要弄清程序是否用完了堆栈,可以在 dbx 命令下运行该程序:

    % dbx a.out
    (dbx) catch SIGSEGV
    
    (dbx) run
    ...
    signal SEGV (segmentation violation) in <some_routine> at 0xeff57708
    (dbx) where
    
    如果现在可以看到调用链,那说明堆栈空间还没有用完。
    但是,如果看到像下面这样的东西:
    
    fetch at 0xeffe7a60 failed -- I/O error
    (dbx)
    

    那么,堆找很可能已经用完。上面这个十六进制数就是可以提取或映射的堆栈地址。
    你也可以尝试在 C-shell 中调整堆栈段的大小限制。

    limit stacksize 10
    

    你可以在 C-shell 中调整堆栈段和数据段的最大值。进程的总地址空间仍然受交换区大小的限制,可以用 swap -s 命令查看交换区的大小。

    当程序出现坏指针值时,什么样的结果都有可能发生。一种广被接受的说法是,如果你走运,指针将指向你的地址空间之外,这样第一次使用该指针时就会使程序进行信息转储后终止。如果你不走运,指针将指向你的地址空间之内,并损坏 (改写) 所指向的内存的任何信息。这将引起隐晦的 Bug,非常难以捕捉。

    展开全文
  • CAN总线错误处理与故障界定

    万次阅读 多人点赞 2018-04-21 17:57:13
    常听到一句话“汽车上都用CAN总线,那这个总线的稳定性应该是有所保障的”,而这种稳定性的保障,正是因为CAN总线直面了现场总线的复杂环境,做了相应的错误处理以及故障界定。 工业现场总线的应用环境,不可避免的...

        常听到一句话“汽车上都用CAN总线,那这个总线的稳定性应该是有所保障的”,而这种稳定性的保障,正是因为CAN总线直面了现场总线的复杂环境,做了相应的错误处理以及故障界定。

        工业现场总线的应用环境,不可避免的会有干扰在传输线上,虽然已经用差分信号传递数据,但是因为所有终端都是接到了一个CAN总线上,不可避免又会出现诸如发送消息碰撞,或者因为某个终端的性能下降等原因,影响整个总线的通信质量。CAN总线,定义了类似CSMA/CA来处理消息碰撞的问题,并通过ACK来保证报文发送成功并且实现了相关的错误处理以及故障界定策略,来保证总线上的稳定通信质量。

    1. 碰撞处理

        CSMA/CA指的是可对发送的数据进行实时侦听,进行冲突检测,并实现同一通信线路的多路访问的一种协议。

        CAN总线上消息传递的基本单位为,其由不同的位场构成。

        数据帧,由帧起始、仲裁场、控制场、数据场、CRC 场、应答场、帧结尾7个位场组成。帧的起始位由一位显性电平组成,下面的示意图将显性电平画为了低电平。

        

        防止碰撞的关键就在于仲裁场,其中包括识别符和远程发送请求位(RTR)。CAN控制器能实时的侦测到当前总线的状态,当两个CAN控制器同时发送报文的时候,CAN控制器会实时监测监测总线状态,当其中一个CAN控制器在仲裁域发现其发送的电平本来是隐性位,但是读上来的确实显性位的时候,就会发生仲裁失败,退出发送状态,转为接收状态。所以说,对于总线上的数据,识别符部分越小(高位连续低电平个数较多)的帧,会抢占识别符高的帧发送。

        ACK位前后都是隐性位,发送此报文的CAN控制器会尝试发送隐性位。如果有其余的CAN控制器能够通过CRC校验成功,就会在ACK位将总线置成显性位。这样发送报文的CAN控制器通过读取的ACK位为显性位就知道总线上有其余的CAN节点成功接收到了数据。

    2.错误处理

        作为CAN控制器,判断总线上发生了错误的依据,跟总线上的帧格式有着莫大的关系。我们将总线上正在发送报文的CAN控制器为发送器,其余的位接收器

        位错误:当接入总线的CAN控制器处于发送的阶段(发送报文已经仲裁成功),检测到总线上的位状态与发送的不相符,则发生位错误(ACK SLOT的隐性位除外)。

        填充错误:数据帧以及遥控帧,均通过位填充的方法编码。无论何时,发送器只要检测到位流里有5 个连续识别值的位,便自动在位流里插入一补码位。如果在通过NRZ编码过的帧部分,出现了连续相同的位电平,则产生填充错误。

        CRC错误:CRC 序列包括发送器的CRC 计算结果。接收器计算CRC 的方法与发送器相同。如果计算结果与接收到CRC 序列的结果不相符,则检测到一个CRC 错误(CRC ERROR)。

        形式错误:当一个固定形式的位场含有1 个或多个非法位,则检测到一个形式错误(FORM ERROR)。比如说帧结尾固定为隐性位,却检测到了显性位。

        应答错误:只要在ACK 间隙(ACK SLOT)期间所监视的位不为“显性”,则发送器会检测到一个应答错误

    (ACKNOWLEDGMENT ERROR)。

        当总线上的CAN控制器发生了这些错误,将会根据当前CAN控制器所处的状态做出相应的操作。

        根据设备的故障界定结果,设备可能会处于三种不同的状态:错误主动状态错误被动状态,以及总线关闭状态,三种状态表征设备当前的CAN总线状况按顺序逐渐严重。“错误主动”的单元可以正常地参与总线通讯并在错误被检测到时发出主动错误标志。“错误被动”的单元不允许发送主动错误标志。“错误被动”的单元参与总线通讯而且在错误被检测到时只发出被动错误标志。而且,发送以后,“错误被动”单元将在预设下一个发送之前处于等待状态。“总线关闭”的单元不允许在总线上有任何的影响(比如,关闭输出驱动器)。

        当CAN控制器检测到位错误,填充错误,形式错误或者应答错误,这个CAN控制器会即刻在下一位发出错误帧。错误帧由两个不同的场组成,第一个场是一根总线上挂载的所有CAN控制器提供的错误标志的叠加,第二个场是错误界定符。错误标志分为两种,一种是主动错误标志,由6个显性的位组成,由处于错误主动状态的CAN控制器发送。而作为处于错误被动状态的CAN控制器,发送的错误标志称为被动错误标志,由6个隐性位组成,因为发送的是隐性位,所以当处于被动错误的CAN控制器要发送错误帧的时候,只要检测到6个连续相同的极性位即算成功发送错误标志。

         数据帧以及遥控帧的帧起始、仲裁场、控制场、数据场以及CRC 序列,均通过位填充的方法编码。无论何时,发送器只要检测到位流里有5 个连续相同值的位,便自动在位流里插入一补充反向位。数据帧或远程帧(CRC 界定符、应答场和帧结尾)的剩余位场形式固定,不填充。错误帧和过载帧不进行编码。主动错误标志将破坏从帧起始到CRC 界定符的位填充规则,或者破坏了应答场或帧末尾场的固定格式。所以当一个处于错误主动状态的CAN控制器发送错误帧的时候,会引起所有其余处于错误主动状态的CAN控制器同时发送错误标志,因此,显性位叠加导致总线上会出现所有站的错误标志叠加到一起,但是因为在总线上出现错误帧之前的连续显性电平位数不确定,所以这个总长度最小为6位,最大为12位。

        错误界定符包括8 个“隐性”的位。错误标志传送了以后,每一站就发送“隐性”的位并一直监视总线直到检测出一个“隐性”的位为止。然后就开始发送7 位以上的“隐性”位。

        讲到这里就顺便讲一下过载帧。首先数据帧(或者远程帧)与前边的帧需要“隔离",这通过帧间空间来实现,帧间空间包括间歇场,挂起传送位场,以及总线空闲位场。间歇场由3个隐性位组成,而紧跟间歇场的挂起传送位场只有处于错误被动状态的CAN控制器会需要再连续监测总线3个隐性位,才能转到总线空闲状态。在总线空闲的状态上,监测到显性位理解为帧起始。过载帧格式跟由主动错误标志组成的错误帧一样,区别就在于其是在间歇场发出的,由接收器的内部条件决定(报文过载)决定的,过载标志的形式破坏了间歇场的固定形式。因此,所有其他的站都检测到一过载条件并与此同时发出过载标志。

        3.故障界定

        在每一总线单元里实现两种计数以便故障界定:
        • 发送错误计数

        • 接收错误计数

        这些计数按照固定的规则进行改变。

        接收错误增加/减少的方式包括:

        1.作为接收器,检测到了包括CRC错误等的错误,接收错误计数器加一(发送主动错误标志或过载标志时,如果发送器检测到位错误,则发送错误计数器值加八)。

        2.作为接收器,发送完错误错误标志之后如果检测到显性位,则接收错误计数器加八,而后如果还能连续检测到8位显性位,持续加八。

        3.如果接收计数器错误数值介于1和127之间,在成功接收到报文之后(直到应答间隙接收没有错误,及成功地发送了ACK 位),接收错误计数器值减1;如果大于127,则它会设置一个介于119 到127 之间值。如果接收错误计数器值是0,则它保持0;

        发送错误计数器增加/减少的方式包括:

        1.当发送器发送错误标志(检测到错误,或者接收器发送错误标志导致填充错误),发送错误计数器值加八。但是有两个例外,一个是发送器为错误被动,检测到的是应答错误,并且发送被动错误标志的时候检测不到一个错误,这个时候发送错误计数器不加八。另一种例外是发送器因为填充错误而发送错误标志(注:此填充错误发生于仲裁期间。引起填充错误是由于:填充

    位位于RTR 位之前,并已作为“隐性”发送,但是却被监视为“显性”),发送错误计数器同样不自增。

        2.在发送器发送主动错误标志或者过载标志的时候,如果发送器检测到位错误,则发送错误计数器值加8。在发送主动错误标志、被动错误标志或过载标志以后,每多检测到8位显性位,则发送错误计数器值持续加8。

        4.报文成功传送后(得到ACK 及直到帧末尾结束没有错误),发送错误计数器值减1,除非已经是0。

        CAN控制根据这个计数器切换错误主动状态,错误被动状态,以及总线关闭这三种状态,具体的切换关系图如下。

        

        这里多说一句题外话,BOSCH的原厂是描述的在总线监视到128 次出现11 个连续“隐性”位之后,“总线关闭”的节点可以变成“错误主动”不再是“总线关闭”),它的错误计数值也被设置为0。而这个功能在STM公司的芯片的CAN控制器实现上需要配置寄存器使能这个功能。

        BOSCH的原厂的协议说明有两条很重要注意。

        1.一个大约大于96 的错误计数值显示总线被严重干扰。最好能够预先采取措施测试这个条件。

        2.当节点启动之后,总线上只有1 个节点在线,以及如果这个节点发送一些报文,则将不会有应答,并检测到错误和重复报文。由此,节点会变为“错误被动”,而不是“总线关闭”。

    展开全文
  • 这个是醇酒大哥翻译的Sandisk manual v2.2 里面他校正了一些错误还加入了他自己的一些建议经验等。值得一看。
  • 现代汽车包含数十个ECU(电子控制装置)和无线连接设备,它们通过车内部总线紧密的互联。尽管这些电子组件增强了汽车的安全性和效率,同时也带来了新的漏洞。本论文揭露了车内网络中一种新的重要的漏洞。利用CAN总...
  • 总线关闭(bus off)是CAN节点比较重要的错误处理机制。那么,在总线关闭状态下,CAN节点的恢复流程是怎样的?又该如何理解节点恢复流程的“快恢复”和“慢恢复”机制?本文将为大家详细分析总线关闭及恢复的机制和...
  • 在发送和接收报文时,总线上的节点如果检测出了错误,那么该节点就会发送错误帧,通知总线上的节点,自己出错了。 错误帧由错误标志和错误界定符两个部分组成。 主动错误标志:6个连续的显性位 (0); 被动错误...
  • 总线概述及常见总线

    2016-09-27 09:16:49
    一. 总线概念 所谓总线(Bus),是指计算机设备和设备之间传输信息的公共数据通道。总线是连接计算机硬件系统内多种设备的通信线路,它的一个重要...微机中的总线分为数据总线、地址总线和控制总线3类。不同型号的C
  • AHB总线

    千次阅读 多人点赞 2020-12-17 22:12:24
    AHB总线一、 简介1.1 AHB总线的架构二、AHB总线(宏观构造)2.1.AHB总线组成2.2.AHB总线组成互连2.3.AHB操作概述2.4.AHB基本传输阶段三、AHB总线传输(时序)3.1.AHB信号描述(重要)3.2.基本AHB传输(重要)3.2.1零...
  • STM32单线串口对总线舵机的控制

    万次阅读 多人点赞 2017-03-07 16:19:30
    1 总线舵机的介绍 总线伺服舵机即串行总线智能舵机,实际上可以理解为数字舵机的衍生品,...这款TS-315是通过单线的串口通信旋转进行控制的,控制字符串协议如下: 字符串协议: #1P1500T100 控
  • 1.SPI总线简介 SPI(serial peripheral interface,串行外围设备接口)总线技术是Motorola公司推出的一种同步串行接口。它用于CPU与各种外围器件进行全双工、同步串行通讯。它只需四条线就可以完成MCU与各种外围...
  • platform总线

    千次阅读 2020-02-26 19:24:39
    相对于USB、PCI、I2C、SPI等物理总线来说,platform总线是一种虚拟、抽象出来的总线,实际中并不存在这样的总线。那为什么需要platform总线呢?其实是Linux设备驱动模型为了保持设备驱动的统一性而虚拟出来的总线。...
  • PCIe总线

    千次阅读 2018-09-29 11:06:56
    PCIe总线 与PCI总线不同,PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个设备互为是数据发送端和数据接收端。PCIe链路可以由多条Lane组成,目前PCIe链路×1、×2、×4、×8、×16...
  • 1.3 PCI总线的存储器读写总线事务

    千次阅读 2013-07-22 16:26:57
    总线的基本任务是实现数据传送,将一组数据从一个设备传送到另一个设备,当然总线也可以将一个设备的数据广播到多个设备。在处理器系统中,这些数据传送都要依赖一定的规则,PCI总线并不例外。 PCI总线使用单端并行...
  • 总线概述及常见总线(转)

    万次阅读 2019-01-14 10:31:08
    总线是连接计算机硬件系统内多种设备的通信线路,它的一个重要特征是由总线上的所有设备共享,可以将计算机系统内的多种设备连接到总线上。如果是某两个设备或设备之间专用的信号连线,就不能称之为总线。系统总线...
  • AMBA总线(二) AHB总线

    千次阅读 2019-12-21 21:05:31
    总线传输:AHB 总线传输是数据目标的读写操作,可能会持续一个或者多个总线周期,而总线的传输在收到从机的ready信号终止,总线位宽为8、16、32、64、128bits。 猝发传输:定义了一个或多个数据传输,由主线总机发起...
  • UART总线

    千次阅读 2018-03-05 17:52:04
    定义: UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它...
  • 【Avalon总线】1.Avalon总线总体介绍

    千次阅读 2017-11-21 21:09:18
    文章中如有错误请指出,谢谢! 1 Avalon总线总体介绍 Avalon总线提供了FPGA内部各种组件(Components)的接口,包括高速流传输设备(High Speed Streaming Application)和内存映射设备(Memory-Map
  • LIN 总线开发知识总结

    万次阅读 多人点赞 2018-01-23 18:42:45
    做为一个CAN总线作为低成本辅助总线,LIN总线在车身控制中应用广泛,车门、车窗、车灯以及中控锁等都使用LIN线。其实对于不计成本新能源造车来说,完全可以使用CAN线更简单统一的实现这些功能,但限于汽车里零
  • 现场总线作为工业自动化系统中最后一段通讯的桥梁,越来越多的传感器和执行机构都集成了CAN总线之类的通讯接口,但其固化的几个通讯数据格式,面对当前众多复杂的大系统,时常会给设计者带来底层数据冲突的困扰,...
  • 通信总线-现场总线-CAN

    千次阅读 2019-09-25 10:48:10
    摘要:博主在网上搜寻了大量关于CAN总线的博客,发现没有一篇能像这篇博客一样层次分明、脉络清晰,而且知识点面面俱到。这里向JawSoW表示感谢,感谢他花费...该文章FD-CAN的描述不是很多,我会在文章最后进行补充。
  • 安川伺服驱动器第二代现场总线MECHATROLINK-Ⅱ的用户手册,描述MECHATROLINK-Ⅱ的系统结构,通信协议,错误检测,数据定义以及指令描述

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,951
精华内容 16,780
关键字:

对总线的描述错误的是