bcm617xx_GPIO模拟SPI_mcp2515

Ora ·
更新时间:2024-09-20
· 704 次阅读

2020.02.21,第一个任务:基于bcm617xx调通mcp2515实现SPI转CAN(未结束)
纪念第一次调Linux内核驱动
上步骤!
1.在kernel_3.0.1_bcm\arch\mips\bcm617xx\cpuh下的platform.c文件中加入4个结构体,分别是spi_gpio_platform_data、mcp251x_platform_data、spi_board_info、platform_device。
1.1 spi_gpio_platform_data中填入硬件电路图中SPI连接的GPIO引脚号。

static struct spi_gpio_platform_data spigpio_platform_data = { .sck = 9, .mosi = 10, .miso = 12, .num_chipselect = 11, };

1.2 mcp251x_platform_data中填入硬件电路图上mcp2515连接的晶振频率,以及采用下降沿触发的方式。

static struct mcp251x_platform_data mcp251x_info = { .oscillator_frequency = 25 * 1000 * 1000, .irq_flags = IRQF_TRIGGER_FALLING, //.board_specific_setup = &mcp251x_setup, //.power_enable = mcp251x_power_enable, //.transceiver_enable = NULL, };

1.3 spi_board_info中需要填入设备模块的名字、SPI最大速率、总线编号、片选、SPI模式以及平台数据(platform_data)还有中断号。模块名称"mcp2515",这将与mcp251x.c里面的devicename对应,否则无法注册;由于mcp2515是挂在spi下,所以platform_data应该填入1.2中的数据,中断采用的是外部中断。

static struct spi_board_info bcm617xx_spi_baord_info[] __initdata = { { .modalias = "mcp2515", .max_speed_hz = 1*1000*1000, .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_0, .platform_data = &mcp251x_info, //.irq = CELIVERO_CPUH_GPIO, .irq = CELIVERO_CPUH_IRQ_EXT0, }, };

1.4 platform_device中填入name、id、dev。由于使用GPIO模拟SPI,所以name填"spi_gpio",这个名字与spi_gpio.c中的drivername对应,否则无法注册。

static struct platform_device bcm617xx_spi_gpio = { .name = "spi_gpio", .id = 0, .dev = { .platform_data = &spigpio_platform_data, }, };

2.内核注册spi_gpio,在\kernel_3.0.1_bcm\drivers\spi下spi_gpio.c中修改引脚号,并配置IO口的模式和方向。注:这里面的drivername为spi_gpio,与1.4中的name需相同。
2.1 修改引脚宏定义

#define GPIO_PIN_MISO (12) #define GPIO_PIN_SCK (9) #define GPIO_PIN_MOSI (10) #define GPIO_PIN_CS (11)

2.2 根据手册,配置引脚

/* reg address */ #define PM_MUX_ADDR_BASE (0x1EC02400) #define PM_MUX_ADDR_MAXSIZE (0x100) #define GPIO_ADDR_BASE (0x1EC01400) #define GPIO_ADDR_MAXSIZE (0x100) #define GPIO_SWPORTB_DR (0x0C) #define GPIO_SWPORTB_DDR (0x10) #define GPIO_EXT_PORTB (0x54) static void __iomem *pmmux_address_base = NULL; static void __iomem *gpio_address_base = NULL; pmmux_address_base = ioremap(PM_MUX_ADDR_BASE, PM_MUX_ADDR_MAXSIZE); if (pmmux_address_base == NULL) { PRINT_ERROR("ioremap failed!\n"); goto out_ioremap; } gpio_address_base = ioremap(GPIO_ADDR_BASE, GPIO_ADDR_MAXSIZE); if (gpio_address_base == NULL) { PRINT_ERROR("ioremap failed!\n"); goto out_ioremap; } /* PM_MUX_CTRL_REGS_PIN_MUX_CTRL_19 */ reg = ioread32(pmmux_address_base + 0x8C); reg &= ~(0xF << 16); //GPIOH_12 reg &= ~(0xF << 12); //GPIOH_11 reg &= ~(0xF << 8); //GPIOH_10 reg &= ~(0xF << 4); //GPIOH_9 iowrite32(reg, pmmux_address_base + 0x8C); /* PM_MUX_CTRL_REGS_PIN_MUX_PAD_CTRL_11 */ reg = ioread32(pmmux_address_base + 0xc4); reg &= ~(0xC << 4); reg |= (0x4 << 4); // GPIOH_11 set PULL_UP iowrite32(reg, pmmux_address_base + 0xc4); printk("%s, %d: GPIOH_11 set PULL_UP\n\n", __FILE__, __LINE__); /* PM_MUX_CTRL_REGS_PIN_MUX_PAD_CTRL_21 */ reg = ioread32(pmmux_address_base + 0x94); reg &= ~(0xf); reg |= (0x0); // EXT_IRQH_0 iowrite32(reg, pmmux_address_base + 0x94); /* set GPIO direction */ reg = ioread32(gpio_address_base + GPIO_SWPORTB_DDR); reg &= ~(0x1 << GPIO_PIN_MISO); // input reg |= (0x1 << GPIO_PIN_MOSI); // output reg |= (0x1 << GPIO_PIN_SCK); // output reg |= (0x1 << GPIO_PIN_CS); // output iowrite32(reg, gpio_address_base + GPIO_SWPORTB_DDR); reg = ioread32(gpio_address_base + GPIO_SWPORTB_DR); reg |= (0x1 << GPIO_PIN_CS); // CS = 1 iowrite32(reg, gpio_address_base + GPIO_SWPORTB_DR);

3.内核提供mcp251x的驱动,所以在kernel_3.0.1_bcm\drivers\net\can底下注册mcp2515即可。
3.1 修改宏定义devicename,这里使用的是mcp2515。注:这里的drivername应与1.3中的modalias相同。

#define DEVICE_NAME "mcp2515"

4.修改完代码,现在需要在menuconfig中开启相关功能。
4.1 开启spi_gpio

Device Drivers ---> [*] SPI support ---> -*- Utilities for Bitbanging SPI masters GPIO-based bitbanging SPI Master User mode SPI device driver support

4.2 开启mcp2515

[*] Networking support ---> CAN bus subsystem support ---> Raw CAN Protocol (raw access with CAN-ID filtering) Broadcast Manager CAN Protocol (with content filtering) Platform CAN drivers with Netlink support [*] CAN bit-timing calculation Microchip MCP251x SPI CAN controllers

5.编译后将镜像文件烧入板子,应该可以看到spi_gpio和mcp2515注册成功。

6.使用SocketCAN测试是否可用
6.1 下载
6.1.1 canutils的最新源码http://www.pengutronix.de/software/socket-can/download/canutils,最新的为4.0.6。
6.1.2 canutils编译需要libsocketcan库,http://www.pengutronix.de/software/libsocketcan/download/,我下载的是0.0.11。
6.2 编译
6.2.1编译libsocketcan

./configure --host=mipsel-unknown-linux CC=mipsel-unknown-linux-gnu-gcc --prefix=/home/SocketCan/libsocketcan make make install

6.2.2 编译canutils

./configure CC=mipsel-unknown-linux-gnu-gcc --host=mipsel-unknown-linux --build=i386-linux libsocketcan_LIBS=-lsocketcan LDFLAGS=-L/home/SocketCan/libsocketcan/lib libsocketcan_CFLAGS=-I/home/SocketCan/libsocketcan/include CFLAGS=-I/home/SocketCan/libsocketcan/include --prefix=/home/SocketCan/canutils make make install

7.将lib、bin啥的拷入板子对应目录,该软链接的软链接。

8.回环测试
8.1 配置波特率、回环模式

ifconfig can0 down canconfig can0 bitrate 500000 canconfig can0 ctrlmode loopback on triple-sampling off ifconfig can0 up

8.2 开始测试!

candump can0 & cansend can0 -e 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88

成功收到
[8] 11 22 33 44 55 66 77 88
[8] 11 22 33 44 55 66 77 88

至于为啥收到了两帧,还不懂问题出在哪里。

9.两块板子对接测试
注:配置前需要先执行ifconfig can0 down!
两块块板子配置

ifconfig can0 down canconfig can0 ctrlmode loopback off triple-sampling on ifconfig can0 up candump can0 & cansend can0 -e 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88

奇了怪了,就是收不到数据!!!硬件也检查了,软件也检查了,回环可以,但是实际使用却不行,真不知道为啥!仍然在查!


作者:小灰yzh



spi gpio xx

需要 登录 后方可回复, 如果你还没有账号请 注册新账号