-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Best practices for adding SPI and I2C code to a driver? #13208
Description
Description
I have added working SPI support for the lpsxxx driver and would like to share it. However, looking at the drivers that have SPI as well as I2C support at the moment, I found the following:
- bmx280 (last relevant modification: 10.01.2019)
- lis2dh12 (last relevant modification: 23.01.2018)
- pn532 (last relevant modification: 29.08.2017)
The bmx280 and lis2dh12 drivers rely on defines, that put the driver into either SPI or I2C mode. (BMX280_USE_SPI and MODULE_LIS2DH12_SPI). The code that routes the calls to SPI or I2C is completely split and compiled in, depending on the defines.
The pn532 driver uses 2 defines (PN532_SUPPORT_I2C and PN532_SUPPORT_SPI) for routing the bus communication to I2C or SPI. The code that routes the calls to SPI or I2C is the same, but splits up at the point where a low-level I2C or SPI call gets done, using the defines. i.e. One implementation with may 'defined' checks.
The bmx280, lis2dh12 and pn532 drivers can only operate in one of the 2 modes, which is determined at compile time.
The way that I implemented I2C and/or SPI for the lpsxxx, relies on setting up function pointers for the routing the bus functions to either SPI or I2C, based on driver parameters, at startup (not compile time). This means that a board can have more than one of the same sensors, connected via SPI or I2C. However, I can't think of any hardware, other than test setups, that might want this. A major advantage however, is that the I2C and SPI code can be re-used by different sensors. i.e. The SPI/I2C implementation is only done once, so much less code maintenance.
The function pointer solution however has a slight code space and minute, calling overhead. I have not got hard figures on this yet, as I first wanted to find out if this kind of implementation makes sense.
Questions
- Will a function pointer type solution for pivoting between I2C and SPI implementations, as described above, be useful for RIOT?
- Are there any best-practice way of implementing SPI and I2C for a single driver, in RIOT?
Useful links
BTW, I happened to stumble accross the following. If this is related, it should also be keep in mind:
RIOT/drivers/include/net/netdev.h
Lines 51 to 62 in c5dfc7d
| * The peripheral drivers for shared buses (i.e. SPI and I2C) implement access | |
| * synchronization using mutexes, which are locked and unlocked in the driver's | |
| * `require` and `release` functions. The problem is now, that this type of | |
| * synchronization does only work in thread context, but not in interrupt | |
| * context. With reasonable effort and resource usage, we have no means of | |
| * synchronizing the bus access also in interrupt context. | |
| * | |
| * The solution to this problem as implemented by this interface is **not to | |
| * call any function that interacts with a device directly from interrupt | |
| * context**. Unfortunately this requires some added complexity for | |
| * synchronization efforts between thread and interrupt context to be able to | |
| * handle device events (i.e. external interrupts). See section |