From 96b70fd619b9701335a1ae8d827ff1d54bc52330 Mon Sep 17 00:00:00 2001 From: Patricio Whittingslow Date: Thu, 23 Feb 2023 09:26:14 -0300 Subject: [PATCH] rp2040: provide better errors for invalid pins on i2c and spi (#3443) machine/rp2040: provide better errors for invalid pins on i2c and spi --- src/machine/machine_rp2040_i2c.go | 19 ++++++++++++++++++- src/machine/machine_rp2040_spi.go | 24 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_rp2040_i2c.go b/src/machine/machine_rp2040_i2c.go index d49e7f57..2c0c2e6e 100644 --- a/src/machine/machine_rp2040_i2c.go +++ b/src/machine/machine_rp2040_i2c.go @@ -57,6 +57,8 @@ var ( ErrInvalidTgtAddr = errors.New("invalid target i2c address not in 0..0x80 or is reserved") ErrI2CGeneric = errors.New("i2c error") ErrRP2040I2CDisable = errors.New("i2c rp2040 peripheral timeout in disable") + errInvalidI2CSDA = errors.New("invalid I2C SDA pin") + errInvalidI2CSCL = errors.New("invalid I2C SCL pin") ) // Tx performs a write and then a read transfer placing the result in @@ -90,7 +92,7 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error { // SCL: 3, 7, 11, 15, 19, 27 func (i2c *I2C) Configure(config I2CConfig) error { const defaultBaud uint32 = 100_000 // 100kHz standard mode - if config.SCL == 0 { + if config.SCL == 0 && config.SDA == 0 { // If config pins are zero valued or clock pin is invalid then we set default values. switch i2c.Bus { case rp.I2C0: @@ -101,6 +103,21 @@ func (i2c *I2C) Configure(config I2CConfig) error { config.SDA = I2C1_SDA_PIN } } + var okSDA, okSCL bool + switch i2c.Bus { + case rp.I2C0: + okSDA = config.SDA%4 == 0 + okSCL = (config.SCL+1)%4 == 0 + case rp.I2C1: + okSDA = (config.SDA+2)%4 == 0 + okSCL = (config.SCL+3)%4 == 0 + } + + if !okSDA { + return errInvalidI2CSDA + } else if !okSCL { + return errInvalidI2CSCL + } if config.Frequency == 0 { config.Frequency = defaultBaud } diff --git a/src/machine/machine_rp2040_spi.go b/src/machine/machine_rp2040_spi.go index fd1b6ab0..569a452a 100644 --- a/src/machine/machine_rp2040_spi.go +++ b/src/machine/machine_rp2040_spi.go @@ -40,6 +40,9 @@ var ( ErrLSBNotSupported = errors.New("SPI LSB unsupported on PL022") ErrSPITimeout = errors.New("SPI timeout") ErrSPIBaud = errors.New("SPI baud too low or above 66.5Mhz") + errSPIInvalidSDI = errors.New("invalid SPI SDI pin") + errSPIInvalidSDO = errors.New("invalid SPI SDO pin") + errSPIInvalidSCK = errors.New("invalid SPI SCK pin") ) type SPI struct { @@ -162,7 +165,7 @@ func (spi SPI) GetBaudRate() uint32 { // No pin configuration is needed of SCK, SDO and SDI needed after calling Configure. func (spi SPI) Configure(config SPIConfig) error { const defaultBaud uint32 = 115200 - if config.SCK == 0 { + if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 { // set default pins if config zero valued or invalid clock pin supplied. switch spi.Bus { case rp.SPI0: @@ -175,6 +178,25 @@ func (spi SPI) Configure(config SPIConfig) error { config.SDI = SPI1_SDI_PIN } } + var okSDI, okSDO, okSCK bool + switch spi.Bus { + case rp.SPI0: + okSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 17 + okSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 + okSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 + case rp.SPI1: + okSDI = config.SDI == 8 || config.SDI == 12 + okSDO = config.SDO == 11 || config.SDO == 15 + okSDO = config.SCK == 10 || config.SCK == 14 + } + + if !okSDI { + return errSPIInvalidSDI + } else if !okSDO { + return errSPIInvalidSDO + } else if !okSCK { + return errSPIInvalidSCK + } if config.DataBits < 4 || config.DataBits > 16 { config.DataBits = 8 }