[OneOS study notes] I2C in the device driver model

  1. Introduction
  • OneOS abstracts the device driver model based on various peripherals . This article will analyze the implementation process of the I2C driver around the driver model.
  • The I2C driver takes STM32 as an example to mainly analyze the calling relationship between the layers in the driver model.
  • For the OneOS device driver model, see the document driver section on the OneOS official website (https://os.iot.10086.cn).
  1. I2C Driver Overview
  • The I2C driver framework is shown in the figure below:

  1. It can be seen from the figure that users can directly access the unified interface of the device and the API of the I2C device framework layer.
  2. The API provided by the driver for I2C devices is shown in the following table:

    API

    layer

    os_device_find

    management

    os_i2c_transfer

    frame layer

    os_i2c_client_write

    frame layer

    os_i2c_client_read

    frame layer

    os_i2c_client_write_byte

    frame layer

    os_i2c_client_read_byte

    frame layer

    os_i2c_master_send

    frame layer

    os_i2c_master_recv

    frame layer

  3. For different chips, the management layer provides device operation interfaces, the framework layer provides common interfaces for devices such as I2C, and the driver layer provides I2C device drivers for specific chips.
  • STM32 series chip I2C driver implementation process:
  1. Device registration:

After OneOS starts, it will enter _driver_stm32_i2c_driver_init(). When executing the initialization function, it will call driver_match_devices() to complete the matching between the driver and the device. If the match is successful, it will execute the stm32_i2c_probe() function of the device driver layer. In the probe() function Call the os_i2c_bus_device_register() function to register the i2c device of st to the i2c bus device. The os_i2c_bus_device_register() function in the framework layer, by calling the os_device_register() function, the i2c bus device is mounted to the kernel device linked list.

  1. Device access:

The application layer finds the device through the find function. The device ops function is implemented in the framework layer and the driver layer. The same function function is called layer by layer. The calling relationship is as follows:

os_device_read_nonblock →i2c_bus_device_read(os_i2c_master_recv)→os_i2c_transfer→stm32_i2c_transfer (call ST series HAL library function)

os_device_write_block →i2c_bus_device_write(os_i2c_master_send)→os_i2c_transfer→ stm32_i2c_transfer (call ST series HAL library function)

os_device_control →i2c_bus_device_control→os_i2c_transfer()→stm32_i2c_transfer ( call ST series HAL library function)

  1. Device Management

The device management layer implements the encapsulation of the device driver, which is a common function interface for all devices, and the I2C device implements device search and registration in the management layer.

  1. Find device: os_device_find()

Function prototype: os_device_t *os_device_find(const char *name)

Location: drivers\device.c

Parameter: name (device name)

Return value type: os_device_t (return device pointer)

Note: When accessing the device through os_device_find(), it is only implemented in the device management layer.

  1. os_device_find() traverses the device list os_device_list to find the device according to the name "i2c1" of the incoming device by defining os_list_for_each_entry; if the device is found, it returns the corresponding device pointer, otherwise it returns the null pointer OS_NULL.
  2. The value of os_device_list comes from the device registration function os_device_register().
  1. Register device: os_device_register()

Location: drivers\device.c

Parameters: dev (device pointer), name (device name)

Return value type: os_err_t

  1. First use os_device_find to find out whether the device name has been registered, if it has been registered, return the error type of invalid parameters.
  2. Initialize the base class object, put it into the object container to realize the initialization of the device, and add the device node to the device list of the system through os_list_add.

4. Equipment framework layer

The device framework layer abstracts the same hardware device drivers, extracts the same parts of the same hardware device drivers from different manufacturers, and leaves the different parts out of the interface to be implemented by the driver.

  1. Function interface (API):

    function

    Function

    os_i2c_bus_device_find

    Find I2C bus devices based on the I2C bus name

    i2c_bus_device_control

    Controls the characteristics of I2C bus devices

    i2c_bus_device_write

    Write send data to I2C bus device

    i2c_bus_device_read

    Read the data received by the I2C bus device

    os_i2c_master_recv

    I2C bus device data reception

    os_i2c_master_send

    I2C bus device data transmission

    os_i2c_client_write

    I2C master device data transmission

    os_i2c_client_read

    I2C master data reception

    os_i2c_client_write_byte

    Use cmd to write single-byte data to the I2C master device

    os_i2c_client_read_byte

    Read single byte data of I2C master device according to cmd

    os_i2c_transfer

    Transfer messages using I2C devices

    os_i2c_bus_device_register

    Register I2C device bus

  2. main effect:
  1. This layer mainly serves as a link between the previous and the next, providing a unified API for upper-layer applications, and providing registration functions for lower-layer drivers.
  2. Implement the device ops function: i2c_ops
  1. const static struct os_device_ops i2c_ops = {
  2.     .read    = i2c_bus_device_read,
  3.     .write   = i2c_bus_device_write,
  4.     .control = i2c_bus_device_control
  5. };
  1. Call the os_device_register function to register the I2C device to the device management layer.

5. Device driver layer

1. Implement the device ops function stm32_i2c_transfer, connect to the underlying hardware, and call the HAL library of STM32.

2. The probe function implements device initialization, and calls os_i2c_bus_device_register to register the device with the framework layer.

3. The method of calling the probe function.

  1. Call OS_DRIVER_INFO, and assign the probe and name of st_i2c to os_driver_info_t.
  1. OS_DRIVER_INFO stm32_i2c_driver = {
  2.     .name  = "I2C_HandleTypeDef",
  3.     .probe = stm32_i2c_probe,
  4. };
  1. #define OS_DRIVER_INFO static OS_USED OS_SECTION("driver_table") const os_driver_info_t
  1. The os_driver_info_t structure is defined as follows:
  1. typedef struct os_driver_info
  2. {
  3.     char *name;
  4.     int (*probe)(const struct os_driver_info *drv, const struct os_device_info *dev);
  5. } os_driver_info_t;
  1. When the device is initialized, stm32_i2c_driver will be used as the parameter of OS_DRIVER_DEFINE, the driver and device matching function will be called, and the driver will be compared with the driver corresponding to the device in the device_table one by one, until the same driver is found, the matching is completed, and then the device and driver are passed to The probe completes device registration.
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/5443273/blog/10084141