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

Previously it would trigger a nil pointer panic.
Этот коммит содержится в:
Ayke van Laethem 2020-05-11 16:02:00 +02:00 коммит произвёл Ron Evans
родитель b5f028e1f7
коммит 38fc340802
7 изменённых файлов: 84 добавлений и 51 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -90,7 +90,8 @@ func InitPWM() {
} }
// Configure configures a PWM pin for output. // 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. // Set turns on the duty cycle for a PWM pin using the provided value.

Просмотреть файл

@ -159,7 +159,8 @@ func InitPWM() {
} }
// Configure configures a PWM pin for output. // 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. // Set turns on the duty cycle for a PWM pin using the provided value.

Просмотреть файл

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