bcm617xx_GPIO模拟SPI_mcp2515

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

成功收到
<0x00000001> [8] 11 22 33 44 55 66 77 88
<0x00000001> [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

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

发布了1 篇原创文章 · 获赞 1 · 访问量 74

猜你喜欢

转载自blog.csdn.net/weixin_43020518/article/details/104556416
今日推荐