Realization of CAN Bus Driver under Embedded Linux

Citation source: https://www.cnblogs.com/general001/articles/2342728.html

 1 Introduction

  Industrial control devices designed based on embedded systems are subject to various interferences at the industrial control site, such as electromagnetic, dust, and weather, which have a great impact on the normal operation of the system. To frequently exchange and transmit data between various devices in the industrial control field, a field bus with strong anti-interference, stability and fast transmission rate is needed for communication. Article using the CAN bus , 32-bit embedded systems based S3C44B0X microprocessor , through its SPI interfaces , the MCP2510  CAN controller extended CAN bus ; embedded operating system embedded in a micro S3C44B0X processor , a multi-task can friendly graphical User interface; for S3C44B0X microprocessor without memory management unit MMU, uClinux embedded operating system is adopted. In this way, the key technology for expanding CAN devices in embedded systems is the realization of CAN device drivers under embedded operating systems. The article focuses on solving the problem of CAN bus driver implementation under embedded operating system. For users, the implementation of CAN devices driven by embedded operating systems shields users from the details of the hardware, and users can compile their own user programs without caring about the hardware. The experimental results show that the correctness of the driver program can improve the anti-interference ability of the entire system, with good stability, and the maximum transmission rate can reach 1Mb/s; the error verification feature of the hardware also enhances the anti-electromagnetic interference ability of CAN.

  2 System hardware design

  The system adopts S3C44B0X microprocessor and needs to expand CAN controller. Commonly used CAN controller has SJA1000 and MCP2510 , both chips support CAN2.0B standard. The bus used by SJA1000 is a multiplexing of address and data lines , but the external bus of embedded processors is mostly structured with separate address and data lines, so each time you operate SJA1000, you need to write address and data twice. And SJA1000 uses 5V logic level. Therefore, the MCP2510 controller is used for expansion, and the transceiver uses 82C250 . MCP2510 controller features: 1. Support standard format and extended format CAN data frame structure (CAN2.0B); effective data length of 2.0-8 bytes, support remote frame; 3. Maximum programmable baud rate of 1Mb/s ; 4.2 receiving buffers supporting filters, 3 sending buffers; 5. SPI high-speed serial bus, maximum 5MHz ; 6.3 ~ 5.5V wide voltage range power supply. The working voltage of MCP2510 is 3.3V , which can be directly connected to the I/O port of S3C44B0X microprocessor. In order to further improve the anti-interference of the system, an optical isolation 6N137 can be added between the CAN controller and the transceiver . Its structural principle block diagram is shown in Figure 1:

                Figure 1. S3C44B0X extended CAN structure block diagram

                   Figure 2. Character device registry

  The design of 3CAN device driver

  Linux treats devices as special files for management. To add a device, you must first register the device and add its driver. The device driver is the interface between the operating system kernel and the device hardware, and shields the hardware details for the application. In linux, the user process cannot directly operate the physical device, and must make a request to the kernel through a system call, and the kernel calls the corresponding device driver. Therefore, the concepts of Linux device management, device driver, device registration, and Linux interrupt are first established.

  3.1 Linux device management

  Linux supports a variety of peripheral devices, and the management of these devices is generally called device management. Device management is divided into two parts: one is the upper layer of the driver, which has nothing to do with the device. This part communicates with the device through a specific device driver interface according to input and output requests; the other part is the lower layer, which is related to the device, usually called As a device driver, it directly deals with the hardware and provides a set of access interfaces to the upper layer. In order to perform operations such as reading and writing on the device, Linux device management logicalizes the physical device, regards it as a special file, called a device file, and uses file system interfaces and system calls to manage and control the device . Linux divides devices into three categories, block devices, character devices, and network devices. Each type of equipment has different management and control methods and different drivers, so it is convenient to cut the system. The Linux kernel recognizes the device based on the device type and device number. Each device that uses the same driver in a character device has a unique major device number. The CAN device sets the device type and device number to can and 125 under the /vendor/Samsung/44b0/Makefile file.

  3.2 file_opera TI ON s structure

  The specific realization of device operation by Linux is completed by the device driver. The device driver is loaded into the system through device registration. The operation of the Linux driver on the file is completed through the file_operations structure. The file_operations structure is a collection of file operation function pointers. In the device management, the operating functions pointed to by each member item of the structure are the operating routines of the device driver, and writing the driver is essentially writing each function in the structure. Different devices can be equipped with all or part of the operation functions, and the function pointers that are not used are set to NULL . The following is the CAN device file_operations structure:

  Static struct file_operations {

  WRI TE : s3c44b0_mcp2510_write, // write

  read: s3c44b0_mcp2510_read,//read operation

  ioctl: s3c44b0_mcp2510_ioctl,//operations other than reading and writing

  open: s3c44b0_mcp2510_open,//Open the device

  release: s3c44b0_mcp2510_release};//Close the device

  The name of each member of this structure corresponds to a system call. The user process uses the system call to call its own driver interface. The system call finds the corresponding device driver through the major device number of the device file, then reads the corresponding function pointer of this data structure, and then transfers control to the function.

  3.3 Device registration

  In Linux, when a device is installed in the system, it must be registered with the system. The main task of device registration is to load the device driver into the system. Linux separates the registration and management of different devices (such as character devices and block devices). Each device descriptor includes two pointers: name points to the device name string, and fops points to the file operation function structure file_operations, which contains pointers to various operation routines of the driver. Figure 2 shows a schematic diagram of the Linux character device registry. The registration function of the CAN character device is the kernel function: register_chrdev(MAJOR_NR, device _N AME ,&s3c44b0_mcp2510_fops);

  The parameter DEVICE_NAME represents the device name, and s3c44b0_mcp2510_fops represents a pointer to the file_operations structure, that is, the driver that points to the device.

  3.4 Linux interrupt handling

  In the Linux system, the processing of interrupts belongs to the core part of the system. Therefore, if the device and the system exchange data in an interrupt mode, the device driver must be regarded as a part of the system core. The device driver applies for an interrupt by using the request_irq function, and releases the interrupt by free_irq. Since interrupts were not used in this experiment, we will not introduce them in detail here.

  3.5 Implementation of CAN Driver

  3.5.1 Writing driver operation routines

  CAN devices are character devices. For CAN bus devices, in addition to sending (using the write method) and receiving (using the read method), it also needs to control the baud rate of CAN bus communication, set the working mode, set ID, etc., so using ioctl is The most suitable method.

  Entry function of CAN driver:

  int __init s3c44b0_mcp2510_init(void){ ARM TargetInit( );//Initialize ARM

  init_MCP2510(BandRat125kbps);//Initialize CAN controller ret=register_chrdev(MAJOR_NR,DEVICE_NAME,&s3c44b0_mcp2510_fops);)//Register CAN device

  The exit function of the CAN driver: void __exit s3c44b0_mcp2510_exit(void){

  unregister_chrdev(MAJOR_NR,DEVICE_NAME);printk("MCP2510 Eixt!n");}

  Write various operation routines of CAN device driver:

  1.ioctl function:

  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://set working method

  MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLK| CLK1);break;case SETID://setting identifier

  MCP2510_Write_Can_ID(RXF0SIDH,U8 ID,0);break;case SETFILTER: //Set the mask code

  MCP2510_Write_Can_ID(RXM0SIDH,0x1ff,0);break;}}

  2.open function (open the device):

  static int s3c44b0_mcp2510_open(struct inode *inode,struct file *file)

  {printk("device openn");return 0;}

  3.write function (send data):

  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 function (receive data):

  static ssize_t s3c44b0_mcp2510_read(struct file *file,char *buffer,size_t count,loff_t *ppos){Revdata(0x66,datas,0x08);//Receive data function

  copy_to_user(buffer,Receivedata.data,0x08);return count;}

  3.5.2 Cross compiling CAN driver

  Cross-compiling the driver requires a host computer with Red Hat Linux installed. For the method of installing cross-compilation tools, please refer to related documents (cross-compilation tools: arm-elf-tools-20030314.sh). The use of the driver can be compiled in two ways, one is statically compiled into the kernel, and the other is compiled into a module for dynamic loading. Since uclinux does not support dynamic loading of modules, only the method of statically compiling the driver into the kernel is introduced here. In order for the compiler to compile the added driver, the relevant files need to be modified.

  1. Modify /linux-2.4.x/driver/char/Makefile, add:

  Ifeq((tab键)$(CONFIG_MCP2510),Y)      (换行)Obj-y+=akaeled.o

  Endif//These words mean that if mcp2510 is configured, mcp2510.o will be added to the kernel.

  2. Modify linux-2.4.x/driver/char/mem.c and add the following code to the file:

  #ifdef CONFIG_MCP2510   (换行)extern void mcp2510_init();

  #endif//Tell the kernel to call the corresponding CAN driver through this file

  #ifdef CONFIG_MCP2510 (line feed)mcp2510_init(); (line feed)#endif

  3. Modify the linux-2.4.x/driver/char/Config.in file and add the following code in the character field:

  Bool ‘mcp2510 support’ CONFIG_MCP2510

  In this way, the configuration options of mcp2510 will appear when make menuconfig.

  4. Modify /uClinux/vendor/Samsung/44b0/Makefile

  Add content in the DEVICES section: can, c, 125, 0. The meaning of this sentence is to register a character device can in the device. The major device number of the device is 125 and the minor device number is 0. Enter Character devices when make menuconfig, select support mcp2510 inside. Run the following commands under root authority to compile the kernel:

  1、#make dep;2、#make lib_only;3、#make romfs;4、#make image;5、#make

  4 CAN driver test

  4.1 Writing an application

  In order to verify the correctness of the added driver, write an application CAN2510.C for testing. Use the following function in the application to create a thread to send data:

  pthread_creat(&id,NULL,(void *)cansend,&sendata);

  In the cansend() function, use the write() function to call the driver s3c44b0_mcp2510_write() to send data, use the read() function to call the driver s3c44b0_mcp2510_read() to receive the data sent by the node, and use printf() to output the data sent by the node To verify that the received data is correct.

  4.2 Compile CAN application

  There are two ways to compile an application: one is to compile it in the kernel. This method requires writing a Makefile and modifying the corresponding file, which is troublesome; the other is to compile separately and add the executable file generated by the compilation. Go to the bin folder in the romfs of the uclinux file system and recompile the kernel. This experiment uses the latter. Implementation: #arm-elf-gcc –elf2flt can2510.c –o can2510 –lpthread

  Among them, arm-elf-gcc is the compiler, and the parameter -elf2flt is added because uclinux only supports executable files in flat format, -0 is to optimize the compilation, and can2510 is the name of the executable file generated by the compilation. Copy can2510 to the /home/cai/uclinux/romfs/bin directory, recompile the kernel, download the generated image file image.rom or image.ram to the target board, and run can2510 for CAN driver test.

  5 Conclusion

  The innovation of this article: Based on the analysis of the working principle and structure of the Linux device driver, the CAN bus device driver is independently added to the embedded operating system Linux. Experiments show that the extended CAN bus under the embedded system has reliable data transmission and strong anti-interference, and has great use value in industrial control occasions. At the same time, the successful realization of the driver program of the CAN device under the embedded operating system linux is for the embedded system Extending other hardware device drivers in the system provides a good reference value.

Ability determines the stage, performance reflects value, wealth returns talent! If you don't accumulate steps, you can't reach a thousand miles; if you don't accumulate small currents, you can't become a river! A thousand miles begins with a single step. To change the present is to change the future. Change the future, start now.

Guess you like

Origin blog.csdn.net/lilifang_2011/article/details/111170734