Difference between revisions of "Zephyr drivers"

From Wiki at Neela Nurseries
Jump to navigation Jump to search
m (Add section q Trigger a.k.a. Interrupt Support q)
m (Amend notes on BMI323 interrupt support)
Line 227: Line 227:
  
 
BMI323 sensor driver provides interrupt handling and support through the following code constructs:
 
BMI323 sensor driver provides interrupt handling and support through the following code constructs:
 +
 +
<pre>
 +
1100 static DEVICE_API(sensor, bosch_bmi323_api) = {
 +
1101        .attr_set = bosch_bmi323_driver_api_attr_set,
 +
1102        .attr_get = bosch_bmi323_driver_api_attr_get,
 +
1103        .trigger_set = bosch_bmi323_driver_api_trigger_set,
 +
1104        .sample_fetch = bosch_bmi323_driver_api_sample_fetch,
 +
1105        .channel_get = bosch_bmi323_driver_api_channel_get,
 +
1106 };
 +
1107
 +
1108 static void bosch_bmi323_irq_callback(const struct device *dev)
 +
1109 {
 +
1110        struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data;
 +
1111
 +
1112        k_work_submit(&data->callback_work);
 +
1113 }
 +
</pre>
 +
 +
<pre>
 +
1115 static int bosch_bmi323_init_irq(const struct device *dev)
 +
1116 {
 +
1117        struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data;
 +
1118        struct bosch_bmi323_config *config = (struct bosch_bmi323_config *)dev->config;
 +
1119        int ret;
 +
1120
 +
1121        ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
 +
1122
 +
1123        if (ret < 0) {
 +
1124                return ret;
 +
1125        }
 +
1126
 +
1127        gpio_init_callback(&data->gpio_callback, config->int_gpio_callback,
 +
1128                            BIT(config->int_gpio.pin));
 +
1129
 +
1130        ret = gpio_add_callback(config->int_gpio.port, &data->gpio_callback);
 +
1131
 +
1132        if (ret < 0) {
 +
1133                return ret;
 +
1134        }
 +
1135
 +
1136        return gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_DISABLE);
 +
1137 }
 +
1138
 +
1139 static int bosch_bmi323_init_int1(const struct device *dev)
 +
1140 {
 +
1141        uint16_t buf;
 +
1142
 +
1143        buf = IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_LVL, ACT_HIGH) |
 +
1144              IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OD, PUSH_PULL) |
 +
1145              IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OUTPUT_EN, EN);
 +
1146
 +
1147        return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_IO_INT_CTRL, &buf, 1);
 +
1148 }
 +
</pre>
  
 
* https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/sensor/bosch/bmi323/bmi323.c#L1150
 
* https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/sensor/bosch/bmi323/bmi323.c#L1150

Revision as of 05:30, 24 February 2026

Keywords: sensor interrupts : sensor triggers : Zephyr triggers : sensor interrupt support

OVERVIEW

This page a stash point to hold Zephyr driver notes. Zephyr RTOS project includes a range of types of drivers. First type referenced by this page will be Zephyr's sensor drivers.

^ Zephyr Sensor Model

Zephyr 4.3.0 device driver documentation:

Zephyr 4.3.0 sensor model:

"Sensor attribute get" function prototype. This prototype reveals Zephyr's enumerations for sensor yyy . . .

Zephyr's sensor model plays a big role in the design of sensor drivers for this RTOS. Zephyr's [... sensor.h] header defines many things. Two important enums from this header file are:

_ Sensor channel enum _

_ Sensor attribute enum _

Sensor channels generally correspond to readings of a quantity in specific units, like degrees centigrade and acceleration in the x-axis. Sensor attributes generally corrrespond to configuration settings for a sensor, where these settings modify the way in which readings are taken and reported.

For a Zephyr driver to support configuration of a sensor's attributes, it must implement a function of the form:

sensor_attr_set()
int sensor_attr_set(const struct device* dev,
                enum sensor_channel chan,
                enum sensor_attribute attr,
                const struct sensor_value* val)

. . . whose typedef is at https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/drivers/sensor.h#L431.

^ Bosch BMI323 Driver Example

The Bosch BMI323 accelerometer magnetometer combined sensor has a driver in Zephyr 4.3.0. This driver implements its sensor attribute setter function in bmi323.c in two places. The first place is a sensor API struct which the driver declares. This API struct organizes the public API function of the driver. These APIs implement and honor each a function signature that's type defined in Zephyr's sensor.h header file.

The structure is defined starting at about line 384, bmi323.c:384:

static DEVICE_API(sensor, bosch_bmi323_api) = {
        .attr_set = bosch_bmi323_driver_api_attr_set,        <-- attribute setter
        .attr_get = bosch_bmi323_driver_api_attr_get,
        .trigger_set = bosch_bmi323_driver_api_trigger_set,
        .sample_fetch = bosch_bmi323_driver_api_sample_fetch,
        .channel_get = bosch_bmi323_driver_api_channel_get,
};

The attribute setter function is defined at about line 1101, bmi323.c:1101:

static int bosch_bmi323_driver_api_attr_set(const struct device *dev,
					    enum sensor_channel chan,
					    enum sensor_attribute attr,
					    const struct sensor_value *val)
{
	struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data;
	int ret;

	k_mutex_lock(&data->lock, K_FOREVER);

	switch (chan) {
	case SENSOR_CHAN_ACCEL_XYZ:
		switch (attr) {
		case SENSOR_ATTR_SAMPLING_FREQUENCY:
			ret = bosch_bmi323_driver_api_set_acc_odr(dev, val);

			break;

		case SENSOR_ATTR_FULL_SCALE:
			ret = bosch_bmi323_driver_api_set_acc_full_scale(dev, val);

			break;

		case SENSOR_ATTR_FEATURE_MASK:
			ret = bosch_bmi323_driver_api_set_acc_feature_mask(dev, val);

			break;

		default:
			ret = -ENODEV;

			break;
		}

		break;

	case SENSOR_CHAN_GYRO_XYZ:
		switch (attr) {
		case SENSOR_ATTR_SAMPLING_FREQUENCY:
			ret = bosch_bmi323_driver_api_set_gyro_odr(dev, val);

			break;

		case SENSOR_ATTR_FULL_SCALE:
			ret = bosch_bmi323_driver_api_set_gyro_full_scale(dev, val);

			break;

		case SENSOR_ATTR_FEATURE_MASK:
			ret = bosch_bmi323_driver_api_set_gyro_feature_mask(dev, val);

			break;

		default:
			ret = -ENODEV;

			break;
		}

		break;

	default:
		ret = -ENODEV;

		break;
	}

	k_mutex_unlock(&data->lock);

	return ret;
}

^ Mutex Use in BMI323 Driver

BMI323 driver code locks a mutex in the following routines of bmi323.c:

1. line 384: static int bosch_bmi323_driver_api_attr_set(...)

2. line 727: static int bosch_bmi323_driver_api_attr_get(...)

3. line 843: static int bosch_bmi323_driver_api_trigger_set(...)

4. line 996: static int bosch_bmi323_driver_api_sample_fetch(const struct device *dev, enum sensor_channel chan)

5. line 1047: static int bosch_bmi323_driver_api_channel_get(...)

6. line 1150: static void bosch_bmi323_irq_callback_handler(...)

7. line 1241: static int bosch_bmi323_pm_action(...)

^ BMI323 Driver Routines

59:static int bosch_bmi323_bus_init(const struct device *dev)
68:static int bosch_bmi323_bus_read_words(const struct device *dev, uint8_t offset, uint16_t *words,
78:static int bosch_bmi323_bus_write_words(const struct device *dev, uint8_t offset, uint16_t *words,
88:static int32_t bosch_bmi323_lsb_from_fullscale(int64_t fullscale)
94:static int64_t bosch_bmi323_value_to_micro(int16_t value, int32_t lsb)
100:static void bosch_bmi323_value_to_sensor_value(struct sensor_value *result, int16_t value,
111:static bool bosch_bmi323_value_is_valid(int16_t value)
116:static int bosch_bmi323_validate_chip_id(const struct device *dev)
134:static int bosch_bmi323_soft_reset(const struct device *dev)
152:static int bosch_bmi323_enable_feature_engine(const struct device *dev)
178:static int bosch_bmi323_driver_api_set_acc_odr(const struct device *dev,
226:static int bosch_bmi323_driver_api_set_acc_full_scale(const struct device *dev,
257:static int bosch_bmi323_driver_api_set_acc_feature_mask(const struct device *dev,
280:static int bosch_bmi323_driver_api_set_gyro_odr(const struct device *dev,
328:static int bosch_bmi323_driver_api_set_gyro_full_scale(const struct device *dev,
361:static int bosch_bmi323_driver_api_set_gyro_feature_mask(const struct device *dev,
384:static int bosch_bmi323_driver_api_attr_set(const struct device *dev, enum sensor_channel chan,
455:static int bosch_bmi323_driver_api_get_acc_odr(const struct device *dev, struct sensor_value *val)
530:static int bosch_bmi323_driver_api_get_acc_full_scale(const struct device *dev,
566:static int bosch_bmi323_driver_api_get_acc_feature_mask(const struct device *dev,
589:static int bosch_bmi323_driver_api_get_gyro_odr(const struct device *dev, struct sensor_value *val)
664:static int bosch_bmi323_driver_api_get_gyro_full_scale(const struct device *dev,
704:static int bosch_bmi323_driver_api_get_gyro_feature_mask(const struct device *dev,
727:static int bosch_bmi323_driver_api_attr_get(const struct device *dev, enum sensor_channel chan,
796:static int bosch_bmi323_driver_api_trigger_set_acc_drdy(const struct device *dev)
806:static int bosch_bmi323_driver_api_trigger_set_acc_motion(const struct device *dev)
843:static int bosch_bmi323_driver_api_trigger_set(const struct device *dev,
883:static int bosch_bmi323_driver_api_fetch_acc_samples(const struct device *dev)
925:static int bosch_bmi323_driver_api_fetch_gyro_samples(const struct device *dev)
968:static int bosch_bmi323_driver_api_fetch_temperature(const struct device *dev)
996:static int bosch_bmi323_driver_api_sample_fetch(const struct device *dev, enum sensor_channel chan)
1047:static int bosch_bmi323_driver_api_channel_get(const struct device *dev, enum sensor_channel chan,
1100:static DEVICE_API(sensor, bosch_bmi323_api) = {
1108:static void bosch_bmi323_irq_callback(const struct device *dev)
1115:static int bosch_bmi323_init_irq(const struct device *dev)
1139:static int bosch_bmi323_init_int1(const struct device *dev)
1150:static void bosch_bmi323_irq_callback_handler(struct k_work *item)
1164:static int bosch_bmi323_pm_resume(const struct device *dev)
1225:static int bosch_bmi323_pm_suspend(const struct device *dev)
1241:static int bosch_bmi323_pm_action(const struct device *dev, enum pm_device_action action)
1271:static int bosch_bmi323_init(const struct device *dev)
1318:	static struct bosch_bmi323_data bosch_bmi323_data_##inst;                                  \
1322:	static void bosch_bmi323_irq_callback##inst(const struct device *dev,                      \
1328:	static const struct bosch_bmi323_config bosch_bmi323_config_##inst = {                     \

^ Sensor Bus API and Sensor Bus

178 struct bosch_bmi323_bus_api {
179         /* Read up to multiple words from the BMI323 */
180         int (*read_words)(const void *context, uint8_t offset, uint16_t *words,
181                           uint16_t words_count);
182 
183         /* Write up to multiple words to the BLI323 */
184         int (*write_words)(const void *context, uint8_t offset, uint16_t *words,
185                            uint16_t words_count);
186 
187         /* Initialize the bus */
188         int (*init)(const void *context);
189 };
190 
191 struct bosch_bmi323_bus {
192         const void *context;
193         const struct bosch_bmi323_bus_api *api;
194 };

^ Trigger a.k.a. Interrupt Support

BMI323 sensor driver provides interrupt handling and support through the following code constructs:

1100 static DEVICE_API(sensor, bosch_bmi323_api) = {
1101         .attr_set = bosch_bmi323_driver_api_attr_set,
1102         .attr_get = bosch_bmi323_driver_api_attr_get,
1103         .trigger_set = bosch_bmi323_driver_api_trigger_set,
1104         .sample_fetch = bosch_bmi323_driver_api_sample_fetch,
1105         .channel_get = bosch_bmi323_driver_api_channel_get,
1106 };
1107 
1108 static void bosch_bmi323_irq_callback(const struct device *dev)
1109 {
1110         struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data;
1111 
1112         k_work_submit(&data->callback_work);
1113 }
1115 static int bosch_bmi323_init_irq(const struct device *dev)
1116 {
1117         struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data;
1118         struct bosch_bmi323_config *config = (struct bosch_bmi323_config *)dev->config;
1119         int ret;
1120 
1121         ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
1122 
1123         if (ret < 0) {
1124                 return ret;
1125         }
1126 
1127         gpio_init_callback(&data->gpio_callback, config->int_gpio_callback,
1128                            BIT(config->int_gpio.pin));
1129 
1130         ret = gpio_add_callback(config->int_gpio.port, &data->gpio_callback);
1131 
1132         if (ret < 0) {
1133                 return ret;
1134         }
1135 
1136         return gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_DISABLE);
1137 }
1138 
1139 static int bosch_bmi323_init_int1(const struct device *dev)
1140 {
1141         uint16_t buf;
1142 
1143         buf = IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_LVL, ACT_HIGH) |
1144               IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OD, PUSH_PULL) |
1145               IMU_BOSCH_BMI323_REG_VALUE(IO_INT_CTRL, INT1_OUTPUT_EN, EN);
1146 
1147         return bosch_bmi323_bus_write_words(dev, IMU_BOSCH_BMI323_REG_IO_INT_CTRL, &buf, 1);
1148 }
1150 static void bosch_bmi323_irq_callback_handler(struct k_work *item)
1151 {
1152         struct bosch_bmi323_data *data =
1153                 CONTAINER_OF(item, struct bosch_bmi323_data, callback_work);
1154 
1155         k_mutex_lock(&data->lock, K_FOREVER);
1156 
1157         if (data->trigger_handler != NULL) {
1158                 data->trigger_handler(data->dev, data->trigger);
1159         }
1160 
1161         k_mutex_unlock(&data->lock);
1162 }

^ References

1. https://github.com/zephyrproject-rtos/zephyr/issues/30133


- - - top of page - - -