From b8f5627c9f54e7b520806cc4e8fcf98fca41fe62 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 4 Apr 2020 14:33:29 +0200 Subject: [PATCH] machine: move errors.New calls to globals Calling errors.New in an error path causes a heap allocation at an already unfortunate moment. It is more efficient to create these error values in globals and return these constant globals. If these errors are not used (because the related code was optimized out), the globals will also be optimized out. --- src/device/arm/arm.go | 4 ++- src/machine/i2c.go | 15 +++++++++++ src/machine/machine_atsamd21.go | 23 ++++++++--------- src/machine/machine_atsamd51.go | 23 ++++++++--------- src/machine/machine_fe310.go | 9 +++---- src/machine/machine_stm32f103xx.go | 40 ++++++++++++++---------------- src/machine/uart.go | 4 ++- src/machine/usb.go | 7 +++++- 8 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/device/arm/arm.go b/src/device/arm/arm.go index fcac1e57..21ba3bbd 100644 --- a/src/device/arm/arm.go +++ b/src/device/arm/arm.go @@ -35,6 +35,8 @@ import ( "unsafe" ) +var errCycleCountTooLarge = errors.New("requested cycle count is too large, overflows 24 bit counter") + // Run the given assembly code. The code will be marked as having side effects, // as it doesn't produce output and thus would normally be eliminated by the // optimizer. @@ -232,7 +234,7 @@ func SetupSystemTimer(cyclecount uint32) error { } if cyclecount&SYST_RVR_RELOAD_Msk != cyclecount { // The cycle refresh register is only 24 bits wide. The user-specified value will overflow. - return errors.New("requested cycle count is too large, overflows 24 bit counter") + return errCycleCountTooLarge } // set refresh count diff --git a/src/machine/i2c.go b/src/machine/i2c.go index 25d3180f..977c9bad 100644 --- a/src/machine/i2c.go +++ b/src/machine/i2c.go @@ -2,12 +2,27 @@ package machine +import ( + "errors" +) + // TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus. const ( TWI_FREQ_100KHZ = 100000 TWI_FREQ_400KHZ = 400000 ) +var ( + errI2CWriteTimeout = errors.New("I2C timeout during write") + errI2CReadTimeout = errors.New("I2C timeout during read") + errI2CBusReadyTimeout = errors.New("I2C timeout on bus ready") + errI2CSignalStartTimeout = errors.New("I2C timeout on signal start") + errI2CSignalReadTimeout = errors.New("I2C timeout on signal read") + errI2CSignalStopTimeout = errors.New("I2C timeout on signal stop") + errI2CAckExpected = errors.New("I2C error: expected ACK not NACK") + errI2CBusError = errors.New("I2C bus error") +) + // WriteRegister transmits first the register and then the data to the // peripheral device. // diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index 86491195..cd83b7b4 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -10,7 +10,6 @@ package machine import ( "device/arm" "device/sam" - "errors" "runtime/interrupt" "unsafe" ) @@ -549,13 +548,13 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error { for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) { timeout-- if timeout == 0 { - return errors.New("I2C timeout on ready to write data") + return errI2CWriteTimeout } } // ACK received (0: ACK, 1: NACK) if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) { - return errors.New("I2C write error: expected ACK not NACK") + return errI2CAckExpected } // write data @@ -581,13 +580,13 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error { // In that case, send a stop condition and return error. if i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) { i2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition - return errors.New("I2C read error: expected ACK not NACK") + return errI2CAckExpected } } // ACK received (0: ACK, 1: NACK) if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) { - return errors.New("I2C read error: expected ACK not NACK") + return errI2CAckExpected } // read first byte @@ -624,16 +623,16 @@ func (i2c I2C) WriteByte(data byte) error { for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) { // check for bus error if sam.SERCOM3_I2CM.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_BUSERR) { - return errors.New("I2C bus error") + return errI2CBusError } timeout-- if timeout == 0 { - return errors.New("I2C timeout on write data") + return errI2CWriteTimeout } } if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) { - return errors.New("I2C write error: expected ACK not NACK") + return errI2CAckExpected } return nil @@ -652,7 +651,7 @@ func (i2c I2C) sendAddress(address uint16, write bool) error { !i2c.Bus.STATUS.HasBits(wireOwnerState<