Description
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
- setting pull-up configuration on output pins has minimal effect (output drivers override pull-ups).
- modifying
DIRCLR
andDIRTGL
registers updatesDIRSET
so it aligns withDIR
. - Testing shows
DIRSET
tracksDIR
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.