瑞芯微Rockchip开发者社区
直播中

杨勇

7年用户 1173经验值
私信 关注
[问答]

MCP2515是什么?MCP2515协议控制器有哪些功能呢

MCP2515是什么?MCP2515协议控制器有哪些功能呢?

回帖(1)

谢芳芳

2022-3-7 16:29:49
【RK3399】【Linux】Rockchip3399 Can驱动分析 mcp2515

MCP2515介绍

Microchip 的MCP2515 是一款独立控制器局域网络(Controller Area Network, CAN)协议控制器,完全支持CAN V2.0B 技术规范。该器件能发送和接收标准和扩展数据帧以及远程帧。MCP2515 自带的两个验收屏蔽寄存器和六个验收滤波寄存器可以过滤掉不想要的报文,因此减少了主单片机(MCU)的开销。MCP2515与MCU 的连接是通过业界标准串行外设接口(Serial Peripheral Interface, SPI)来实现的。

SPI协议模块:



TXCAN:连接到CAN总线的发送输出引脚

RXCAN:连接到CAN总线的接收输入引脚

CLKOUT:带可编程预分频器的时钟输出引脚

mcp251x.c驱动分析

在驱动的probe函数中mcp251x_can_probe进行spi资源的获取,设备的注册

1035     const struct of_device_id *of_id = of_match_device(mcp251x_of_match,
1036                                &spi->dev);
1037     struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);
1038     struct net_device *net;
1039     struct mcp251x_priv *priv;
1040     struct clk *clk;
1041     int freq, ret;
1042
1043     clk = devm_clk_get(&spi->dev, NULL);
1044     if (IS_ERR(clk)) {
1045         if (pdata)
1046             freq = pdata->oscillator_frequency;
1047         else
1048             return PTR_ERR(clk);
1049     } else {
1050         freq = clk_get_rate(clk);
1051     }
1052
1053     /* Sanity check */
1054     if (freq < 1000000 || freq > 25000000)
1055         return -ERANGE;

1035:从设备树中获取spi设备资源

1043~1051:获取设备树中设定的时钟

1057     /* Allocate can/net device */
1058     net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
1059     if (!net)
1060         return -ENOMEM;
1061
1062     if (!IS_ERR(clk)) {
1063         ret = clk_prepare_enable(clk);
1064         if (ret)
1065             goto out_free;
1066     }
分配can/net设备

struct mcp251x_priv结构如下:

244 struct mcp251x_priv {
245     struct can_priv    can;
246     struct net_device *net;
247     struct spi_device *spi;
248     enum mcp251x_model model;
249
250     struct mutex mcp_lock; /* SPI device lock */
251
252     u8 *spi_tx_buf;
253     u8 *spi_rx_buf;
254     dma_addr_t spi_tx_dma;
255     dma_addr_t spi_rx_dma;
256
257     struct sk_buff *tx_skb;
258     int tx_len;
259
260     struct workqueue_struct *wq;
261     struct work_struct tx_work;
262     struct work_struct restart_work;
263
264     int force_quit;
265     int after_suspend;
266 #define AFTER_SUSPEND_UP 1
267 #define AFTER_SUSPEND_DOWN 2
268 #define AFTER_SUSPEND_POWER 4
269 #define AFTER_SUSPEND_RESTART 8
270     int restart_tx;
271     struct regulator *power;
272     struct regulator *transceiver;
273     struct clk *clk;
274 };

对上述结构体进行赋值,并写入到spi驱动中

1068     net->netdev_ops = &mcp251x_netdev_ops;
1069     net->flags |= IFF_ECHO;
1070
1071     priv = netdev_priv(net);
1072     priv->can.bittiming_const = &mcp251x_bittiming_const;
1073     priv->can.do_set_mode = mcp251x_do_set_mode;
1074     priv->can.clock.freq = freq / 2;
1075     priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
1076         CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
1077     if (of_id)
1078         priv->model = (enum mcp251x_model)of_id->data;
1079     else
1080         priv->model = spi_get_device_id(spi)->driver_data;
1081     priv->net = net;
1082     priv->clk = clk;
1083
1084     spi_set_drvdata(spi, priv);
1068     net->netdev_ops = &mcp251x_netdev_ops;对Can操作函数进行赋值

mcp251x_netdev_ops:

992 static const struct net_device_ops mcp251x_netdev_ops = {
993     .ndo_open = mcp251x_open,
994     .ndo_stop = mcp251x_stop,
995     .ndo_start_xmit = mcp251x_hard_start_xmit,
996     .ndo_change_mtu = can_change_mtu,
997 };
1071     priv = netdev_priv(net);访问net_device网络设备的私有数据

1072     priv->can.bittiming_const = &mcp251x_bittiming_const;设置can设备的时序参数

220 #define DEVICE_NAME "mcp251x"


226 static const struct can_bittiming_const mcp251x_bittiming_const = {
227     .name = DEVICE_NAME,
228     .tseg1_min = 3,
229     .tseg1_max = 16,
230     .tseg2_min = 2,
231     .tseg2_max = 8,
232     .sjw_max = 4,
233     .brp_min = 1,
234     .brp_max = 64,
235     .brp_inc = 1,
236 };

can_bittiming_const定义如下

46 struct can_bittiming_const {
47     char name[16];      /* Name of the CAN controller hardware */
48     __u32 tseg1_min;    /* Time segement 1 = prop_seg + phase_seg1 */
49     __u32 tseg1_max;
50     __u32 tseg2_min;    /* Time segement 2 = phase_seg2 */
51     __u32 tseg2_max;
52     __u32 sjw_max;      /* Synchronisation jump width */
53     __u32 brp_min;      /* Bit-rate prescaler */
54     __u32 brp_max;
55     __u32 brp_inc;
56 };

CAN位时间
CAN 总线上的所有器件都必须使用相同的比特率。然而,并非所有器件都要求具有相同的主振荡器时钟频率。对于采用不同时钟频率的器件,应通过适当设置波特率预分频比以及每一时间段中的时间份额的数量来对比特率进行调整。CAN 位时间由互不重叠的时间段组成。 每个时间段又由时间份额 (TQ)组成,在 CAN 规范中,标称比特率 (NominalBit Rate, NBR)定义为在不需要再同步的情况下,理想发送器每秒发送的位数,它可用下面的公式来表示:





  • 标称位时间


标称位时间 (Nominal Bit Time, NBT)(tbit)由互不重叠的段时间段组成(图 5-1) 。因此 NBT 为下列时间段之和:



与 NBT 相关的参数是采样点、同步跳转宽度(Synchronization Jump Width, SJW)和信息处理时间(Information Processing Time, IPT)



  • 同步段        
  • 同步段 (SyncSeg)为 NBT 中的首段,用于同步 CAN总线上的各个节点。输入信号的跳变沿就发生在同步段,该段持续时间为 1 TQ。






  • 传播段(PropSeg)用于补偿各节点之间的物理传输延迟时间。传输延迟时
  • 间为信号在总线上传播时间的两倍,包括总线驱动器延迟时间。传播段的长度可编程设定为 1 – 8 TQ。
  • 相位缓冲段 1 (PS1)和相位缓冲段 2 (PS2)两个相位缓冲段 PS1 和 PS2 用于补偿总线上的边沿相位误差。通过再同步,可以延长 PS1 (或缩短 PS2) 。PS1 可编程设定为 1–8 TQ, 而 PS2 可编程设定为 2–8 TQ。
  • 采样点  
  • 采样点是位时间内的一个时间点。在该时间点,读取总线电平并进行分析。采样点位于相位缓冲段 PS1 的终点。但当采样模式设置为每位采样 3 次时例外。这种情况下,在 PS1 的终点仍然对某一位进行采样时,前两次的采样时间间隔为TQ/2,而该位的值将根据三个采样值中至少两次采样的相同值决定。
  • 信息处理时间        
  • 信息处理时间 (IPT)是确定采样点的位电平值所需要的时间。 IPT 从采样点开始,以 TQ 计量, MicrochipCAN 模块将该时间长度定义为 2 TQ。 PS2 同样开始于采样点,且为位时间的最后一个时间段,因此 PS2 的最小值不能小于 IPT
  • 同步跳转宽度        
  • 同步跳转宽度(SJW)可通过编程设定为 1 – 4 TQ,它可对位时钟进行必要的调整来保持与发送报文同步。
  • 时间份额        
  • 组成位时间的每个段都由时间份额 (TQ)组成。每个时间份额的长度取决于振荡器周期 (tOSC)。通常 TQ为两个振荡器周期。图 5-2 显示了如何从 TOSC 和 TQ推导出位周期。 TQ 的长度等于一个 TQ 时钟周期(tBRPCLK),利用称为波特率预分频器(BRP)的可编程预分频器对它进行编程设置。以下公式对此进行了阐
    述:




举报

更多回帖

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