-
-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interrupt safe? #8
Comments
nothing is interrupt safe, you should design your code to be interrupt safe while using libraries like this |
The library should be able to support you in writing interrupt safe code, but please be aware interrupts are not threads. The following code should work adding items into the buffer within the ISR and removing them from within the CircularBuffer<volatile long,10> times;
void setup() {
Serial.begin(9600);
Serial.print("buffer size is "); Serial.println(times.size());
attachInterrupt(digitalPinToInterrupt(2), count, RISING);
}
long time = 0;
void loop() {
Serial.print("buffer count is "); Serial.println(times.count());
delay(250);
if (millis() - time >= 10000 && !times.isEmpty()) {
Serial.print("popping "); Serial.println(times.pop());
time = millis();
}
}
void count() {
times.unshift(millis());
} Please consider I didn't test this code, yet... |
@chaeron have you the opportunity to check the proposed code? |
I've added a feature branch called |
adding volatile can affect performance, but at a very miniscule level. Fact remains is the tail and head are being separately accessed, and so are their slots, so if ones writing to tail and other removing from head, there shouldnt be any issues within the ISR I designed a circular buffer system that runs up against 30mhz SPI bus between 2 microcontrollers exchanging 100 dword data at 250uS intervals through the queue system which ive set to 8 slots. considering the queue system is dual purpose (ring buffer and array queueing), the SPI interface is transferring data over queue array system rather than a ring buffer implementation, without the hindering of the volatility, and able to achieve 5000Hz message transfers at those bus speeds of 100dwords |
@tonton81 is this library at the core of your bus? The |
yes sir, its the main buffer, theres 2 array versions for 2-way traffic, got no misses or failures at those speeds :) |
yes, count, available should be available, but you could also make them std::atomic, which wouldnt need to be volatiled, as it handles the variable atomically. during the ISR interactions with my library, honestly, on a teensy a volatile bool or volatile uint8_t.... didnt work, because they are not native types like uint32 on arm, so the software has to handle the conversion. during the SPI transfers, bool, uint8_t, even with volatile, did NOT work. uint16_t and uint32_t DID, but i omitted them and went with the std::atomic, never failed! perhaps you should use std::atomic<uint16_t> for your count/available, they work great in ISRS. and dont even bother with mutexes in isrs, youll deadlock always :) |
I don't think Apart from an error I just spotted on the In other words the switchable If you can confirm that, not only I'm willing to add the pre-processor switch, but I will also improve the documentation adding this precious bit of information for the Teensy (does it apply to other processors? what is the Teensy mcu?). BTW, are you willing to contribute the changes yourself, so to leave a more prominent trace of your valuable help? |
std::atomic is part of STL you need only #include , it should be in the arduino core (no download necessary), its definately in teensy core. I just wanted to report my findings on the SPI ISR how volatile bool and uint8_t failed during the 190uS timed transfers at ~51uS transfers and processing time inclusive. I know you want to maintain portability but yours could work fine for mcus that are 8bits (avrs), but on 32bit arms, they have to do extra processing to return the registers (volatile) that are not native 32bit writes, which is why the 16/32 primitives worked but bool/U8 failed during my tests even though they were volatile. testing was done on a T3.2, T3.5, and T3.6. but yeah volatile 16 and volatile 32 work on teensy, but atomics are usually preferred over volatiles anyways, and dont need to define them as volatile either :) |
#include atomic github removed the brackets around atomic sorry |
i just tried changing my volatile uint16_t (head,tail,_available) to std::atomic<uint16_t>, unfortuneately i cant convert mine without rewriting methods to support it, compiler complaining because some of my methods dont match, but i would just stick to volatile uint16_t for the count, head, and tail, to be safe amongst many microcontrollers without the need to sprinkle ifdefs everywhere, keeping uint8_t volatile seems to be an issue with teensy, or perhaps ARM controllers, as the data is not accessed atomically. So, even with 8bit mcus, i think you should still keep uint16_t and not use a switch feature, for clarity and perhaps, people prefer to store more than 255 entries |
I agree that's why The flag name I've picked might be misleading though The |
INT_SAFE seems good, i dont think there are other words for it |
No STL on small embedded systems please :) |
I've added the |
Is this implementation interrupt safe?
That is, if you add items in the interrupt handler and remove them in the main loop, will things work correctly?
Thanks!
The text was updated successfully, but these errors were encountered: