Skip to content

MCP2515 bandwidth issues at 500K and 1Mbps -> SPI command optimizations #31

Open
@BiggRanger

Description

@BiggRanger

I made a few optimizations to improve the performance of the interface for the MCP2515. There are a couple of commands to reduce the overhead of the SPI to increase the data throughput to and from the MCP2515; LOAD RX BUFFER, RTS, and READ RX BUFFER. I added it endPacket() even though it doesn't matter as much since it waits for the packet to complete sending before returning (there is still an improvement), the improvement in parsePacket() is nice.

int MCP2515Class::parsePacket()
{
  int n;

  uint8_t intf = readRegister(REG_CANINTF);

  if (intf & FLAG_RXnIF(0)) 
  {
    n = 0;
  } 
  else if (intf & FLAG_RXnIF(1)) 
  {
    n = 1;
  }
  else
  {
    _rxId = -1;
    _rxRtr = false;
    _rxLength = 0;
    return 0;
  }
  uint8_t SIDH = readRegister(REG_RXBnSIDH(n));
  uint8_t SIDL = readRegister(REG_RXBnSIDL(n));
  uint32_t idA = ((SIDH << 3) & 0x07f8) | ((SIDL >> 5) & 0x07);
  _rxId = idA;
  _rxRtr = (SIDL & FLAG_SRR) ? true : false;

  _rxDlc = readRegister(REG_RXBnDLC(n)) & 0x0f;
  _rxIndex = 0;

  if (_rxRtr) 
  {
    _rxLength = 0;
  } 
  else 
  {
    _rxLength = _rxDlc;

    SPI.beginTransaction(_spiSettings);
    digitalWrite(_csPin, LOW);
    SPI.transfer(0b10010010 | (n << 2));        //Set to stream RX data from Buffer n
    for (uint8_t x = 0; x < _rxLength; x++)
      _rxData[x] = SPI.transfer(0x00);          //Stream data form RX buffer
    digitalWrite(_csPin, HIGH);                 //unsetting CS pin will reset IRQ flag
    SPI.endTransaction();
  }

  return _rxRtr ? true : _rxDlc;
}

int MCP2515Class::endPacket()
{
  if (!CANControllerClass::endPacket()) 
  {
    return 0;
  }

  int n = 0;

  writeRegister(REG_TXBnSIDH(n), _txId >> 3);
  writeRegister(REG_TXBnSIDL(n), _txId << 5);
  writeRegister(REG_TXBnEID8(n), 0x00);
  writeRegister(REG_TXBnEID0(n), 0x00);

  if (_txRtr)
  {
    writeRegister(REG_TXBnDLC(n), 0x40 | _txLength);
  }
  else 
  {
    writeRegister(REG_TXBnDLC(n), _txLength);    //set packet length

    SPI.beginTransaction(_spiSettings);
    digitalWrite(_csPin, LOW);
    SPI.transfer(0b01000000 | (n * 2 + 1));      //set TX buffer for stream
    for (uint8_t x = 0; x < _txLength; x++)
      SPI.transfer(_txData[x]);                  //stream data to buffer
    digitalWrite(_csPin, HIGH);
    SPI.endTransaction();
  }

  SPI.beginTransaction(_spiSettings);
  digitalWrite(_csPin, LOW);
  SPI.transfer(0b10000000 | (1 << n));          //set RTS for TX Buffer n
  digitalWrite(_csPin, HIGH);
  SPI.endTransaction();  

  bool aborted = false;

  while (readRegister(REG_TXBnCTRL(n)) & 0x08) 
  {
    if (readRegister(REG_TXBnCTRL(n)) & 0x10) 
    {
      // abort
      aborted = true;

      modifyRegister(REG_CANCTRL, 0x10, 0x10);
    }

    yield();
  }

  if (aborted) {
    // clear abort command
    modifyRegister(REG_CANCTRL, 0x10, 0x00);
  }

  modifyRegister(REG_CANINTF, FLAG_TXnIF(n), 0x00);

  return (readRegister(REG_TXBnCTRL(n)) & 0x70) ? 0 : 1;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions