1.ioctl函数:
Static int s3c44b0_mcp2510_ioctl (struct inode * inode,struct file *file, unsined cmd ,unsigned long arg){switch(cmd){case SETBAND://设置波特率
MCP2510_SetBandRate(BandRate,TRUE);break;case SETLPBK://设置工作方式
MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLK| CLK1);break;case SETID://设置标识符
MCP2510_Write_Can_ID(RXF0SIDH,U8 ID,0);break;case SETFILTER: //设置屏蔽码
MCP2510_Write_Can_ID(RXM0SIDH,0x1ff,0);break;}}
2.open函数(打开设备):
static int s3c44b0_mcp2510_open(struct inode *inode,struct file *file)
{printk("device openn");return 0;}
3.write函数(发送数据):
static ssize_t s3c44b0_mcp2510_write(struct file *file,const char *buffer,size_t count,loff_t *ppos){copy_from_user(&temp,buffer,sizeof(mcpcan_data)); canWrite(temp.id,temp.data,temp.DataLen,temp.IdType,temp.BufNo);}//发送数据函数
4.read函数(接收数据):
static ssize_t s3c44b0_mcp2510_read(struct file *file,char *buffer,size_t count,loff_t *ppos){Revdata(0x66,datas,0x08);//接收数据函数
copy_to_user(buffer,Receivedata.data,0x08);return count;}
3.5.2交叉编译CAN驱动程序
交叉编译驱动程序需要一台装了Red Hat Linux的宿主机。安装交叉编译工具的方法请参考相关文档(交叉编译工具:arm-elf-tools-20030314.sh)。驱动程序的使用可以按照两种方式进行编译,一种是静态编译进内核,一种是编译成模块以供动态加载。由于uclinux不支持模块动态加载,所以这里只介绍将驱动程序静态编译进内核的方法。为了让编译器编译所添加的驱动程序,需要修改相关文件。
1.修改/linux-2.4.x/driver/char/Makefile文件,增加:
Ifeq((tab键)$(CONFIG_MCP2510),Y) (换行)Obj-y+=akaeled.o
Endif//这几句话的意思是如果配置了mcp2510,则把mcp2510.o加进内核。
2.修改linux-2.4.x/driver/char/mem.c,在文件中增加如下代码:
#ifdef CONFIG_MCP2510 (换行)extern void mcp2510_init();
#endif//通过该文件告诉内核调用相应的CAN驱动程序
#ifdef CONFIG_MCP2510 (换行)mcp2510_init(); (换行)#endif
3.修改linux-2.4.x/driver/char/Config.in文件,在字符字段内添加如下代码:
Bool ‘mcp2510 support’ CONFIG_MCP2510
这样在make menuconfig时将出现mcp2510的配置选项。
4.修改/uClinux/vendor/Samsung/44b0/Makefile
在DEVICES部分添加内容:can, c, 125, 0。这句话的意思是在device中注册一个字符设备can,该设备主设备号为125,次设备号为0。在make menuconfig时进入Character devices,选中里面的support mcp2510。在root权限下执行下列命令编译内核:
1、#make dep;2、#make lib_only;3、#make romfs;4、#make image;5、#make
4 CAN驱动程序的测试
4.1 编写应用程序
为了验证所添加的驱动程序的正确性,编写一个应用程序CAN2510.C进行测试,在应用程序中使用下面函数创建一个线程用来发送数据:
pthread_creat(&id,NULL,(void *)cansend,&sendata);
在cansend()函数中用write()函数调用驱动程序s3c44b0_mcp2510_write()实现数据的发送,用read()函数调用驱动程序s3c44b0_mcp2510_read()接收节点发送过来的数据,用printf()输出节点发送过来的数据,验证接收到的数据是否正确。
4.2 编译CAN应用程序
编译应用程序有两种方法:一是放到内核中编译,这种方法需要写一个Makefile文件,还需要修改相应文件,比较麻烦;另外一种办法是单独编译,把编译产生的可执行文件添加到uclinux文件系统romfs中的bin文件夹下,重新编译内核。本实验采用了后者。执行:#arm-elf-gcc –elf2flt can2510.c –o can2510 –lpthread
其中arm-elf-gcc是编译器,增加参数–elf2flt是由于uclinux只支持flat格式的可执行文件,-0是对编译进行优化,can2510是编译产生的可执行文件名称。把can2510复制到/home/cai/uclinux/romfs/bin目录下,重新编译内核,把产生的映像文件image.rom或image.ram下载到目标板,运行can2510进行CAN驱动测试。
5 结论
本文的创新点:在分析Linux设备驱动程序工作原理和结构的基础上,独立添加了CAN总线设备驱动程序到嵌入式操作系统Linux中。经实验表明嵌入式系统下扩展CAN总线传输数据可靠、抗干扰强,在工业控制场合有很大的使用价值;同时,CAN设备在嵌入式操作系统linux下驱动程序的成功实现,为在嵌入式系统中扩展其他硬件设备驱动程序提供了很好的参考价值。