I am currently working on the SD/MMC driver for CoFILOS.
During this time I figured out that there are some issues with the Mutex system, whih I will describe here.
FunkOS uses a driver structure that contains everything needed from the driver level. It mainly contains the standard FunkOS Driver entry point functions (Function Pointer to Init/Read/Write etc), a mutex entry and then custom data which are defined per each driver.
The Driver level is actually a wrapper of the actual driver functions that are called. There the common functionality required by the driver system is implemented. Then the function pointers call the actual work routines of the driver.
The mutex function is checked on the Driver level. Now as the mutex is stored on the driver structure, the mutex will work for two tasks if both tasks share the same driver structure. For example accessing the serial port with two tasks that share the serial port (not a very common scenario) means that both tasks should share the same structure. This might be fine for such applications with the drawback that both tasks share the driver structure. Who in this case does the initialization? There are some issues to be solved by the application.
However I do not believe this would be the common case of the drivers. Normally a single task access each device, so this is not a big problem.
Let’s see another example. The SPI interface supports multiple physical devices that may be accessed. The SPI bus itself is a common shared resource. Each SPI device may use different clock speeds and phase settings to work. I would expect in this case that each SPI device has its own Driver structure. Actually this is how the SPI driver is built in CoFILOS.
Now the common mutex scheme employed by FunkOS would not work, as the mutexes are inside each structure; This means a mutex lock will lock the specific driver’s mutex. Another task will still access the SPI as the mutex of this driver is not locked. This leads to the probably obvious solution to keep a driver internal common mutex to properly support mutlitasking.
The new implementation supports two different configuration of access. The first mode is the interleaved mode. There each task may access the SPI interface per transaction (read/write). So two tasks can execute transactions to two different devices. Each transaction though is locked, so we do not scramble the SPI input/output data.
However there are cases where we need to lock a complete transaction sequence. In this case the SPI driver through the Control function supports locking of sequences. In this case CS of this device should be manipulated by the task level itself. This could be modified to be done on the driver as well, but I have not decided if there is a need for handling CS from the task level. This scheme is used for the SD/MMC interfaces where the there is a requirement of series of actions, especially during the initialization phase.
TDD cannot completely cover the full testing of this sequence easily, I just created a primitive test to check critical sections and mutex claims, without actually checking the internal sequence. This is a risk I will take in order to reduce the development time, as my main task is the SD/MMC driver interface implementation.