Skip to content

Bug: digitalWrite() incorrectly uses DIRSET register instead of DIR register for pin direction checking #727

Open
@jacoblgit

Description

@jacoblgit

Bug Description

The current implementation of digitalWrite() in the SAMD core incorrectly uses the DIRSET register to determine if a pin is configured as an output, which could lead to inconsistent behavior.

Technical Details

In wiring_digital.c, the function uses the following condition to check if a pin is configured as an output:

if ((PORT->Group[port].DIRSET.reg & pinMask) == 0)
{
  // the pin is not an output, disable pull-up if val is LOW, otherwise enable pull-up
  PORT->Group[port].PINCFG[pin].bit.PULLEN = ((ulVal == LOW) ? 0 : 1);
}

However, according to the SAMD21 datasheet (section 23.8.3), DIRSET is designed to be a write-only register and does not guarantee it matches actual pin direction state. This will cause the function to sometimes incorrectly attempt configuring pull-up resistors even on pins configured as outputs.

Proposed Fix

Replace the DIRSET check with a DIR check, which correctly reflects the current pin direction state:

if ((PORT->Group[port].DIR.reg & pinMask) == 0)
{
  // [rest of the code unchanged]
}

Impact Assessment

This bug has likely been present for some time without causing major functional issues, because

  1. setting pull-up configuration on output pins has minimal effect (output drivers override pull-ups).
  2. modifying DIRCLR and DIRTGL registers updates DIRSET so it aligns with DIR.
  3. Testing shows DIRSET tracks DIR even under circumstances not guaranteed by the datasheet

While not a high impact issue, it's technically incorrect and could potentially cause subtle issues in certain edge cases or confuse developers examining the behavior of the function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions