arduino / arduino/ArduinoCore-samd

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

Open Beginner friendly
#727 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
502
Forks
740
PR merge metrics
No merged PRs in 30d

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:

```c
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:
```c
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.

Contributor guide

No contributing guide indexed for this repository

Research direction

Open wiring_digital.c and inspect digitalWrite(), then read SAMD21 datasheet section 23.8.3 to compare DIRSET with DIR. The change is complete when the output-direction check uses the register that reflects current pin direction and the existing behavior remains unchanged for pull-up handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.