Summary of HMC5883L driver writing and debugging

Source: Internet
Author: User

I have just finished writing and debugging the HMC5883L driver for the sensor. Although I have been in touch with various related knowledge points, I still encountered a lot of trouble when I was writing the driver from scratch, here, we will summarize the experience and lessons learned from driver writing in the future. We will also review and summarize the kernel driver knowledge we have learned in the past. Facts have proved that it is better to learn how many books you have read than to learn by yourself. Remember it.

I2C interfaces are required for several sensors at hand, so I have reviewed and studied the I2C subsystem. Some of the code I mentioned or pasted below may not be suitable for real board-level drivers, because it is tested in modular form.
In this modular driver, you must not only register the driver (i2c_driver), but also register the device information (i2c_client ), I think it makes no difference here regardless of the order (just like the question of "first chicken or first egg ). I mentioned when analyzing the i2c subsystem at the frontend that i2c_register_board_info cannot be used for new devices that are added after the i2c adapter is registered, which causes the device to be completely inactive, the i2c_new_device is required to dynamically register the device to the system. When using i2c_new_device, The i2c_board_info structure of the device is required, and the I2C adapter bus number attached to the device is also required. First, you can run the i2cdetect command to view the bus number:
  root@arm:/home/debian# i2cdetect -l  i2c-0    i2c           OMAP I2C adapter                    I2C adapter  i2c-1    i2c           OMAP I2C adapter                    I2C adapter
Then, you can use it in the Code as follows:
Struct i2c_adapter * adap; int adap_nr = 1; // the bus number is 1 adap = i2c_get_adapter (adap_nr );

In this way, the i2c_adapter pointer of the specified bus number is obtained, and then the pointer can be used for i2c_new_device. Note that after you register the device information, use i2c_put_adapter (adap) to release the pointer.
The structure used to describe hardware information can be saved as the private data of the i2c_client, and the structure usually needs to save the corresponding client. The corresponding relationship should be carried out in the probe interface function:
  static int hmc5883l_probe(struct i2c_client *client, struct i2c_device_id *id)  {      ...      i2c_set_clientdata(client, dev);      dev->client = client;      ...  }
Driver not written, debugging first. If you can directly debug and view the device through the simple application of the tool before you start writing the driver, it will be of great help to writing the driver. So here we will talk about several Debugging commands i2cdetect, i2cdump, i2cget, and i2cset In the I2C shell. The first is i2cdetect, which is generally used to detect and list the bus (as demonstrated above). The general usage is: list the bus-> test the effective device.
I2cdetect-l // list existing I2C adapter information i2cdetect-y-r 1 // view all devices mounted on the I2C adapter with bus number 1. If the device is true and valid, the address is displayed, instead of UU. UU indicates that there may be an actual device, but the device may be busy.

The result is as follows:
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  00:          -- -- -- -- -- -- -- -- -- -- -- -- --   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --   50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --   60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --   70: -- -- -- -- -- -- -- -- 
Here we can see that the devices with the IP address 0x68 and 0x1e have actually valid hardware connections, respectively, The MPU6050 of HMC5883L and AD0 grounding (not connected. 0x54 55 56 57 is the EEPROM, and the device is busy.
The second is i2cdump, which is used to view the internal register value of the device. The usage is i2cdump-y bus number device address.
  root@arm:/home/debian# i2cdump -y 1 0x1e  No size specified (using byte-data access)       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef  00: 10 20 03 01 21 01 4b ff 50 03 48 34 33 00 00 3c    ? ??!?K.P?H43..<  10: 00 00 00 00 00 00 00 00 00 00 00 94 09 04 e8 10    ...........?????  20: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00    ........?.......  30: 00 00 00 14 11 55 56 00 a0 00 07 00 00 00 00 00    ...??UV.?.?.....  40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  80: 10 20 03 01 21 01 4b ff 50 03 48 34 33 00 00 3c    ? ??!?K.P?H43..<  90: 00 00 00 00 00 00 00 00 00 00 00 94 09 04 e8 10    ...........?????  a0: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00    ........?.......  b0: 00 00 00 14 11 55 56 00 a0 00 07 00 00 00 00 00    ...??UV.?.?.....  c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................  f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
Then i2cget and i2cset are used to obtain and write registers respectively. The usage is i2cget-y bus number device Address Register address mode and i2cset-y bus number device Address Register address value mode. The default mode is B (byte) to read 8-bit data. The i2cget mode is B/w/c, and the i2cset mode is B/w/c/I/s, w is the word (16 bit), and I and s are the block data of I2C and SMBUS respectively.

Do not forget to initialize the Mutex mutex lock. Static initialization DEFINE_MUTEX (mutex_name) and dynamic initialization of mutex_init (struct mutex * lock ). If you forget to initialize and use it, the kernel will directly report an error. Do not use mutex lock in the interrupt context, because if a race occurs, mutex may enter sleep, And the interrupt context is absolutely not allowed to sleep. Therefore, do not use it. If you must use the lock mechanism to protect some drive resources during the interruption, we recommend that you use the spin lock (semaphore semaphores are not allowed, for the same reason ). Pay attention to deadlocks. If any operation requires a lock, you must plan the lock in advance. Do not lock the lock when an operation enters, but lock the lock after entering its sub-step. In this way, the lock is directly deadlocked and the system is freeze. The use of interrupt is very simple, but there are many noteworthy details.
GPIO interruption. For example, on some development boards, many GPIO ports are extended externally, but IRQ ports are not found. Therefore, you need to extend GPIO to a disconnection. In the code, you can use the gpio_to_irq (gpio_nr) function (linux/gpio. h) to obtain the interrupt line number after automatic conversion, which can be used to request interruption. If the final parameter given during request_irq is not NULL, the second parameter must be consistent with free_irq, otherwise, the system will not be able to find the handler handle of the interrupt to be released (of course, if it is NULL, it will be NULL. This is no problem, as long as it is consistent ). The work queue is divided into work_struct and delayed_work. The difference is that delayed_work will start running after the specified delay, and work_struct will be scheduled to run immediately.
Initialization. INIT_WORK (struct work_struct * work, void (* work_func) (struct work_struct * work) dynamically initializes work_struct. INIT_DELAYED_WORK (struct delayed_work * work, void (* work_func) (struct work_struct * work) dynamically initializes delayed_work. In the work_func function of delayed_work, you can forcibly convert * work to the struct delayed_work type. Scheduling. Work_struct is scheduled to schedule_work (struct work_struct * work), while delayed_work requires another delay parameter schedule_delayed_work (struct delayed_work * work, unsigned long delay ), here, the delay parameter is how long the delay will take to work. The unit is jiffies. classes such as msecs_to_jiffies (msecs) and other conversion functions are often used. If a queue is not specified for the working function, it will automatically enter system_wq, and its own working queue is often used in the driver, but this is often not required for simple work. For jobs that frequently report information, it is best to define your own work queue and put this job into your work queue for running, instead of the system's default system_wq, this will prevent your work from being quickly scheduled when the system is busy, and your work queue will play a major role in this regard. Completion synchronization uses completion as the synchronization mechanism because it tries to perform self-check and involves interruptions during the debugging process. Simple usage is proposed here.
Initialization. Init_completion (struct completion * wait) wait. Wait_for_completion_timeout (struct completion * wait, unsigned long timeout), the return value is the remaining time. If the remaining time is 0, that is, it times out. Wake up. The complete (struct completion * wait) code is in the https://github.com/bbbLinux/projects_hmc5883l

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.