From c844c02af4fda9033342ec615e6e347475e40b61 Mon Sep 17 00:00:00 2001 From: NoboNobo Date: Fri, 17 Apr 2026 02:36:16 +0900 Subject: [PATCH 1/3] add support extended id for mcp2515 --- mcp2515/mcp2515.go | 112 +++++++++++++++++++++---------------------- mcp2515/registers.go | 7 +++ 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/mcp2515/mcp2515.go b/mcp2515/mcp2515.go index ac08b5a68..78be9baa8 100644 --- a/mcp2515/mcp2515.go +++ b/mcp2515/mcp2515.go @@ -6,22 +6,36 @@ package mcp2515 // import "tinygo.org/x/drivers/mcp2515" import ( + "encoding/binary" "errors" "fmt" + "machine" "time" "tinygo.org/x/drivers" - "tinygo.org/x/drivers/internal/legacy" - "tinygo.org/x/drivers/internal/pin" +) + +var ( + ErrNothingIsReceived = errors.New("readMsg: nothing is received") + ErrRequestNewModeMaxTimeEx = errors.New("requestNewMode max time expired") + ErrLengthIsLongerThanCapacity = errors.New("length is longer than capacity") + ErrTxTimeout = errors.New("Tx: Tx timeout") + ErrInvalidDirection = errors.New("invalid direction") + ErrInvalidParameter = errors.New("invalid parameter") + ErrCannotExpandBuffer = errors.New("cannot expand buffer (to avoid memory allocation)") ) // Device wraps MCP2515 SPI CAN Module. type Device struct { - spi SPI - cs pin.OutputFunc - msg *CANMsg - mcpMode byte - configurePins func() + spi SPI + cs machine.Pin + msg *CANMsg + extended bool + mcpMode byte +} + +type Configuration struct { + Extended bool } // CANMsg stores CAN message fields. @@ -38,29 +52,26 @@ const ( ) // New returns a new MCP2515 driver. Pass in a fully configured SPI bus. -func New(b drivers.SPI, csPin pin.Output) *Device { +func New(b drivers.SPI, csPin machine.Pin) *Device { d := &Device{ spi: SPI{ bus: b, tx: make([]byte, 0, bufferSize), rx: make([]byte, 0, bufferSize), }, - cs: csPin.Set, + cs: csPin, msg: &CANMsg{}, - configurePins: func() { - legacy.ConfigurePinOut(csPin) - }, } return d } // Configure sets up the device for communication. -func (d *Device) Configure() { - if d.configurePins == nil { - panic(legacy.ErrConfigBeforeInstantiated) - } - d.configurePins() +func (d *Device) Configure(cfg Configuration) { + d.cs.Configure(machine.PinConfig{ + Mode: machine.PinOutput, + }) + d.extended = cfg.Extended } const beginTimeoutValue int = 10 @@ -117,9 +128,13 @@ func (d *Device) Tx(canid uint32, dlc uint8, data []byte) error { timeoutCount++ } if timeoutCount == timeoutvalue { - return fmt.Errorf("Tx: Tx timeout") + return ErrTxTimeout } - err = d.writeCANMsg(bufNum, canid, 0, 0, dlc, data) + ext := byte(0) + if d.extended { + ext = 1 + } + err = d.writeCANMsg(bufNum, canid, ext, 0, dlc, data) if err != nil { return err } @@ -389,7 +404,7 @@ func (d *Device) configRate(speed, clock byte) error { set = false } if !set { - return errors.New("invalid parameter") + return ErrInvalidParameter } if err := d.setRegister(mcpCNF1, cfg1); err != nil { return err @@ -449,7 +464,7 @@ func (d *Device) readMsg() error { return err } } else { - return fmt.Errorf("readMsg: nothing is received") + return ErrNothingIsReceived } return nil @@ -556,39 +571,22 @@ func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8, } func (s *SPI) setTxBufData(canid uint32, ext, rtrBit, dlc uint8, data []byte) error { - canid = canid & 0x0FFFF + var id [4]byte if ext == 1 { - // TODO: add Extended ID - err := s.setTxData(0) - if err != nil { - return err - } - err = s.setTxData(0) - if err != nil { - return err - } - err = s.setTxData(0) - if err != nil { - return err - } - err = s.setTxData(0) - if err != nil { - return err - } + canid = canid & extidBottom29Mask + extended_id := canid + high_11 := extended_id & extidTop11WriteMask + low_18 := extended_id & extidBottom18Mask + high_11 <<= 3 + extended_id_shifted := high_11 | low_18 + canid = extended_id_shifted | extidFlagMask } else { - err := s.setTxData(byte(canid >> 3)) - if err != nil { - return err - } - err = s.setTxData(byte((canid & 0x07) << 5)) - if err != nil { - return err - } - err = s.setTxData(0) - if err != nil { - return err - } - err = s.setTxData(0) + canid = canid & stdidBottom11Mask + canid <<= 16 + 5 + } + binary.BigEndian.PutUint32(id[:], canid) + for _, b := range id { + err := s.setTxData(b) if err != nil { return err } @@ -785,7 +783,7 @@ func (d *Device) requestNewMode(newMode byte) error { if r&modeMask == newMode { return nil } else if e := time.Now(); e.Sub(s) > 200*time.Millisecond { - return errors.New("requestNewMode max time expired") + return ErrRequestNewModeMaxTimeEx } } } @@ -861,23 +859,23 @@ func (s *SPI) clearBuffer(dir int) error { return s.setBufferLength(0, dir) } func (s *SPI) setBufferLength(length int, dir int) error { if dir == tx { if length > cap(s.tx) { - return fmt.Errorf("length is longer than capacity") + return ErrLengthIsLongerThanCapacity } s.tx = s.tx[:length] } else if dir == rx { if length > cap(s.rx) { - return fmt.Errorf("length is longer than capacity") + return ErrLengthIsLongerThanCapacity } s.rx = s.rx[:length] } else { - return fmt.Errorf("invalid direction") + return ErrInvalidDirection } return nil } func (s *SPI) setTxData(data byte) error { if len(s.tx) >= bufferSize { - return fmt.Errorf("cannot expand buffer (to avoid memory allocation)") + return ErrCannotExpandBuffer } s.tx = append(s.tx, data) diff --git a/mcp2515/registers.go b/mcp2515/registers.go index 6b7f28a99..9ca666164 100644 --- a/mcp2515/registers.go +++ b/mcp2515/registers.go @@ -417,4 +417,11 @@ const ( canFail = 0xff canMaxCharInMessage = 8 + + // for extended id + extidTop11WriteMask = 0x1FFC0000 + extidBottom29Mask = (1 << 29) - 1 // extended id bits + extidBottom18Mask = (1 << 18) - 1 // bottom 18 bits + stdidBottom11Mask = 0x7FF + extidFlagMask = 1 << 19 ) From 3792e3cb41c0f5c906d65814219d0882327f9290 Mon Sep 17 00:00:00 2001 From: NoboNobo Date: Fri, 17 Apr 2026 20:46:37 +0900 Subject: [PATCH 2/3] fix mcp2512 example code --- examples/mcp2515/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mcp2515/main.go b/examples/mcp2515/main.go index 6b7a84f1a..739ecf2f3 100644 --- a/examples/mcp2515/main.go +++ b/examples/mcp2515/main.go @@ -21,7 +21,7 @@ func main() { SDI: machine.SPI0_SDI_PIN, Mode: 0}) can := mcp2515.New(spi, csPin) - can.Configure() + can.Configure(mcp2515.Configuration{}) err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz) if err != nil { failMessage(err.Error()) From b02515be81a465644c2e94b21bb63765f6058039 Mon Sep 17 00:00:00 2001 From: NoboNobo Date: Mon, 20 Apr 2026 14:15:33 +0900 Subject: [PATCH 3/3] revert Pin control --- mcp2515/mcp2515.go | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/mcp2515/mcp2515.go b/mcp2515/mcp2515.go index 78be9baa8..2b0309687 100644 --- a/mcp2515/mcp2515.go +++ b/mcp2515/mcp2515.go @@ -9,10 +9,11 @@ import ( "encoding/binary" "errors" "fmt" - "machine" "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/internal/legacy" + "tinygo.org/x/drivers/internal/pin" ) var ( @@ -27,11 +28,12 @@ var ( // Device wraps MCP2515 SPI CAN Module. type Device struct { - spi SPI - cs machine.Pin - msg *CANMsg - extended bool - mcpMode byte + spi SPI + cs pin.OutputFunc + msg *CANMsg + extended bool + mcpMode byte + configurePins func() } type Configuration struct { @@ -52,15 +54,18 @@ const ( ) // New returns a new MCP2515 driver. Pass in a fully configured SPI bus. -func New(b drivers.SPI, csPin machine.Pin) *Device { +func New(b drivers.SPI, csPin pin.Output) *Device { d := &Device{ spi: SPI{ bus: b, tx: make([]byte, 0, bufferSize), rx: make([]byte, 0, bufferSize), }, - cs: csPin, + cs: csPin.Set, msg: &CANMsg{}, + configurePins: func() { + legacy.ConfigurePinOut(csPin) + }, } return d @@ -68,10 +73,11 @@ func New(b drivers.SPI, csPin machine.Pin) *Device { // Configure sets up the device for communication. func (d *Device) Configure(cfg Configuration) { - d.cs.Configure(machine.PinConfig{ - Mode: machine.PinOutput, - }) + if d.configurePins == nil { + panic(legacy.ErrConfigBeforeInstantiated) + } d.extended = cfg.Extended + d.configurePins() } const beginTimeoutValue int = 10