I have an Arduino program to control X-10 using Thomas Mittet's X-10 library:
github.com/tmittet/x10/
This works using the Arduino 1.6.4 IDE but I'd like to update to 1.6.12. It doesn't want to play.
My c++ is pretty, well, sketchy but I've narrowed the problem down to a section in the x10ex.h include file where the library declares a volatile array of struct items, which is used to hold the message buffer and persist it between calls to the interrupt service routine.
I sort of understand what the volatile keyword is there for -
Essentially, the compiler will assume the Arduino is able to hold a value unchanged in a register for at least a reasonable period of time. It uses this assumption to streamline the code, working with copies of values in a register as a sort of cache rather than reloading from main memory all the time. If an interrupt happens, though, and the routine that services the interrupt makes a change to that value in the main memory then that assumption doesn’t hold. The volatile keyword tells the compiler to assume that any copy of this value that happens to be in a register is suspect and has to be re-read from main memory any time it’s needed.
Since the X-10 transmit and receive code is entirely interrupt-driven it’s pretty easy to see why volatile variables would make sense.
I've stripped everything down to about the smallest chunk of code that still demonstrates the problem - so don't pull me up on the fact that the volatile keyword is completely pointless in the code below! I really just need to understand what is wrong with this so I can apply it to the real use case.
/************************************************************************/
/* */
/* Code to demonstrate problem with in Arduino IDE 1.6.12 */
/* when using volatile keyword as defined in */
/* */
/* X10 PLC library test sketch with Serial support, v1.6. */
/* */
/* Written by Thomas Mittet (code@lookout.no) June 2012. */
/************************************************************************/
#define X10_BUFFER_SIZE 17
// Used when buffering messages
struct X10msg
{
uint32_t message;
uint8_t repetitions;
};
class X10ex
{
public:
X10ex();
// Public methods
void begin();
private:
/************************************************************************/
/* */
/* The Problem: */
/* */
/************************************************************************/
X10msg volatile sendBf[X10_BUFFER_SIZE];
// X10msg sendBf[X10_BUFFER_SIZE];
};
X10ex::X10ex()
{}
//////////////////////////////
/// Public
//////////////////////////////
void X10ex::begin()
{}
X10ex x10ex = X10ex();
void setup() {}
void loop() {
// put your main code here, to run repeatedly:
}
Using the (commented) non-volatile declaration instead of the volatile one it compiles fine. In the real use-case of course I get problems which I'm attributing to this value changing during the interrupt service routine. Using the volatile version I get the error report:
Test_volatile:41: error: use of deleted function 'X10ex::X10ex(X10ex&&)'
X10ex x10ex = X10ex();
^
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:19:7: note: 'X10ex::X10ex(X10ex&&)' is implicitly deleted because the default definition would be ill-formed:
class X10ex
^
Test_volatile:19: error: no matching function for call to 'X10msg::X10msg(volatile X10msg)'
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:19:7: note: candidates are:
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: X10msg::X10msg()
struct X10msg
^
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: candidate expects 0 arguments, 1 provided
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: constexpr X10msg::X10msg(const X10msg&)
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: no known conversion for argument 1 from 'volatile X10msg' to 'const X10msg&'
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: constexpr X10msg::X10msg(X10msg&&)
C:\Users\Phil\Documents\Arduino\Test_volatile\Test_volatile.ino:13:8: note: no known conversion for argument 1 from 'volatile X10msg' to 'X10msg&&'
exit status 1
use of deleted function 'X10ex::X10ex(X10ex&&)'
The original author seems to have gone quiet on his blog but a couple of other people seem to have hit the same problem.
So - can anyone tell me what's changed between 1.6.4 and 1.6.12 to exhibit this problem? Can anyone supply the correct workaround?
If you want more detail on what I'm up to I have a blog article on this you can check out - but it really shouldn't be necessary to understand the problem. If you're interested:
hypercene.wordpress.com/2016/11/02/x10-ding-mysensors/