mcp2518驱动调试

只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效

The SPI in the microcontroller must be configured in mode (0,0) or (1,1) in 8-bit operating mode

Spi-imx.c

spi_imx 30830000.ecspi: mode_bits = 71(0x47),0100 0111, mode 3 , SPI_CS_HIGH, SPI_NO_CS

#define   SPI_CPHA      0x01                     /* clock phase */

#define   SPI_CPOL      0x02                     /* clock polarity */

#define   SPI_MODE_0  (0|0)               /* (original MicroWire) */

#define   SPI_MODE_1  (0|SPI_CPHA)

#define   SPI_MODE_2  (SPI_CPOL|0)

#define   SPI_MODE_3  (SPI_CPOL|SPI_CPHA)

#define   SPI_CS_HIGH 0x04                     /* chipselect active high? */

#define   SPI_LSB_FIRST       0x08                     /* per-word bits-on-wire */

#define   SPI_3WIRE      0x10                     /* SI/SO signals shared */

#define   SPI_LOOP      0x20                     /* loopback mode */

#define   SPI_NO_CS    0x40                     /* 1 dev/bus, no chipselect */

#define   SPI_READY     0x80                     /* slave pulls low to pause */

#define   SPI_TX_DUAL 0x100                    /* transmit with 2 wires */

#define   SPI_TX_QUAD 0x200                    /* transmit with 4 wires */

#define   SPI_RX_DUAL 0x400                    /* receive with 2 wires */

#define   SPI_RX_QUAD       0x800                    /* receive with 4 wires */

修改时钟频率

Dts:

clocks = <&mcp251x_clock>;

dtsi:

       clocks {

              #address-cells = <1>;

              #size-cells = <0>;

              mcp251x_clock: mcp251x_clock {

                     compatible = "fixed-clock";

                     reg = <1>;

                     #clock-cells = <0>;

                     clock-frequency = <20000000>;

                     clock-output-names = "mcp251x_clock";

            };

       …….

       ……

}

传输规则

spi_tx_buf[0] = 4bit(cmd)+ 4bit(reg地址的高4位)

spi_tx_buf[1] = 8bit(reg地址的低8为)

要使能片选脚

cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;

DRV_CANFDSPI_RamInit

给mcp2518的ram初始化,长度2048

1=2字节(1 word = 2 byte) 
1字节=8(1 byte = 8bit)

一次可以读写4个字节的整数倍,每个字节后地址会自动加一,地址从0x400到0xbff

随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。

#define SPI_DEFAULT_BUFFER_LENGTH      

改为8,kernel起不来

改为64 ,96

[    1.391649] imx-sdma 30bd0000.dma-controller: sdma firmware not ready!

[    1.398187] spi_bitbang_transfer_one : 290 status = -22

[    1.403510] mcp251x spi1.0: SPI transfer failed: -22

[    1.408495] spi_master spi1: failed to transfer one message from queue

[    1.415034] mcp251x spi1.0: spi transfer failed: ret = -22

[    1.420530] mcp251x spi1.0: 0: DRV_CANFDSPI_RamInit error

内核报错

spi-bitbang.c:      master->transfer_one = spi_bitbang_transfer_one;

关掉DRV_CANFDSPI_RamInit就没有imx-sdma 30bd0000.dma-controller: sdma firmware not ready!

这个意思没有加载sdma的固件

可是有log

[    5.685641] imx-sdma 30bd0000.dma-controller: loaded firmware 4.4

而且在

./lib/firmware/imx/sdma/sdma-imx7d.bin

./lib/firmware/imx/sdma/sdma-imx6q.bin

都是有固件存在的

说明是加载了,但加载时间比较后面,我们在使用驱动的时候并没有加载到这个固件

只要让mcp251x.c改为用以模块的形式加载就没有问题了,这样加载时间会比较后面。

          pinctrl-names = "default";

              pinctrl-0 = <&pinctrl_mcp2518_irq>;

interrupt-parent = <&gpio5>;

interrupts = <8 2>;

gpio5_8 代表io口号,2代表中断类型

dt-bindings/interrupt-controller/irq.h下定义

中断类型如下

#define IRQ_TYPE_NONE           0

#define IRQ_TYPE_EDGE_RISING 1

#define IRQ_TYPE_EDGE_FALLING    2

#define IRQ_TYPE_EDGE_BOTH  (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)

#define IRQ_TYPE_LEVEL_HIGH  4

#define IRQ_TYPE_LEVEL_LOW  8

中断脚的定义必须放在从设备的设备树当中?待确认

interrupt-parent

interrupts

设备树中加入这两个参数,驱动会自动生成中断号,应该在某处申请的,带研究

利用中断函数,去检测中断类型,去操作相应寄存器

P25 3-14

#define cREGADDR_CiINT      0x01C

#define cREGADDR_CiINTFLAG      cREGADDR_CiINT

中断寄存器

       con_reqop = FIELD_PREP(MCP25XXFD_CAN_CON_REQOP_MASK, mode_req);

       err = regmap_update_bits(priv->map, MCP25XXFD_CAN_CON,

                             MCP25XXFD_CAN_CON_REQOP_MASK, con_reqop);

Mode_req来至mcp25xxfd_get_normal_mode

rx-offload.c rx-offload.h:

can_rx_offload_add_manual

Bitfield.h:

#define FIELD_PREP(_mask, _val)                  

ip link set can0 down

ip link set can0 type can bitrate 250000 loopback on/off

ip link set can0 up

candump can0 &

 cansend can0 -s 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88

0x19FA044A 0x22 0x00 0xF0 0xFF 0xFF 0xFF 0xFF 0xFF

~/can-utils/canutils/4.0.6-r0/

编译candump

aarch64-poky-linux-gcc  --sysroot=/opt/fsl-imx-wayland/4.14-sumo/sysroots/aarch64-poky-linux -DHAVE_CONFIG_H -I. -I../include  -I../include -I../include -DPF_CAN=29 -DAF_CAN=PF_CAN    -O2 -pipe -g -feliminate-unused-debug-types  -Wall -g -O2 -MT candump.o -MD -MP -MF .deps/candump.Tpo -c -o candump.o candump.c

aarch64-linux-gnu-gcc -I./ -o candump candump.c

snprintf返回传输大小

server从CAN总线上接收数据,client将数据发到CAN总线上,当CAN总线上有数据时,server才能接收数据,当CAN总线空闲时,client才能将数据发送出去

net/can/raw.c

raw_recvmsg()是应用层read的接口函数,调用了没有数据会停着

net/can/af_can.c:

当有数据时才会调用canfd_rcv()

struct canfd_frame *cfd = (struct canfd_frame *)skb->data;

       regmap_write(priv->map, MCP25XXFD_IOCON, val);

       regmap_read(priv->map, MCP25XXFD_IOCON, ret);

       if (new_state == CAN_STATE_BUS_OFF) {

              mcp25xxfd_chip_stop(priv, CAN_STATE_BUS_OFF);

              can_bus_off(priv->ndev);

       }

err = regmap_read(priv->map, MCP25XXFD_CAN_TREC, &trec);

REGISTER 3-20: CiTREC – TRANSMIT/RECEIVE ERROR COUNT REGISTER

Yocto 编译

drivers/net/can/spi/mcp25xxfd/mcp25xxfd-core.o: In function `mcp25xxfd_probe':

| mcp25xxfd-core.c:(.text+0x1dbc): undefined reference to `can_rx_offload_add_manual'

| mcp25xxfd-core.c:(.text+0x1dbc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `can_rx_offload_add_manual'

解决:rm work/imx8mmevk-poky-linux/linux-imx/4.14.98-r0/build/drivers/net/can/rx-offload.o

Dtb没有编译出来

Bitbake –C compile linux-imx

参数-C 中C大写才会编译设备树

在bus-off后,can会在500ms后restart,这时候can的模式会从MCP25XXFD_CAN_CON_MODE_CONFIG(4)切到MCP25XXFD_CAN_CON_MODE_CAN2_0(6)

代码:

con_reqop = FIELD_PREP(MCP25XXFD_CAN_CON_REQOP_MASK, mode_req);

err = regmap_update_bits(priv->map, MCP25XXFD_CAN_CON,

 MCP25XXFD_CAN_CON_REQOP_MASK, con_reqop);

这个过程中可能出现数据发送,网络数据发送调用ndo_start_xmit这个接口函数

static const struct net_device_ops mcp25xxfd_netdev_ops = {

.ndo_open = mcp25xxfd_open,

.ndo_stop = mcp25xxfd_stop,

.ndo_start_xmit = mcp25xxfd_start_xmit,

.ndo_change_mtu = can_change_mtu,

};

这个时候

这个地方就会导致内核挂掉

解决在can开始restart时会有rx,tx的缓存初始化操作 

 

在这个初始化时,调用netif_stop_queue把tx队列置为off状态,使得暂时不能发送数据

在restart结束后,调用netif_start_queue把tx队列off位清除

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值