Browse Source

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
pull/3757/head
Ayke van Laethem 1 year ago
committed by Ron Evans
parent
commit
b7b23ace3f
  1. 12
      src/machine/machine_atsamd21g18.go

12
src/machine/machine_atsamd21g18.go

@ -46,10 +46,14 @@ func init() {
// Return the register and mask to enable a given GPIO pin. This can be used to // Return the register and mask to enable a given GPIO pin. This can be used to
// implement bit-banged drivers. // implement bit-banged drivers.
func (p Pin) PortMaskSet() (*uint32, uint32) { 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 { if p < 32 {
return &sam.PORT.OUTSET0.Reg, 1 << uint8(p) return &sam.PORT_IOBUS.OUTSET0.Reg, 1 << uint8(p)
} else { } 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. // implement bit-banged drivers.
func (p Pin) PortMaskClear() (*uint32, uint32) { func (p Pin) PortMaskClear() (*uint32, uint32) {
if p < 32 { if p < 32 {
return &sam.PORT.OUTCLR0.Reg, 1 << uint8(p) return &sam.PORT_IOBUS.OUTCLR0.Reg, 1 << uint8(p)
} else { } else {
return &sam.PORT.OUTCLR1.Reg, 1 << uint8(p-32) return &sam.PORT_IOBUS.OUTCLR1.Reg, 1 << uint8(p-32)
} }
} }

Loading…
Cancel
Save