mcp2518驱动调试

mcp2518驱动调试_第1张图片

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

 

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)

mcp2518驱动调试_第2张图片

一次可以读写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

mcp2518驱动调试_第3张图片

#define cREGADDR_CiINT      0x01C

#define cREGADDR_CiINTFLAG      cREGADDR_CiINT

中断寄存器

 

 

mcp2518驱动调试_第4张图片

 

mcp2518驱动调试_第5张图片

 

       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;

 

 

mcp2518驱动调试_第6张图片

       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大写才会编译设备树

你可能感兴趣的:(mcp2518驱动调试)