Sampling Analytics - MichaelMcGetrick/meta-stm32mp1-custom GitHub Wiki
According to its datasheet, the MCP3008 analog to digital converter can sample at a maximum rate of 200ksps. This is for the idealised case of a transfer of 18 bytes necessary for conveying a data sample and with a top clock speed of 3.6MHz for a device running on 5V power supply. According to the datasheet, the relation between clock frequency (fc) and sampling frequency (fs) is given by
fc = 18 * fs
The datasheet implies that a device running at 3.3V would deliver a maximum clock frequency of 1.94MHz. For the purposes of this analysis, we will consider a clock rate of 1MHz on the spi bus which is a safe rate preventing possible overclocking at 3.3V. Using the above formula, this would deliver a sample rate of around 55ksps In reality, due to the transfer requirements of three 8-bit words with the Linux Spi driver this will be reduced to around 41ksps (just under the standard audio sampling rate). The object of this analysis is to see whether our standard Linux, non real time, operating system is up to providing this degree of sampling delivery.
Figure 1.1 shows the results of sampling from the MCP3008 ADC. The y-axis shows the Sampling Integrity, defined as a percentage of the number of samples gathered in the test interval time to the expected number of samples to be observed during this time. The graph shows two plots.The red plot represents the MCP3008 sampling with a suitable delay function to provide the requested sample rate. The black plot represents the integrity of the delay function. For both plots, a sampling integrity of 100% implies that all of the expected events have been observed; in the language of real-time, all events have realised their deadline.

Figure 1.1: Sampling Integrity with the MCP3008 Analog to Digital Converter
The sampling test is performed with the spi_test executable, details of which are provided at:
https://github.com/MichaelMcGetrick/meta-stm32mp1-custom/tree/master/recipes-apps/spi_test.
We add
IMAGE_INSTALL:append = " spitest"
to the conf/local.conf file in the build directory.
To minimise code in the sampling loop (for example time keeping algorithms), flagging of the test time interval was provided by an interrupt signal from the DS3231 Real Time Clock running in alarm mode. A Device Tree alarm-device node was set up to configure the required hardware, as can be seen from the following patch file:
https://github.com/MichaelMcGetrick/meta-stm32mp1-custom/blob/master/recipes-kernel/linux/stm32mp1/0001-add-gpio-alarm-dts.patch
The alarm interrupt is processed by a dedicated alarm driver kernel module:
https://github.com/MichaelMcGetrick/meta-stm32mp1-custom/blob/master/recipes-alarm/alarm-mod/files/alarm_driver.c
To ensure we bake the module into the image, we add
IMAGE_INSTALL:append = " alarm-mod"
to the conf/local.conf file in the build directory.
The interrupt pin of the DS3231 is connected to GPIO pin PA8 on the STM32MP157F-DK2, and an interrupt handler configured for this pin in the alarm driver. When the kernel module interrupt function is triggered, it sends a flag to user space.
For sampling with the MCP3008, it is seen that after a sampling rate of around 100Hz, the sampling integrity begins to significantly fall. At a sampling rate of 3000Hz, the sampling integrity falls to ~55%. This means that, for a given time interval, half of the expected observations (events) have not been realised thus reducing the effective sampling rate to around 1500Hz.
The black plot shows the integrity of calls to the delay function (used to realise the required sample rate) only - i.e. sampling with the MCP3008 has been omitted. We also see significant degradation in the ability of the delay system calls to respond in the required time. At a sample rate of 3000Hz, the delay integrity has dropped to around 73%; in other words, around 25% of the required delays have not been scheduled. It is clear that both system delay algorithms and the SPI sampling process contribute to significant loss of sampling integrity.
To analyse the issue further, we have used a RIGOL oscilloscope to trace the chip select (CS) and Mosi SPI signals during fast looping - i.e. no system delays are put between spi sampling calls. Figure 1.2 shows the two signals - the yellow trace is chip select (CS) and the blue trace is the Mosi data line.

Figure 1.1: Chip Select and MOSI signals trace during fast looping
the CS trace shows that there is a time interval of around 200 microseconds between sample transfer calls. This provides an effective maximum sampling rate of around 5000Hz, as can be seen in Figure 1.3 where running spi_test in maximum sample rate mode shows a mximum sample rate of 5120.63Hz.

Figure 1.3: Maximum sampling rate attained during fast looping
Figure 1.2 show areas of significant latency. Firstly, around 55 microseconds of latency between the completion of the MOSI data transfer and when the CS line goes high. Secondly, the long inactive period of the CS line of around 100 microseconds before it is asserted again for the next spi transfer.
It is clear that a standard Linux OS is not adequate to attain high sampling rates of the order of 40ksps with the MCP3008. The ethos behind hybrid embedded systems is that real time requirements are left to the MCU side. However, before we look at the sampling ability of the on-board Cortex M4 MPU, it is worth checking out modifying standard Linux with the PREEMPT_RT patch. STM has provided the package add-on,
X-LINUX-RT
which we will consider in the next section.