CHAPTER 5: NON-BLOCKING ANALISIS 46
5.1 I 2 C Hardware Driver Analysis 48
5.1.3 I 2 C Waveform Analysis 52
For this example, the same three sensors previously mentioned are read using
both blocking and non-blocking I2C function calls. Each of these sensors is read every
5ms. In order to visually examine the effects of blocking code, a couple of general
related to I2C communication. These GPIO pins were viewed on a digital logic analyzer
along with the associated I2C signals. Snapshots of the blocking and non-blocking results
from digital analyzer are shown in Figures 5.3 and 5.4, respectively. The signal used to
represent the time spent executing the I2C functions is D11. It is set high at the beginning
and set low at the end of every I2C function call. So, the amount of time spent in each
function is indicated by the signal remaining high. In a similar fashion, the D10 signal
represents the time spent executing the Sensor Task. The D10 signal is set high when
entering the Sensor Task function and is set low when upon completion. The sensor task’s
application is responsible for the devices that use the I2C communication. Signals D1
Figure 5.3: Blocking I2C Waveform (a) 20ms Resolution (b) 1ms Resolution
With the Superloop scheduling method, the processor continually loops through
all of the tasks. When none of the tasks block, the main scheduling loop will be executed
in a very short time. This results in signal D10, which represents the sensor task
execution time, toggling so quickly that it appears as solid section in Figure 5.3(a). There
is a resolution of 20 ms per division for Figure 5.3(a). When I2C communication occurs,
signal D10 is held high indicating that the sensor task is blocking the main scheduling
loop. The I2C communication is indicated by the solid portions on the D1 and D0 signals
due to the fact that the I2C read function indicated by D11 block the sensor task, which in
turn blocks the scheduler. In this example, the accelerometer and gyroscope are typically
read from inside the same sensor task call. This is why both D11 and D10 are held high
during the blocking I2C communication.
In the wider section of I2C activity, the D11 signal has two sections indicating
that there are two I2C communications that take place in one sensor task call. These are
the I2C communications for reading the accelerometer and gyroscope sensors. The
narrower I2C activity sections indicate when the magnetometer is read. It can be seen
from Figure 5.3(a) that all of three sensors are read once every 50ms in this example.
Figure 5.3(b) displays a zoomed-in view of accelerometer and gyroscope sensor readings
at a resolution of 1ms per division. The decoded I2C message is displayed in the lower
part of Figure 5.3(b). The I2C address of the accelerometer is 0x1D, and the gyroscope is
0x69. The relatively slow nature of I2C communication results in the sensor reads taking
considerably longer than the typical scheduler cycle. Figure 5.3(b) shows that the
scheduler typically cycles well over ten times per millisecond. Whereas, the I2C sensor
read can easily exceed 4ms. Figure 5.3(b) shows that it typically takes longer than 8ms to
complete the sensor task when the two sensors are read. Figure 5.3(a) show a
magnetometer takes about half as much time, which is 4ms. So, there is a total of 20ms
activity on the I2C communication lines every 50ms. During this time, the main
scheduling loop is kept from cycling. This means that approximately 24% of processing
time is wasted on simply polling I2C hardware. Furthermore, Superloop schedulers work
needs to change. So, if one of the tasks block for much more than a millisecond, there is a
good chance another task will miss an important state update. For some systems (e.g., this
sensor system), this could only result in losing a couple of data samples. However, for
some systems (e.g., a critical control system), a missed state change could result in
catastrophic failure. So, it is important to consider the possible failures before risking the
use of blocking code.
In contrast, Figure 5.4 shows that, with the non-blocking example, the sensor task
does not block the main scheduler from cycling through the tasks. For ease of
comparison, Figure 5.4 displays the non-blocking example similarly to the blocking
example in Figure 5.3. All of the signals are represented by the same names (D0, D1,
etc.) that were used for the blocking example in Figure 5.3. The only difference for the
example shown in Figure 5.4 is the use of a non-blocking I2C driver to interface with the
sensor. The non-blocking driver uses an I2C task to execute callback functions. Thus,
signal D11 is held high whenever the I2C task function is called in addition to the I2C
read and writes. Since the non-blocking I2C driver releases control back to the sensor task
when read requests are called, the scheduler continues to cycle while the sensors are
being read. Figure 5.4(a), which is also has a resolution of 20ms per division, shows both
the I2C tasks and the sensor tasks are cycling at the same time as the microcontroller is
communicating with the sensors. There is the occasional blip where a task takes a little
longer than usual. This blip is usually caused by the sensor task processing the data
directly after the I2C read is completed. Figure 5.4(b), which has a resolution 1ms per
So, even though the total I2C communication activity is still over 12ms every 50ms, there
is only 2ms of this time where the Sensor Task blocks the main scheduling loop from
cycling at its normal pace. This means that about only 4% of the processing time is spent
waiting on the sensor task with a non-blocking I2C driver. This means that about 20% of
the processer availability is freed in this example. If the system never uses more than
80% of the processing time, then wasting 20% may not be a significant problem. This is
particularly true if the system’s only task is reading the sensors. However, there are
occasions where the system using less than 50% might still have a time-critical occasion
that cannot afford to be blocked for more than 1ms at a time. In this situation, the wasted
Figure 5.4: Non-Blocking I2C Waveform (a) 20ms Resolution (b) 1ms Resolution
While a sample period of 50ms may be very short for some sensors, it is actually
relatively slow for inertial navigation applications where accelerometers, gyroscopes, and
magnetometers are commonly used. This is a practical example of how blocking code can
have a detrimental effect on a system. Clearly, the exact effects of blocking code are
different in each application. As a result of many of the factors involved, it is difficult to