Browse Source

sam: return an error when an incorrect PWM pin is used

Previously it would trigger a nil pointer panic.
pull/1112/head
Ayke van Laethem 5 years ago
committed by Ron Evans
parent
commit
38fc340802
  1. 16
      src/examples/pwm/pwm.go
  2. 3
      src/machine/machine_atmega328p.go
  3. 40
      src/machine/machine_atsamd21.go
  4. 66
      src/machine/machine_atsamd51.go
  5. 3
      src/machine/machine_generic.go
  6. 3
      src/machine/machine_nrf52.go
  7. 4
      src/machine/machine_nrf52840.go

16
src/examples/pwm/pwm.go

@ -28,13 +28,16 @@ func main() {
machine.InitPWM()
red := machine.PWM{redPin}
red.Configure()
err := red.Configure()
checkError(err, "failed to configure red pin")
green := machine.PWM{greenPin}
green.Configure()
err = green.Configure()
checkError(err, "failed to configure green pin")
blue := machine.PWM{bluePin}
blue.Configure()
err = blue.Configure()
checkError(err, "failed to configure blue pin")
var rc uint8
var gc uint8 = 20
@ -52,3 +55,10 @@ func main() {
time.Sleep(time.Millisecond * 500)
}
}
func checkError(err error, msg string) {
if err != nil {
print(msg, ": ", err.Error())
println()
}
}

3
src/machine/machine_atmega328p.go

@ -79,13 +79,14 @@ func InitPWM() {
}
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() {
func (pwm PWM) Configure() error {
switch pwm.Pin / 8 {
case 0: // port B
avr.DDRB.SetBits(1 << uint8(pwm.Pin))
case 2: // port D
avr.DDRD.SetBits(1 << uint8(pwm.Pin-16))
}
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value. On the AVR this is normally a

40
src/machine/machine_atsamd21.go

@ -1090,9 +1090,12 @@ func InitPWM() {
}
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() {
func (pwm PWM) Configure() error {
// figure out which TCCX timer for this pin
timer := pwm.getTimer()
if timer == nil {
return ErrInvalidOutputPin
}
// disable timer
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@ -1139,12 +1142,19 @@ func (pwm PWM) Configure() {
val := pwm.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
pwm.setPMux(val | uint8(pwmConfig<<sam.PORT_PMUX0_PMUXE_Pos))
}
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value.
func (pwm PWM) Set(value uint16) {
// figure out which TCCX timer for this pin
timer := pwm.getTimer()
if timer == nil {
// The Configure call above cannot have succeeded, so simply ignore this
// error.
return
}
// disable output
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@ -1154,7 +1164,7 @@ func (pwm PWM) Set(value uint16) {
}
// Set PWM signal to output duty cycle
pwm.setChannel(uint32(value))
pwm.setChannel(timer, uint32(value))
// Wait for synchronization on all channels
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0 |
@ -1223,32 +1233,32 @@ func (pwm PWM) getTimer() *sam.TCC_Type {
}
// setChannel sets the value for the correct channel for PWM on this pin
func (pwm PWM) setChannel(val uint32) {
func (pwm PWM) setChannel(timer *sam.TCC_Type, val uint32) {
switch pwm.Pin {
case 6:
pwm.getTimer().CC0.Set(val)
timer.CC0.Set(val)
case 7:
pwm.getTimer().CC1.Set(val)
timer.CC1.Set(val)
case 8:
pwm.getTimer().CC0.Set(val)
timer.CC0.Set(val)
case 9:
pwm.getTimer().CC1.Set(val)
timer.CC1.Set(val)
case 14:
pwm.getTimer().CC0.Set(val)
timer.CC0.Set(val)
case 15:
pwm.getTimer().CC1.Set(val)
timer.CC1.Set(val)
case 16:
pwm.getTimer().CC2.Set(val)
timer.CC2.Set(val)
case 17:
pwm.getTimer().CC3.Set(val)
timer.CC3.Set(val)
case 18:
pwm.getTimer().CC2.Set(val)
timer.CC2.Set(val)
case 19:
pwm.getTimer().CC3.Set(val)
timer.CC3.Set(val)
case 20:
pwm.getTimer().CC2.Set(val)
timer.CC2.Set(val)
case 21:
pwm.getTimer().CC3.Set(val)
timer.CC3.Set(val)
default:
return // not supported on this pin
}

66
src/machine/machine_atsamd51.go

@ -1216,7 +1216,7 @@ const (
const period = 0xFFFF
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() {
func (pwm PWM) Configure() error {
// Set pin as output
sam.PORT.GROUP[0].DIRSET.Set(1 << uint8(pwm.Pin))
// Set pin to low
@ -1240,6 +1240,9 @@ func (pwm PWM) Configure() {
// figure out which TCCX timer for this pin
timer := pwm.getTimer()
if timer == nil {
return ErrInvalidOutputPin
}
// disable timer
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@ -1264,7 +1267,7 @@ func (pwm PWM) Configure() {
// Set the initial value
// TCCx->CC[tcChannel].reg = (uint32_t) value;
pwm.setChannel(0)
pwm.setChannel(timer, 0)
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0) ||
timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC1) {
@ -1282,12 +1285,19 @@ func (pwm PWM) Configure() {
// Wait for synchronization
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_ENABLE) {
}
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value.
func (pwm PWM) Set(value uint16) {
// figure out which TCCX timer for this pin
timer := pwm.getTimer()
if timer == nil {
// The Configure call above cannot have succeeded, so simply ignore this
// error.
return
}
// Wait for synchronization
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CTRLB) {
@ -1297,7 +1307,7 @@ func (pwm PWM) Set(value uint16) {
}
// TCCx->CCBUF[tcChannel].reg = (uint32_t) value;
pwm.setChannelBuffer(uint32(value))
pwm.setChannelBuffer(timer, uint32(value))
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0) ||
timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC1) {
@ -1329,61 +1339,61 @@ func (pwm PWM) setPinCfg(val uint8) {
pwm.Pin.setPinCfg(val)
}
// setChannel sets the value for the correct channel for PWM on this pin
func (pwm PWM) setChannel(val uint32) {
// setChannel sets the value for the correct channel for PWM on this pin.
func (pwm PWM) setChannel(timer *sam.TCC_Type, val uint32) {
switch pwm.Pin {
case PA16:
pwm.getTimer().CC[0].Set(val)
timer.CC[0].Set(val)
case PA17:
pwm.getTimer().CC[1].Set(val)
timer.CC[1].Set(val)
case PA14:
pwm.getTimer().CC[0].Set(val)
timer.CC[0].Set(val)
case PA15:
pwm.getTimer().CC[1].Set(val)
timer.CC[1].Set(val)
case PA18:
pwm.getTimer().CC[2].Set(val)
timer.CC[2].Set(val)
case PA19:
pwm.getTimer().CC[3].Set(val)
timer.CC[3].Set(val)
case PA20:
pwm.getTimer().CC[0].Set(val)
timer.CC[0].Set(val)
case PA21:
pwm.getTimer().CC[1].Set(val)
timer.CC[1].Set(val)
case PA23:
pwm.getTimer().CC[3].Set(val)
timer.CC[3].Set(val)
case PA22:
pwm.getTimer().CC[2].Set(val)
timer.CC[2].Set(val)
case PB31:
pwm.getTimer().CC[1].Set(val)
timer.CC[1].Set(val)
default:
return // not supported on this pin
}
}
// setChannelBuffer sets the value for the correct channel buffer for PWM on this pin
func (pwm PWM) setChannelBuffer(val uint32) {
func (pwm PWM) setChannelBuffer(timer *sam.TCC_Type, val uint32) {
switch pwm.Pin {
case PA16:
pwm.getTimer().CCBUF[0].Set(val)
timer.CCBUF[0].Set(val)
case PA17:
pwm.getTimer().CCBUF[1].Set(val)
timer.CCBUF[1].Set(val)
case PA14:
pwm.getTimer().CCBUF[0].Set(val)
timer.CCBUF[0].Set(val)
case PA15:
pwm.getTimer().CCBUF[1].Set(val)
timer.CCBUF[1].Set(val)
case PA18:
pwm.getTimer().CCBUF[2].Set(val)
timer.CCBUF[2].Set(val)
case PA19:
pwm.getTimer().CCBUF[3].Set(val)
timer.CCBUF[3].Set(val)
case PA20:
pwm.getTimer().CCBUF[0].Set(val)
timer.CCBUF[0].Set(val)
case PA21:
pwm.getTimer().CCBUF[1].Set(val)
timer.CCBUF[1].Set(val)
case PA23:
pwm.getTimer().CCBUF[3].Set(val)
timer.CCBUF[3].Set(val)
case PA22:
pwm.getTimer().CCBUF[2].Set(val)
timer.CCBUF[2].Set(val)
case PB31:
pwm.getTimer().CCBUF[1].Set(val)
timer.CCBUF[1].Set(val)
default:
return // not supported on this pin
}

3
src/machine/machine_generic.go

@ -90,7 +90,8 @@ func InitPWM() {
}
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() {
func (pwm PWM) Configure() error {
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value.

3
src/machine/machine_nrf52.go

@ -159,7 +159,8 @@ func InitPWM() {
}
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() {
func (pwm PWM) Configure() error {
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value.

4
src/machine/machine_nrf52840.go

@ -104,8 +104,8 @@ func InitADC() {
}
// Configure configures an ADC pin to be able to read analog data.
func (a ADC) Configure() {
return // no pin specific setup on nrf52840 machine.
func (a ADC) Configure() error {
return nil // no pin specific setup on nrf52840 machine.
}
// Get returns the current value of a ADC pin in the range 0..0xffff.

Loading…
Cancel
Save