OpenMetBuoy-v2021a
OpenMetBuoy-v2021a copied to clipboard
peripherals manager
@gauteh I am building now something I felt I mess in the previous version of the buoy - a way to keep track of whether a peripheral is in use or not, to talk to which devices, and how this knowledge should be used to swith the peripheral on / off.
This is what I am implementing here:
https://github.com/jerabaul29/OpenMetBuoy-v2021a/blob/feat/platformio-tracker-add-peripheral-manager/tracker/lib/peripheral_manager/peripheral_manager.h
https://github.com/jerabaul29/OpenMetBuoy-v2021a/blob/feat/platformio-tracker-add-peripheral-manager/tracker/lib/peripheral_manager/peripheral_manager.cpp
If you have any comments / criticisms / thoughts etc, as usual will be happy to hear, but as usual no problem if you are too busy to look at it :) .
This is a bit similar to a bus manager, or shared_bus
in rust (but without the power management of the device). You probably have to assume that the PeripheralManager or BusManage(?) will be used from multiple threads, so it needs to use a cortex-m mutex (essentially using interrupt_free context), see the shared-bus source code.
One way to do this is to wrap the I2C device in the BusManager, then you can hand out new leases to it to each device and the bus manager will synchronize their access. Both sharing the I2C bus and doing power-management at the same time might complicate the design, maybe it should be two split in two concepts?
Many thanks for the comments :) . I think I will work with the hypothesis that it is single threaded so far :) . When not using a RTOS the code is single threaded except for the interrupts, and this is not some operations that should be done from within an interrupt. What do you think?
Yeah. Just reading from the same I2C bus in an interrupt - say sampling the IMU from RTC or new-sample-interrupt will be unsafe unless you sync the bus access.
Right, I had not thought about that, thanks. I will think a bit extra about it. My idea originally was to use this manager to only keep track of switching things on and off, but I see what you mean. Thanks! :)
This is really interesting - I am so used to the arduino way of thinking, where we do "everything" in a single thread, and interrupts are not used for "hidden multithreading", that I forget that such things can happen ^^ :) .
I have one worry, and it is that, given that I use arduino libraries that are often quite "low quality" / not thought for ISR driven mutlithreading, if I start doing things more complex than updating a counter from an ISR (like, if I communicate with a device on I2C / SPI from within an interrupt), things will likely break (like, getting stuck in an ISR, because it relies on some delay that is implemented using an ISR, or something like this). So I think I will avoid doing stuff like reading a device from an ISR, and instead have my own hand-engineered "event loop" of some kind. This is a poor man's fix, but I think I am stuck there as long as I remain in the arduino ecosystem - and I think alternatives are not fully mature yet, and anyways I do things that go quite slow, so arduino ecosystem is good enough to me so far :) . But many thanks, will keep it in head.
I will update the documentation to make this clear :) .
Actually, the library for the 6dof for example looks very good; I think I will implement what you suggest here, as there should be no issues using the library from withing an ISR triggered context.
So what I plan would be to implement things so that:
- to use the port, you have to "loan it",
- the port "loaning" is protected by i) disabling interrupts, ii) a mutex; this way, cannot be used by 2 separate threads, and cannot jump in an interrupt / "hidden thread" either, as this would block things up - i.e. avoid no more progress in the first thread that is holding the mutex, and no progress in the ISR that is trying to get the mutex.
I have to think if I create 2 methods (loan and give_back), or if I build an additional object to do RAII.
Anything I am missing @gauteh ? :) (and thank you again for your patience and explanations :) ).
If you are the sole owner (own with mutability in rust) you don't need to protect it with the mutex (that is you have no other devices on the same I2C bus, and can pass it to the ISR). Otherwise Mutex (implemented using interrupt guards) works!