What is batching?

Batching refers to storing sensor events in a hardware FIFO before reporting them through the HAL instead of reporting them immediately.

Batching can enable significant power savings by preventing the SoC from waking up to receive each event. Instead, the events can be grouped and processed together.

The bigger the FIFOs, the more power can be saved. Implementing batching is an exercise of trading off hardware memory for reduced power consumption.

Batching happens when a sensor possesses a hardware FIFO (sensor_t.fifoMaxEventCount > 0) and in one of two situations:

  • max_report_latency > 0, meaning the sensor events for this specific sensor can be delayed up to max_report_latency before being reported through the HAL.
  • The SoC is in suspend mode and the sensor is a non-wake-up sensor, meaning events must be stored while waiting for the SoC to wake up.

See the paragraph on the HAL batch function for more details.

The opposite of batching is continuous operation, where events are reported immediately instead of being buffered. Continuous operation corresponds to:

  • When max_report_latency = 0 and the events can be delivered to the app, meaning one of the following:
    • The SoC is awake.
    • The sensor is a wake-up sensor.
  • Or when the sensor doesn’t have a hardware FIFO (sensor_t.fifoMaxEventCount = 0), in which case, one of the following occurs:
    • The events are reported if the SoC is awake or the sensor is a wake-up sensor.
    • The events are lost when the SoC is asleep and the sensor is a non-wake-up sensor.

Wake-up FIFOs and non-wake-up FIFOs

Sensor events from wake-up sensors must be stored in a wake-up FIFO. There can be one wake-up FIFO per sensor, or more commonly, one big shared wake-up FIFO where events from all wake-up sensors are interleaved. Other options are also possible, for example, some wake-up sensors having a dedicated FIFO, and the rest of the wake-up sensors sharing a FIFO.

Similarly, sensor events from non-wake-up sensors must be stored in a non-wake-up FIFO, and there can be one or several non-wake-up FIFOs.

In all cases, wake-up sensor events and non-wake-up sensor events can't be interleaved in the same FIFO. Wake-up events go in wake-up FIFOs, and non-wake-up events go in non-wake-up FIFOs.

For the wake-up FIFO, having a single shared FIFO provides the best power benefits. For the non-wake-up FIFO, the power difference between a shared FIFO and dedicated FIFOs is negligible. See FIFO allocation priority for suggestions on how to allocate each FIFO.

Behavior outside of suspend mode

When the SoC is awake (not in suspend mode), events can be stored temporarily in their FIFO, as long as they are not delayed by more than max_report_latency.

As long as the SoC doesn’t enter the suspend mode, no event is dropped or lost. If an internal hardware FIFO is getting full before max_report_latency elapses, then events are reported at that point to ensure that no event is lost.

If several sensors share the same FIFO and max_report_latency for one of them elapses, all events from the FIFO are reported, even if max_report_latency for the other sensors hasn’t elapsed. The general goal is to reduce the number of times batches of events must be reported, so as soon as one event must be reported, all events from all sensors can be reported.

For example, if the following sensors are activated:

  • Accelerometer batched with max_report_latency = 20s
  • Gyroscope batched with max_report_latency = 5s

Then the accelerometer batches can be reported at the same time the gyroscope batches are reported (every 5 seconds), even if the accelerometer and the gyroscope don't share the same FIFO.

Behavior in suspend mode

Batching is particularly beneficial for collecting sensor data in the background without keeping the SoC awake. Because the sensor drivers and HAL implementation aren't allowed to hold a wake-lock (see Note, below), the SoC can enter the suspend mode even while sensor data is being collected.

The behavior of sensors while the SoC is suspended depends on whether the sensor is a wake-up sensor. See Wake-up sensors for some details.

When a non-wake-up FIFO fills up, it must wrap around and behave like a circular buffer, overwriting older events, so the new events replace the oldest ones. max_report_latency has no impact on non-wake-up FIFOs while in the suspend mode.

When a wake-up FIFO fills up, or when max_report_latency of one of the wake-up sensor elapses, the hardware must wake up the SoC and report the data.

In both cases (wake-up and non-wake-up), as soon as the SoC comes out of the suspend mode, a batch is produced with the content of all FIFOs, even if max_report_latency of some sensors hasn’t elapsed. This minimizes the risk of having to wake-up the SoC again soon if it goes back to the suspend mode. Hence, it minimizes power consumption.

Precautions to take when batching wake-up sensors

Depending on the device, it can take a few milliseconds for the SoC to come out of suspend and start flushing the FIFO. Allocate enough head room in the FIFO to allow the device to come out of suspend without the wake-up FIFO overflowing. Then no events are lost, and max_report_latency is respected.

Precautions to take when batching non-wake-up on-change sensors

On-change sensors only generate events when the value they're measuring is changing. If the measured value changes while the SoC is in the suspend mode, apps expect to receive an event as soon as the SoC wakes up. Because of this, batching of non-wake-up on-change sensor events must be performed carefully if the sensor shares its FIFO with other sensors. The last event generated by each on-change sensor must always be saved outside of the shared FIFO so that it can't be overwritten by other events. When the SoC wakes up, after all events from the FIFO have been reported, the last on-change sensor event must be reported.

For example, avoid this situation:

  1. An app registers to the non-wake-up step counter (on-change) and the non-wake-up accelerometer (continuous), both sharing the same FIFO.
  2. The app receives a step counter event step_count=1000 steps.
  3. The SoC goes to suspend.
  4. The user walks 20 steps, causing step counter and accelerometer events to be interleaved, the last step counter event being step_count = 1020 steps.
  5. The user doesn’t move for a long time, causing accelerometer events to continue accumulating in the FIFO, eventually overwriting every step_count event in the shared FIFO.
  6. The SoC wakes up and all events from the FIFO are sent to the app.
  7. The app receives only accelerometer events and indicates that the user didn’t walk (bad!).

By saving the last step counter event outside of the FIFO, the HAL can report this event when the SoC wakes up, even if all other step counter events were overwritten by accelerometer events. This way, the app receives step_count = 1020 steps when the SoC wakes up.

Implementing batching

Batching can't be emulated in software, so it must be implemented entirely in hardware, with hardware FIFOs. In particular, it can't be implemented on the SoC, for example in the HAL implementation, as this would require the SoC to be awake. The goal here is to save significant amounts of power. Batching must be implemented without the aid of the SoC, which should be allowed to be in suspend mode during batching.

max_report_latency can be modified at any time, in particular while the specified sensor is already enabled; this doesn't result in the loss of events.

FIFO allocation priority

On platforms in which hardware FIFO size is limited, the system designers may have to choose how much FIFO to reserve for each sensor. To help with this choice, here are some example apps that are more power-efficient when different sensors are batched.

High value: Low power pedestrian dead reckoning

Target batching time: 1 to 10 minutes

Sensors to batch:

  • Wake-up step detector
  • Wake-up game rotation vector at 5 Hz
  • Wake-up barometer at 5 Hz
  • Wake-up uncalibrated magnetometer at 5 Hz

Batching this data allows performing pedestrian dead reckoning while letting the SoC go to suspend.

High value: Medium power intermittent activity/gesture recognition

Target batching time: 3 seconds

Sensors to batch: Non-wake-up accelerometer at 50 Hz

Batching this data allows periodically recognizing arbitrary activities and gestures without having to keep the SoC awake while the data is collected.

Medium value: Medium power continuous activity/gesture recognition

Target batching time: 1 to 3 minutes

Sensors to batch: Wake-up accelerometer at 50 Hz

Batching this data allows continuously recognizing arbitrary activities and gestures without having to keep the SoC awake while the data is collected.

Medium-high value: Interrupt load reduction

Target batching time: < 1 second

Sensors to batch: Any high-frequency sensor, usually non-wake-up.

If the gyroscope is set at 240 Hz, even batching just 10 gyro events can reduce the number of interrupts from 240/second to 24/second.

Medium value: Continuous low-frequency data collection

Target batching time: 1 to 10 minutes

Sensors to batch:

  • Wake-up barometer at 1 Hz
  • Wake-up humidity sensor at 1 Hz
  • Other low frequency wake-up sensors at similar rates

Allows creating monitoring apps at low power.

Medium-low value: Continuous full-sensors collection

Target batching time: 1 to 10 minutes

Sensors to batch: All wake-up sensors, at high frequencies

Allows full collection of sensor data while leaving the SoC in suspend mode. Consider this only if FIFO space isn't an issue.