Perennial attachInterrupt in class / library problem.

Status
Not open for further replies.
Whilst researching solutions and looking at the best outcome for my project, I found this pull request for another Arduino core (STM32) which seems to address this issue.

I was wondering if perhaps a similar change would be entertained on the Teensyduino core to enable/facilitate this scenario, perhaps using some optional compilation defines to determine behaviour if there is any speed or memory impact.

The basic premise is to allow attachInterrupt to accept std:function<void(void)> in order to bind an object's method to an interrupt.

The pull request is https://github.com/stm32duino/Arduino_Core_STM32/pull/159 and the code changes are https://github.com/stm32duino/Arduino_Core_STM32/commit/baa22b033f5abf01e5dd9ddf8443e9b6d1ac64c8
(not mine)

I don't know how similar or how much work it would take to make these changes but I can see it making life a lot easier for some library writers and enable code to be more compatible across target boards.
 
I'm not sure if this is the correct way to go... Static member functions (which have a fixed base address during compile time) might already be used for attachInterrupt(). Non static member functions (whose base address might or might not be known at compile time, depending on their creation with new()) can be put in a static wrapper function. Thus, why touch at a running system?
 
This change would be to allow both static global functions as well as non-static member functions. The issue I have is I have a component on i2c which I am writing a library for. As there are multiple configurable addresses, the consumer may have 1 or up to 8 or even more on multiple i2c busses or via a multiplexor. As each device has an (optional in this case) interrupt pin the consumer would have to write many static isr hookup functions linking each pin interrupt to a specific instance.
Alternatively the begin function on the class can be void begin(TwoWire * wire, uint8_t intPin = 0)
And then the library can attach the interrupt to the appropriate instance.
 
I need to learn more about the low-level mechanics of what std:function really does. How many bytes of memory is it? Must be at least 8, right? Or more? How does its overhead compare? How much will it increase latency from interrupt event to the function's first instruction executing?

These are sort of rhetorical questions. I really need to give this stuff a try and look at the generated asm. But if anyone knows, please feel free to chime in. I'm curious about the actual generated assembly code and memory allocation, not so much the C++ language semantics (which look great, except there's notices about some forms going away in C++17....)
 
For reference, the ESP8266 core also has functional interrupts:
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/FunctionalInterrupt.cpp
It appears to have been added here: https://github.com/esp8266/Arduino/commit/ba0e049b83a7d012c857c3c25c0b148a76fd17a1
I am not sure about memory usage, or what latency is added by handling the different interrupt types, but maybe this can help?

For now I have ifdefs around TEENSYDUINO that include messages about manual hookup of interrupts and disable the auto attach in my library but it is not ideal.

In my case I am not doing anything which has major timing issues around interrupts, and perhaps the additional code/memory usage could be disabled by default but enabled by a define or even a board type option?
I am not entirely sure how those all work...
 
I still have huge difficulties in understanding the need of (pin) interrupts together with I2C. On one bus 127 devices can be fit (or even more with extended adressing) and each one can be a master and send data over the same bus without using interrupts to a Teensy which configured as a slave would collect and process the data.
 
I'm not talking about multi-master systems; I'm talking about sensors etc. such as magnetometers, Gyroscope/IMUs, GPS devices, ADCs, temp sensors etc. which often have either data ready or threshold crossed interrupts (or both).
If I have e.g. MCP9808 devices around a system, with temp thresholds setup and set with different addresses. The library might read the temp, allow setting the threshold, and record the date/time the threshold was crossed (perhaps with callbacks if the temp was past the temp for a period of time).
There are many, many other such uses. In an IoT world, you would probably not be continually polling and running in deep sleep if possible. In the case of a Teensy you might be recording to SD card. On an ESP8266 you might be logging via WiFi to the cloud. But the point is to have a library which can drop in on any core platform.
 
Thank you for explaining this to an old fart like me. I had my first I2C training course by a Philips engineer around 1992. They told us that the basic premise of I2C was reducing the wiring by having up to 127 devices connected by just 2 common wires. From this point of view, I find it still highly inefficient to have one extra wire per device which sounds highly contradictory to the idea of a pure serial data bus. These sensors you cite, why are these not smart enough to act as master by themselves so that they could take over the bus instead of using a separate data ready signal?
 
Edit: this case I'm mentioning seems to be different from the one described above, but it does exist within the Wire lib...

I still have huge difficulties in understanding the need of (pin) interrupts together with I2C.

Earlier Kinetis chips lacked the STOPF and SSIE bits in their I2Cx_FLT registers. This is needed when receiving unknown length data in I2C slave mode, which the Wire library supports. As a workaround, I used the pin change interrupts to detect the stop condition.

This code isn't needed and isn't compiled for the newer chips with the STOPF and SSIE bits. Even on the older chips, it's only used for slave mode, and only enabled very briefly.

Yes, it is an ugly workaround, but it was the only way to fully support every feature of the Arduino Wire library on the older chips.
 
For now I have ifdefs around TEENSYDUINO that include messages about manual hookup of interrupts and disable the auto attach in my library but it is not ideal.

FWIW, I am very seriously considering this change. But I want to spend some time really looking into the low-level details before I commit it. Even if I do it, for a while it'll only be on github...

We just released 1.42 last week, so it's (probably) going to be a while until a 1.43 release. My goal has been a new release every ~3 months, or of course whenever Arduino makes a new stable release. We went almost 5 months between 1.41 to 1.42, mostly due to the difficulty of debugging the ports menu change on all 3 systems (but mostly Windows).

Unless Arduino surprises us with 1.8.6, the next non-beta Teensyduino release is scheduled for sometime around mid-September.
 
Status
Not open for further replies.
Back
Top