分类: LINUX
2013-06-18 09:59:08
MCP2515是一种独立的CAN总线通信控制器,是Microchip公司首批独立CAN解决方案的升级器件,其传输能力较Microchip公司原有CAN控制器(MCP2510)高两倍,最高通信速率可达到1Mbps。MCP2515能够接收和发送标准数据帧和扩展数据帧以及远程帧,通过两个接收屏蔽寄存器和六个接收过滤寄存器滤除无关报文,从而减轻CPU负担。
MCP2515主要功能参数及电气特性如下:
(1)支持CAN技术规范2.0A/B, 最高传输速率达到1Mbps;
(2)支持标准数据帧、扩展数据帧和远程帧,每帧数据域长度可为0~8个字节;
(3)内含两个的接收缓冲器和三个发送缓冲器,并且可编程设定优先级;
(4)内含六个29位(bit)的接收过滤寄存器和两个29位(bit)的接收屏蔽寄存器;
(5)高速SPI接口,支持SPI 0,0和1,1模式;
(6)一次性模式可确保报文被一次性传输;
(7)具有可编程时钟脉冲输出引脚,可作为其他芯片时钟信号源;
(8) 帧起始(SOF)信号输出功能可被用于在确定的系统中(如时间触发CAN-TTCAN)执行时隙功能,或在CAN总线诊断中决定早期总线出级;
(9) 采用低功耗CMOS技术,工作电压:2.7V~5.5V, 工作电流:5mA(待机状态1μA);
(10)工作温度范围:(I)-40℃到+85℃,(E)-40℃到+125℃。
硬件连接方式
模块的CS、SO、SI、SCK分别与s3c6410的SPI(本文用的是SPI0)总线的CS、MISO、MOSI、SCK相连
模块的INT连接到s3c6410的中断管脚(本文使用的是GPN3)
驱动实现
1、修改 arch/arm/mach-s3c64xx/mach-smdk6410.c
增加头文件:
#include
#include
#include
#include
增加下列函数
static void cs_set_level(unsigned line_id, int lvl) {
gpio_direction_output(line_id, lvl);
};
static struct s3c64xx_spi_csinfo s3c64xx_spi0_csinfo = {
.fb_delay=0x3,
.line=S3C64XX_GPC(3),
.set_level=cs_set_level,
};
static struct mcp251x_platform_data mcp251x_info = {
.oscillator_frequency = 2 * 8000000,
};
static struct spi_board_info spi_devs[] = {
{
.modalias = "mcp2515",
.bus_num= 0,
.chip_select= 0,
.irq = IRQ_EINT(3),
.max_speed_hz= 1 * 1000 * 1000,
.mode=SPI_MODE_0,
.platform_data = &mcp251x_info,
.controller_data=&s3c64xx_spi0_csinfo,
},
};
在smdk6410_devices中增加SPI0总线驱动
static struct platform_device *hwgw6410_devices[] __initdata = {
&s3c_device_hsmmc0,
&s3c_device_ohci,
&s3c_device_usb_hsotg,
&samsung_asoc_dma,
&s3c_device_nand,
&s3c_device_i2c0,
&s3c64xx_device_spi0, //新增
&hwgw6410_leds_device,
&s3c_device_rtc,
&s3c_device_wdt,
/* &s3c_device_hwmon, */
&hwgw6410_device_eth,
&key_device,
};
在static void __init hwgw6410_machine_init(void)中增加以下代码
static void __init hwgw6410_machine_init(void)
{
u32 cs1;
s3c_nand_set_platdata(&hwgw6410_nand_info);
s3c_i2c0_set_platdata(NULL);
s3c_sdhci0_set_platdata(&hwgw6410_hsmmc0_pdata);
/* configure nCS1 width to 16 bits */
cs1 = __raw_readl(S3C64XX_SROM_BW) &
~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
(0 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
(1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
S3C64XX_SROM_BW__NCS1__SHIFT;
__raw_writel(cs1, S3C64XX_SROM_BW);
__raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
(6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
(4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
(1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
(13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
(4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
(0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
s3c64xx_spi_set_info(0,0,2); //新增
spi_register_board_info(spi_devs, ARRAY_SIZE(spi_devs)); //新增
otg_phy_init();
platform_add_devices(hwgw6410_devices, ARRAY_SIZE(hwgw6410_devices));
}
2、在编译内核时增加MCP2515的驱动选项
[*]Networking support->
<*>CAN bus subsystem support->
<*>Raw CAN Protocal
<*>Broadcast Manage CAN Protocal
CAN Device Drivers->
<*>Platform CAN driver with Netlink support
[*]CAN bit-timing calculation
<*>Microchip MCP251x SPI CAN controllers
Device drivers->
[*]SPI support ->
<*> Samsung S3C2416 series type SPI
至此,驱动移植完成,编译好内核后烧写到开发板,启动开发板后使用ifconfig -a 命令就可以看到一个can0 接口
移植过程中遇到的问题及解决办法
1、在内核启动的过程中出现以下警告信息:
0.080000] ------------[ cut here ]------------
[ 0.080000] WARNING: at drivers/gpio/gpiolib.c:101 gpio_ensure_requested+0x4c/0x100()
[ 0.080000] autorequest GPIO-20
[ 0.080000] Modules linked in:
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] [
[ 0.080000] ---[ end trace 1b75b31a2719ed1c ]---
这是因为SPI的片选管脚在使用前没有申请造成的,在 arch/arm/mach-s3c64xx/mach-smdk6410.c 中的 static void __init hwgw6410_machine_init(void)中增加以下代码
static void __init hwgw6410_machine_init(void)
{
u32 cs1;
s3c_nand_set_platdata(&hwgw6410_nand_info);
s3c_i2c0_set_platdata(NULL);
s3c_sdhci0_set_platdata(&hwgw6410_hsmmc0_pdata);
/* configure nCS1 width to 16 bits */
cs1 = __raw_readl(S3C64XX_SROM_BW) &
~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
(0 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
(1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
S3C64XX_SROM_BW__NCS1__SHIFT;
__raw_writel(cs1, S3C64XX_SROM_BW);
__raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
(6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
(4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
(1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
(13 << S3C64XX_SROM_BCX__TACC__SHIFT) |
(4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
(0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
gpio_request(s3c64xx_spi0_csinfo.line, NULL); //新增
s3c64xx_spi_set_info(0,0,2);
spi_register_board_info(spi_devs, ARRAY_SIZE(spi_devs));
otg_phy_init();
platform_add_devices(hwgw6410_devices, ARRAY_SIZE(hwgw6410_devices));
}
2、在使用CAN通信的过程中出现通信一段时间后通信中断的情况
这是中断触发方式的问题,驱动中默认的是下降沿触发,修改触发方式为低电平触发
修改 arch/arm/mach-s3c64xx/mach-smdk6410.c 中的
static struct mcp251x_platform_data mcp251x_info = {
.oscillator_frequency = 2 * 8000000,
.irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT //新增
};
至此CAN总线应该可以正常运行了,如有错误和疑问,欢迎指出!
参考博文:
wanli34562014-02-20 17:06:52
sinc_mark82:楼主,想请教一下,你移植的SPI总线,会再/dev下产生设备节点么?如果不产生,你怎么使用该总线啊?
我在6410下类似操作,在/sys/bus/spi和/sys/platform下可以看到spi的总线了,但该如何使用啊?谢谢!
会产生设备节点,你只要把SPI的线路和MCP2515连接好以后,内核里有SPI的读写节口,你在MCP2515驱动里可以使用这些接口对设备的寄存器进行读写操作。MCP2515的驱动程序会生生一个字符设备或者是网络接口(这个根据你使用的驱动类型决定),在应用层可以对驱动生成的字符设备或网络接口进行操作。
回复 | 举报sinc_mark822013-12-23 15:07:48
楼主,想请教一下,你移植的SPI总线,会再/dev下产生设备节点么?如果不产生,你怎么使用该总线啊?
我在6410下类似操作,在/sys/bus/spi和/sys/platform下可以看到spi的总线了,但该如何使用啊?谢谢!