Skip to content

Commit b7b23ac

Browse files
aykevldeadprogram
authored andcommitted
samd21: fix issue with WS2812 driver
The regular port access is around 4 cycles, instead of the usual 2 cycles for a store instruction on Cortex-M0+. The IOBUS however is faster, I didn't measure exactly but I guess it's 2 cycles as expected. This fixes a bug in the WS2812 driver that only happens on samd21 chips: tinygo-org/drivers#540
1 parent f366cd5 commit b7b23ac

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

src/machine/machine_atsamd21g18.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,24 @@ func init() {
4646
// Return the register and mask to enable a given GPIO pin. This can be used to
4747
// implement bit-banged drivers.
4848
func (p Pin) PortMaskSet() (*uint32, uint32) {
49+
// Note: using PORT_IOBUS for faster pin accesses.
50+
// The regular PORT registers appear to take around 4 clock cycles to store,
51+
// which is longer than the ws2812 driver expects. The IOBUS is is fast
52+
// enough to avoid this issue.
4953
if p < 32 {
50-
return &sam.PORT.OUTSET0.Reg, 1 << uint8(p)
54+
return &sam.PORT_IOBUS.OUTSET0.Reg, 1 << uint8(p)
5155
} else {
52-
return &sam.PORT.OUTSET1.Reg, 1 << uint8(p-32)
56+
return &sam.PORT_IOBUS.OUTSET1.Reg, 1 << uint8(p-32)
5357
}
5458
}
5559

5660
// Return the register and mask to disable a given port. This can be used to
5761
// implement bit-banged drivers.
5862
func (p Pin) PortMaskClear() (*uint32, uint32) {
5963
if p < 32 {
60-
return &sam.PORT.OUTCLR0.Reg, 1 << uint8(p)
64+
return &sam.PORT_IOBUS.OUTCLR0.Reg, 1 << uint8(p)
6165
} else {
62-
return &sam.PORT.OUTCLR1.Reg, 1 << uint8(p-32)
66+
return &sam.PORT_IOBUS.OUTCLR1.Reg, 1 << uint8(p-32)
6367
}
6468
}
6569

0 commit comments

Comments
 (0)