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:
https://github.com/tinygo-org/drivers/issues/540
This commit is contained in:
Ayke van Laethem
2023-05-26 17:28:04 +02:00
committed by Ron Evans
parent f366cd53b7
commit b7b23ace3f
+8 -4
View File
@@ -46,10 +46,14 @@ func init() {
// Return the register and mask to enable a given GPIO pin. This can be used to
// implement bit-banged drivers.
func (p Pin) PortMaskSet() (*uint32, uint32) {
// Note: using PORT_IOBUS for faster pin accesses.
// The regular PORT registers appear to take around 4 clock cycles to store,
// which is longer than the ws2812 driver expects. The IOBUS is is fast
// enough to avoid this issue.
if p < 32 {
return &sam.PORT.OUTSET0.Reg, 1 << uint8(p)
return &sam.PORT_IOBUS.OUTSET0.Reg, 1 << uint8(p)
} else {
return &sam.PORT.OUTSET1.Reg, 1 << uint8(p-32)
return &sam.PORT_IOBUS.OUTSET1.Reg, 1 << uint8(p-32)
}
}
@@ -57,9 +61,9 @@ func (p Pin) PortMaskSet() (*uint32, uint32) {
// implement bit-banged drivers.
func (p Pin) PortMaskClear() (*uint32, uint32) {
if p < 32 {
return &sam.PORT.OUTCLR0.Reg, 1 << uint8(p)
return &sam.PORT_IOBUS.OUTCLR0.Reg, 1 << uint8(p)
} else {
return &sam.PORT.OUTCLR1.Reg, 1 << uint8(p-32)
return &sam.PORT_IOBUS.OUTCLR1.Reg, 1 << uint8(p-32)
}
}