SAMC21 - CAN transmit buffers/FIFO

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I building off the CAN driver for the C21 Xplained Pro board to migrate code written for an 8 bit Freescale processor to the SAMC21.  This code transmits and receives J1939 style PGN's.  The example code works just fine, but I need to transmit multiple messages (PGN's) within a timed 1ms interrupt.  If I stagger the messages in different interrupts it works fine, but if I do 2 or more in the same interrupt only one transmits.  It would seem like the driver should choose the next available buffer and return a status code if they are full.  The example code the way it is written seems to hardcode for one buffer, CAN_TX_BUFFER_INDEX (defined as 0),  unless I'm reading it wrong.  If anyone can point me in the right direction to expand on this driver I would appreciate it. 

Last Edited: Wed. May 17, 2017 - 09:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After much time buried in the data sheet, I have come up with a solution that seems to work.  This is a replacement for the FIFO tramsmit in the SAM C21 Xplained Pro "CAN Quick Start" example to allow automatic choosing of next available transmit buffer instead of a fixed single buffer:

 

static void can_send_extended_message(uint32_t id_value, uint8_t *data, uint32_t data_length)
{
    static uint32_t can_tx_buffer_index = 0;
    uint32_t i;
    struct can_tx_element tx_element;

    can_get_tx_buffer_element_defaults(&tx_element);
    tx_element.T0.reg |= CAN_TX_ELEMENT_T0_EXTENDED_ID(id_value) |
    CAN_TX_ELEMENT_T0_XTD;
    tx_element.T1.bit.DLC = data_length;

    for (i = 0; i < data_length; i++)
    {
        tx_element.data[i] = *data;
        data++;
    }

    if (CAN_MODULE->TXFQS.bit.TFQF == 0) // Make sure FIFO not full
    {

        can_tx_buffer_index = (uint32_t) CAN_MODULE->TXFQS.bit.TFQPI; // Get next put buffer index
        can_set_tx_buffer_element(&can_instance, &tx_element, can_tx_buffer_index);
        can_tx_transfer_request(&can_instance, 1 << can_tx_buffer_index);

    }

}