digitalReadFast & digitalWriteFast on LC

Status
Not open for further replies.

nox771

Well-known member
I just ran into something here, are digitalReadFast() and digitalWriteFast() compatible with LC ?

I had a small piece of code which used these and sometimes I got this compile error:
C:\Users\Brian\AppData\Local\Temp\ccS1gvqR.s: Assembler messages:
C:\Users\Brian\AppData\Local\Temp\ccS1gvqR.s:2029: Error: lo register required -- `sub ip,#1'

Wierd part is in trying to localize it, by removing some surrounding commands the error would go away. I'm guessing this has something to do with memory alignment.

Once I converted the digitalWriteFast() operations to digitalWrite() (and similar for Read) the error went away.
 
I've not seen that - my use was mostly limited to this, but in about every sketch I do on LC or 3.1:
#define qBlink() (digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) ))
with:
void setup() {
...
pinMode(LED_BUILTIN, OUTPUT);
... }

Then just use qBlink() willy nilly in the sketch.

There is special compile time treatment (I read ?) that when used with a constant (like above) then specific code is used that is hardcoded to a port. So this might act differently if you wanted to test the following. I just put this in an LC OLED1306 sketch and it compiles and works - also added qBlinkX() for pins 6 and 14 that I see blink as expected after error free compile.

#define qBlinkX( x ) (digitalWriteFast(x, !digitalReadFast(x) ))

int xx = LED_BUILTIN + 10;

loop(){ ...
qBlinkX( xx -10 );
...}
 
Ok, here is a test case. Can someone dump this in a sketch and tell me if it compiles? I'm using Arduino 1.6.3 and Teensyduino 1.22.

The code is nonsense - it's a reduced segment of a function I'm working on. I've reduced it to this, but beyond this if I change almost anything it will compile. As-is I get the following error:

C:\Users\Brian\AppData\Local\Temp\cc8yhx2d.s: Assembler messages:
C:\Users\Brian\AppData\Local\Temp\cc8yhx2d.s:175: Error: lo register required -- `sub ip,#1'
Error compiling.

Code:
void setup() {
}

void loop() {
}

struct A
{
    volatile uint8_t S;
};

void function(struct A* a, uint8_t b)
{
    uint8_t c=0, d=0, count=0;

    switch(b)
    {
    case 1:
        c = 18;
        d = 19;
        break;
    case 2:
        c = 17;
        d = 16;
        break;
    }
    if(c && d)
    {
        pinMode(c,((b == 1) ? INPUT : INPUT_PULLUP));
        digitalWriteFast(d,HIGH);
        pinMode(d,OUTPUT);

        while(digitalReadFast(c) == 0 && count++ < 9)
        {
            digitalWriteFast(d,LOW);
            delayMicroseconds(5);       
            digitalWriteFast(d,HIGH);
            delayMicroseconds(5);
        }
        a->S = 5; 
    }
}

I know nothing about disassembling ARM code, so I can't tell what part of the code is generating that bad opcode.

EDIT: I forgot to mention - this is for compiling for LC specifically. This compiles for a T3.1.
 
Last edited:
Indeed the posted code fails with a compile to LC when "NOT" optimized, but goes fine when 'optimized' and compiled for 3.1.

Paul needs to see this - something odd is happening in the compiler. If I recall what I read as noted - there is pre-processing on this writeFast and something is confusing it or perhaps general optimization.

The problem is the first WriteFast, and goes away if I add the post++ increment as shown. The error returns if I add a [--d;] decrement for the next line, so the compiler may be optimizing it out.

Code:
        while(digitalReadFast(c) == 0 && count++ < 9)
        {
            digitalWriteFast(d++,LOW);
            delayMicroseconds(5);       
            digitalWriteFast(d,HIGH);
            delayMicroseconds(5);
        }

I added a transfer to 'uint8_t f' and it still failed when I f=d; until I did the following:
Code:
            f=--d;
            digitalWriteFast(++f,LOW);

It never errors on the 'digitalWriteFast(d,HIGH);', but writing HIGH in the first line still fails.

NOTE: Swapping the top two lines in the while for the lower two HIGH>LOW instead of LOW>HIGH has the same bad result but moving the delay as follows makes it work, but just adding a third delay as the first line in the while still breaks the same.

Code:
        while(digitalReadFast(c) == 0 && count++ < 9)
        {
            delayMicroseconds(5);
            digitalWriteFast(d,LOW);
            delayMicroseconds(5);       
            digitalWriteFast(d,HIGH);
        }
 
Last edited:
I agree, I think this is some kind of compiler bug, I suspect something related to it being an M0 core.

The difficult part is I can't tell what part of the code is triggering the problem. If I knew I would just avoid that. Sometimes rearranging the commands I can get it to compile. I did some searches and ran into a similar bug involving the 'volatile' keyword, but removing the volatile off the struct variable does nothing, so it's not that.

In my original code changing the "Fast" routines to the normal routines did the trick, so perhaps something to do with the arguments like you were doing. That also fixes it on this code, which is why my original question was about those "Fast" routines.
 
I just removed the whole switch before the while, leaving just two assignments and that stopped the error as well - as did moving the switch after the while - so it may just be a general snafu - not FastWrite specific.

My first thought when I saw your empty loops and setup was the compiler might dismiss/confuse the uncalled code. That code I assume was part of a real program and was just paired down to minimize the sample.

There is some optimizing at hand that should show in the ASM looking at one or more of these cases showing what the compiler spits out. Not sure how that resolves to a solution . . . will be interesting to see.
 
Status
Not open for further replies.
Back
Top