Arduino Due and IDE 1.5.3 digitalRead() BUG

tl;dr Set your pin as an input some time before you set your pin as an output. Do a pinMode(, INPUT); pinMode(, OUTPUT);

On a Due, when you try to do a digitalRead on a pin that is configured as an OUTPUT with pinMode, it will always return 0. The bug resides in hardware/arduino/sam/cores/arduino/wiring_digital.c.

According to the SAM3X datasheet, in order to read pin states the peripheral clock must be enabled. By default this is not done when setting a pin to an OUTPUT. In fact, as can be seen below in the OUTPUT case in pinMode the clock is actively turned off to save power if all of the pins for that peripheral are set as outputs.

case OUTPUT:
            PIO_Configure(
             g_APinDescription[ulPin].pPort,
             PIO_OUTPUT_1,
             g_APinDescription[ulPin].ulPin,
             g_APinDescription[ulPin].ulPinConfiguration ) ;

            /* if all pins are output, disable PIO Controller clocking, reduce power consumption */
            if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff )
            {
                pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
            }

I'm all for saving power, but since this is a prototyping platform, I think I'd rather have the functionality first.

For the curious people looking for a temporary workaround, you can sorta-kinda fix it properly by pasting the line below in between the case OUTPUT: and PIO_Configure(

/* Enable peripheral clock for digitalRead() */
pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;

so it reads like

case OUTPUT:
            /* Enable peripheral clock for digitalRead() */
            pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
            PIO_Configure(
             g_APinDescription[ulPin].pPort,
             PIO_OUTPUT_1,
             g_APinDescription[ulPin].ulPin,
             g_APinDescription[ulPin].ulPinConfiguration ) ;

            /* if all pins are output, disable PIO Controller clocking, reduce power consumption */
            if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff )
            {
                pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
            }

If you're going to be using a ton of outputs, you'd probably also do yourself a favor and remove the last four lines, the if statement, from the above code block as well.

If you just want a quick hack, it also works to just set your pin to an input then immediately set it to an output if your circuit allows it. See the tl;dr at the top of this page. It works because setting a pin to an INPUT turns on the peripheral clock in pinMode for the INPUT and INPUT_PULLUP cases so the SAM3X can read inputs correctly. It seems to only get turned off if all of the pins on a port are set as outputs.

I'll see about submitting a pull request for this issue this weekend and see if the maintainers will accept it.

While I'm thinking about it, is there some method to do some power saving for this thing if I want to force the issue? A library or something? If not, maybe I'll look into writing one so you can save power if you really wanna.

I'm so NOT impressed that Arduino libraries are built on top of ASF :frowning:

This bug continues to exist in the Arduino IDE 1.5.6-r2. Any chance to fix it in the near future versions? Thank you,

p

Sooooooooon.....