LPC546 MCAN TX FIFO mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC546 MCAN TX FIFO mode

Jump to solution
2,604 Views
Patrick88
Contributor II

Hi, I'm using LPC54618 with mcan module. In SDK demos, there is only demos of sending can data with "dedicated buffers", while the real sending sequence is determined by CAN ID, But I need send CAN frames sequentially, as in a FIFO way.

I find there is "tx FIFO/queue" way of sending data, but no demos or APIs. Is there any demo or brief about how to use MCAN "tx FIFO/queue" method, or can anyone give me some tips. Thanks!

Labels (1)
0 Kudos
Reply
1 Solution
2,591 Views
RaRo
NXP TechSupport
NXP TechSupport

Hello @Patrick88,

Unfortunately, as you mention there is not an example to start with TX FIFO/QUEUE with MCAN module. Nonetheless, next we list information could be useful to take a look at:

Best regards, Raul.

View solution in original post

0 Kudos
Reply
4 Replies
2,500 Views
Patrick88
Contributor II

HI.@Raul,

Thank you for your advice, I've found a solution for my question.

①In MCAN initialization code, set TX FIFO configuration : 

    mcan_tx_buffer_config_t txBuffer =
    {
        .address = TX_BUFFER_OFS,
        .dedicatedSize = 0U,
        .fqSize = 32,
        .mode = kMCAN_txFifo,
        .datafieldSize = 64,
    };
②In application code :
uint8_t idx_arr[32];
uint8_t idx_idx;

bool MCAN_SendWithFifo(CAN_Type* base, mcan_tx_buffer_frame_t* tx)
{
    /*check if TX FIFO is full*/
    if(base->TXFQS & CAN_TXFQS_TFQF_MASK)
        return false;

    /*get TX FIFO put index*/
    uint8_t idx = ((base->TXFQS & CAN_TXFQS_TFQPI_MASK) >> CAN_TXFQS_TFQPI_SHIFT);
    idx_arr[idx_idx] = idx;
    idx_idx = (idx_idx+1)%32;
    mcan_buffer_transfer_t xfer =
    {
        .bufferIdx = idx,
        .frame = tx,
    };

    /*actually copy data to TX buffer, and add request to send message out*/
    status_t err = MCAN_TransferSendNonBlocking(base, CANFD_Channels[ch].CANHandle, &xfer);
    if(kStatus_Success == err)
        return true;
    else
        return false;
}
③In MCAN ISR code, as I use only TX FIFO and no TX BUFFER or TX QUEUE, I do the following change :
 
void MCAN_TransferHandleIRQ(CAN_Type *base, mcan_handle_t *handle)
{
...............................
        else if (0U != (valueIR & (uint32_t)kMCAN_TxTransmitCompleteFlag))
        {
            /* Solve Tx interrupt. */
            uint8_t idx = 0U;
            // for (; idx < (uint8_t)((base->TXBC & CAN_TXBC_NDTB_MASK) >> CAN_TXBC_NDTB_SHIFT); idx++)
            for(; idx < (uint8_t)((base->TXBC & CAN_TXBC_TFQS_MASK) >> CAN_TXBC_TFQS_SHIFT); idx++)
            {
                /* Get the lowest unhandled Tx Message Buffer */
                if (0U != MCAN_IsTransmitOccurred(base, idx))
                {
                    if ((base->TXBTIE & ((uint32_t)1U << idx)) != 0U)
                    {
                        MCAN_TransferAbortSend(base, handle, idx);
                    }
                }
            }
            result = (uint32_t)kMCAN_TxTransmitCompleteFlag;
            status = kStatus_MCAN_TxIdle;
        }
...............................
}
 
Above all, MCAN TX FIFO mode is now working. I think this solution is not good enough, but works for my project, hopefully someone can give a better one, or an official solution soon.
 
Thank You Again!
2,592 Views
RaRo
NXP TechSupport
NXP TechSupport

Hello @Patrick88,

Unfortunately, as you mention there is not an example to start with TX FIFO/QUEUE with MCAN module. Nonetheless, next we list information could be useful to take a look at:

Best regards, Raul.

0 Kudos
Reply
2,424 Views
Patrick88
Contributor II

Hi.@Raul,

With your tips, I finally found a slotion as below.

①in MCAN initialization code, configure TX Buffer:

    mcan_tx_buffer_config_t txBuffer =
    {
        .address = TX_BUFFER_OFS,
        .dedicatedSize = 0U,
        .fqSize = 32,
        .mode = kMCAN_txFifo,
        .datafieldSize = 64,
    };
②in application code:
 
uint8_t idx_arr[32];
uint8_t idx_idx;

bool MCAN_SendWithFifo(CAN_Type* base, mcan_tx_buffer_frame_t* tx)
{
    /*check if TX FIFO is full*/
    if(base->TXFQS & CAN_TXFQS_TFQF_MASK)
        return false;

    /*get TX FIFO put index*/
    uint8_t idx = ((base->TXFQS & CAN_TXFQS_TFQPI_MASK) >> CAN_TXFQS_TFQPI_SHIFT);
    idx_arr[idx_idx] = idx;
    idx_idx = (idx_idx+1)%32;
    mcan_buffer_transfer_t xfer =
    {
        .bufferIdx = idx,
        .frame = tx,
    };

    /*actually copy data to TX buffer, and add request to send message out*/
    status_t err = MCAN_TransferSendNonBlocking(base, CANFD_Channels[ch].CANHandle, &xfer);
    if(kStatus_Success == err)
        return true;
    else
        return false;
}
 
③In MCAN ISR code, as I use TX FIFO only and no TX BUFFER or TX QUEUE, I did some change:
 
.................
        else if (0U != (valueIR & (uint32_t)kMCAN_TxTransmitCompleteFlag))
        {
            /* Solve Tx interrupt. */
            uint8_t idx = 0U;
            // for (; idx < (uint8_t)((base->TXBC & CAN_TXBC_NDTB_MASK) >> CAN_TXBC_NDTB_SHIFT); idx++)
            for(; idx < (uint8_t)((base->TXBC & CAN_TXBC_TFQS_MASK) >> CAN_TXBC_TFQS_SHIFT); idx++)
            {
                /* Get the lowest unhandled Tx Message Buffer */
                if (0U != MCAN_IsTransmitOccurred(base, idx))
                {
                    if ((base->TXBTIE & ((uint32_t)1U << idx)) != 0U)
                    {
                        MCAN_TransferAbortSend(base, handle, idx);
                    }
                }
            }
            result = (uint32_t)kMCAN_TxTransmitCompleteFlag;
            status = kStatus_MCAN_TxIdle;
        }
.................
 
Above all, mcan now works with TXFIFO mode, and sends messages sequentially. I think this solution is not good enough, but it works for my project, and hopefully someone can give a better solution or an official solution soon.
 
Thank you!
2,572 Views
Patrick88
Contributor II

Thank.@Raul,

I will look into the files you mentioned above, and post the solution if I find any.

0 Kudos
Reply