Skip to content

Commit 3e63445

Browse files
committed
sam: return an error when an incorrect PWM pin is used
Previously it would trigger a nil pointer panic.
1 parent 01f5c1d commit 3e63445

File tree

7 files changed

+84
-51
lines changed

7 files changed

+84
-51
lines changed

src/examples/pwm/pwm.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ func main() {
2828
machine.InitPWM()
2929

3030
red := machine.PWM{redPin}
31-
red.Configure()
31+
err := red.Configure()
32+
checkError(err, "failed to configure red pin")
3233

3334
green := machine.PWM{greenPin}
34-
green.Configure()
35+
err = green.Configure()
36+
checkError(err, "failed to configure green pin")
3537

3638
blue := machine.PWM{bluePin}
37-
blue.Configure()
39+
err = blue.Configure()
40+
checkError(err, "failed to configure blue pin")
3841

3942
var rc uint8
4043
var gc uint8 = 20
@@ -52,3 +55,10 @@ func main() {
5255
time.Sleep(time.Millisecond * 500)
5356
}
5457
}
58+
59+
func checkError(err error, msg string) {
60+
if err != nil {
61+
print(msg, ": ", err.Error())
62+
println()
63+
}
64+
}

src/machine/machine_atmega.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ func InitPWM() {
2929
}
3030

3131
// Configure configures a PWM pin for output.
32-
func (pwm PWM) Configure() {
32+
func (pwm PWM) Configure() error {
3333
if pwm.Pin < 8 {
3434
avr.DDRD.SetBits(1 << uint8(pwm.Pin))
3535
} else {
3636
avr.DDRB.SetBits(1 << uint8(pwm.Pin-8))
3737
}
38+
return nil
3839
}
3940

4041
// Set turns on the duty cycle for a PWM pin using the provided value. On the AVR this is normally a

src/machine/machine_atsamd21.go

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,9 +1090,12 @@ func InitPWM() {
10901090
}
10911091

10921092
// Configure configures a PWM pin for output.
1093-
func (pwm PWM) Configure() {
1093+
func (pwm PWM) Configure() error {
10941094
// figure out which TCCX timer for this pin
10951095
timer := pwm.getTimer()
1096+
if timer == nil {
1097+
return ErrInvalidOutputPin
1098+
}
10961099

10971100
// disable timer
10981101
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@@ -1139,12 +1142,19 @@ func (pwm PWM) Configure() {
11391142
val := pwm.getPMux() & sam.PORT_PMUX0_PMUXO_Msk
11401143
pwm.setPMux(val | uint8(pwmConfig<<sam.PORT_PMUX0_PMUXE_Pos))
11411144
}
1145+
1146+
return nil
11421147
}
11431148

11441149
// Set turns on the duty cycle for a PWM pin using the provided value.
11451150
func (pwm PWM) Set(value uint16) {
11461151
// figure out which TCCX timer for this pin
11471152
timer := pwm.getTimer()
1153+
if timer == nil {
1154+
// The Configure call above cannot have succeeded, so simply ignore this
1155+
// error.
1156+
return
1157+
}
11481158

11491159
// disable output
11501160
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@@ -1154,7 +1164,7 @@ func (pwm PWM) Set(value uint16) {
11541164
}
11551165

11561166
// Set PWM signal to output duty cycle
1157-
pwm.setChannel(uint32(value))
1167+
pwm.setChannel(timer, uint32(value))
11581168

11591169
// Wait for synchronization on all channels
11601170
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0 |
@@ -1223,32 +1233,32 @@ func (pwm PWM) getTimer() *sam.TCC_Type {
12231233
}
12241234

12251235
// setChannel sets the value for the correct channel for PWM on this pin
1226-
func (pwm PWM) setChannel(val uint32) {
1236+
func (pwm PWM) setChannel(timer *sam.TCC_Type, val uint32) {
12271237
switch pwm.Pin {
12281238
case 6:
1229-
pwm.getTimer().CC0.Set(val)
1239+
timer.CC0.Set(val)
12301240
case 7:
1231-
pwm.getTimer().CC1.Set(val)
1241+
timer.CC1.Set(val)
12321242
case 8:
1233-
pwm.getTimer().CC0.Set(val)
1243+
timer.CC0.Set(val)
12341244
case 9:
1235-
pwm.getTimer().CC1.Set(val)
1245+
timer.CC1.Set(val)
12361246
case 14:
1237-
pwm.getTimer().CC0.Set(val)
1247+
timer.CC0.Set(val)
12381248
case 15:
1239-
pwm.getTimer().CC1.Set(val)
1249+
timer.CC1.Set(val)
12401250
case 16:
1241-
pwm.getTimer().CC2.Set(val)
1251+
timer.CC2.Set(val)
12421252
case 17:
1243-
pwm.getTimer().CC3.Set(val)
1253+
timer.CC3.Set(val)
12441254
case 18:
1245-
pwm.getTimer().CC2.Set(val)
1255+
timer.CC2.Set(val)
12461256
case 19:
1247-
pwm.getTimer().CC3.Set(val)
1257+
timer.CC3.Set(val)
12481258
case 20:
1249-
pwm.getTimer().CC2.Set(val)
1259+
timer.CC2.Set(val)
12501260
case 21:
1251-
pwm.getTimer().CC3.Set(val)
1261+
timer.CC3.Set(val)
12521262
default:
12531263
return // not supported on this pin
12541264
}

src/machine/machine_atsamd51.go

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,7 @@ const (
12161216
const period = 0xFFFF
12171217

12181218
// Configure configures a PWM pin for output.
1219-
func (pwm PWM) Configure() {
1219+
func (pwm PWM) Configure() error {
12201220
// Set pin as output
12211221
sam.PORT.GROUP[0].DIRSET.Set(1 << uint8(pwm.Pin))
12221222
// Set pin to low
@@ -1240,6 +1240,9 @@ func (pwm PWM) Configure() {
12401240

12411241
// figure out which TCCX timer for this pin
12421242
timer := pwm.getTimer()
1243+
if timer == nil {
1244+
return ErrInvalidOutputPin
1245+
}
12431246

12441247
// disable timer
12451248
timer.CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
@@ -1264,7 +1267,7 @@ func (pwm PWM) Configure() {
12641267

12651268
// Set the initial value
12661269
// TCCx->CC[tcChannel].reg = (uint32_t) value;
1267-
pwm.setChannel(0)
1270+
pwm.setChannel(timer, 0)
12681271

12691272
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0) ||
12701273
timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC1) {
@@ -1282,12 +1285,19 @@ func (pwm PWM) Configure() {
12821285
// Wait for synchronization
12831286
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_ENABLE) {
12841287
}
1288+
1289+
return nil
12851290
}
12861291

12871292
// Set turns on the duty cycle for a PWM pin using the provided value.
12881293
func (pwm PWM) Set(value uint16) {
12891294
// figure out which TCCX timer for this pin
12901295
timer := pwm.getTimer()
1296+
if timer == nil {
1297+
// The Configure call above cannot have succeeded, so simply ignore this
1298+
// error.
1299+
return
1300+
}
12911301

12921302
// Wait for synchronization
12931303
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CTRLB) {
@@ -1297,7 +1307,7 @@ func (pwm PWM) Set(value uint16) {
12971307
}
12981308

12991309
// TCCx->CCBUF[tcChannel].reg = (uint32_t) value;
1300-
pwm.setChannelBuffer(uint32(value))
1310+
pwm.setChannelBuffer(timer, uint32(value))
13011311

13021312
for timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC0) ||
13031313
timer.SYNCBUSY.HasBits(sam.TCC_SYNCBUSY_CC1) {
@@ -1329,61 +1339,61 @@ func (pwm PWM) setPinCfg(val uint8) {
13291339
pwm.Pin.setPinCfg(val)
13301340
}
13311341

1332-
// setChannel sets the value for the correct channel for PWM on this pin
1333-
func (pwm PWM) setChannel(val uint32) {
1342+
// setChannel sets the value for the correct channel for PWM on this pin.
1343+
func (pwm PWM) setChannel(timer *sam.TCC_Type, val uint32) {
13341344
switch pwm.Pin {
13351345
case PA16:
1336-
pwm.getTimer().CC[0].Set(val)
1346+
timer.CC[0].Set(val)
13371347
case PA17:
1338-
pwm.getTimer().CC[1].Set(val)
1348+
timer.CC[1].Set(val)
13391349
case PA14:
1340-
pwm.getTimer().CC[0].Set(val)
1350+
timer.CC[0].Set(val)
13411351
case PA15:
1342-
pwm.getTimer().CC[1].Set(val)
1352+
timer.CC[1].Set(val)
13431353
case PA18:
1344-
pwm.getTimer().CC[2].Set(val)
1354+
timer.CC[2].Set(val)
13451355
case PA19:
1346-
pwm.getTimer().CC[3].Set(val)
1356+
timer.CC[3].Set(val)
13471357
case PA20:
1348-
pwm.getTimer().CC[0].Set(val)
1358+
timer.CC[0].Set(val)
13491359
case PA21:
1350-
pwm.getTimer().CC[1].Set(val)
1360+
timer.CC[1].Set(val)
13511361
case PA23:
1352-
pwm.getTimer().CC[3].Set(val)
1362+
timer.CC[3].Set(val)
13531363
case PA22:
1354-
pwm.getTimer().CC[2].Set(val)
1364+
timer.CC[2].Set(val)
13551365
case PB31:
1356-
pwm.getTimer().CC[1].Set(val)
1366+
timer.CC[1].Set(val)
13571367
default:
13581368
return // not supported on this pin
13591369
}
13601370
}
13611371

13621372
// setChannelBuffer sets the value for the correct channel buffer for PWM on this pin
1363-
func (pwm PWM) setChannelBuffer(val uint32) {
1373+
func (pwm PWM) setChannelBuffer(timer *sam.TCC_Type, val uint32) {
13641374
switch pwm.Pin {
13651375
case PA16:
1366-
pwm.getTimer().CCBUF[0].Set(val)
1376+
timer.CCBUF[0].Set(val)
13671377
case PA17:
1368-
pwm.getTimer().CCBUF[1].Set(val)
1378+
timer.CCBUF[1].Set(val)
13691379
case PA14:
1370-
pwm.getTimer().CCBUF[0].Set(val)
1380+
timer.CCBUF[0].Set(val)
13711381
case PA15:
1372-
pwm.getTimer().CCBUF[1].Set(val)
1382+
timer.CCBUF[1].Set(val)
13731383
case PA18:
1374-
pwm.getTimer().CCBUF[2].Set(val)
1384+
timer.CCBUF[2].Set(val)
13751385
case PA19:
1376-
pwm.getTimer().CCBUF[3].Set(val)
1386+
timer.CCBUF[3].Set(val)
13771387
case PA20:
1378-
pwm.getTimer().CCBUF[0].Set(val)
1388+
timer.CCBUF[0].Set(val)
13791389
case PA21:
1380-
pwm.getTimer().CCBUF[1].Set(val)
1390+
timer.CCBUF[1].Set(val)
13811391
case PA23:
1382-
pwm.getTimer().CCBUF[3].Set(val)
1392+
timer.CCBUF[3].Set(val)
13831393
case PA22:
1384-
pwm.getTimer().CCBUF[2].Set(val)
1394+
timer.CCBUF[2].Set(val)
13851395
case PB31:
1386-
pwm.getTimer().CCBUF[1].Set(val)
1396+
timer.CCBUF[1].Set(val)
13871397
default:
13881398
return // not supported on this pin
13891399
}

src/machine/machine_generic.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ func InitPWM() {
9090
}
9191

9292
// Configure configures a PWM pin for output.
93-
func (pwm PWM) Configure() {
93+
func (pwm PWM) Configure() error {
94+
return nil
9495
}
9596

9697
// Set turns on the duty cycle for a PWM pin using the provided value.

src/machine/machine_nrf52.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ func InitPWM() {
159159
}
160160

161161
// Configure configures a PWM pin for output.
162-
func (pwm PWM) Configure() {
162+
func (pwm PWM) Configure() error {
163+
return nil
163164
}
164165

165166
// Set turns on the duty cycle for a PWM pin using the provided value.

src/machine/machine_nrf52840.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ func InitADC() {
104104
}
105105

106106
// Configure configures an ADC pin to be able to read analog data.
107-
func (a ADC) Configure() {
108-
return // no pin specific setup on nrf52840 machine.
107+
func (a ADC) Configure() error {
108+
return nil // no pin specific setup on nrf52840 machine.
109109
}
110110

111111
// Get returns the current value of a ADC pin in the range 0..0xffff.

0 commit comments

Comments
 (0)