This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CAN TX busy

Hi,

How does Tivaware wait for CAN tx to finish the transmission ?

Seems like CAN_STATUS_TX_OK doesn't reflect  that.

If I set a breakpoint inside the CANIntHandler , right after CANStatusGet(CAN1_BASE, CAN_STS_CONTROL), I get 0x00000008 (which is TX_OK).

So, I assume that CAN_STATUS_TX_OK doesn't really mean that we can send another message, as the transmission might be still going on...

Thank you

  • Hello Siauhwa,

    TX_OK means that the stream has been sent by the controller and a node on the n/w has ACK-ed the same. This would be after the transmission so the controller's transmitter is idle.

    Regards
    Amit
  • Hi Amit,

    Please find my code below.
    If I include delay(1) (1 ms delay) then the other node receives perfectly.
    But, If I don't then the other node will only receive once. I guess its due to bus error as one or both of the nodes are not ready for another message.

    If I set a breakpoint right after " status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);" I got 0x00000008, which means "CAN_STATUS_TX_OK), eventhough I think the message has not sent completely at that moment.

    Is there any common way to detect when the system is ready to send another message ?

    Thank you
    ===


    int CANSendStr (char *ptr_str_msg, unsigned int msg_len)
    {
    int index_string_msg;
    while (*ptr_str_msg++)
    {
    msg.pui8MsgData = (string_msg + index_string_msg) ;
    //delay(1); //delay of 1 ms
    CANMessageSet(CAN1_BASE, 1, &msg, MSG_OBJ_TYPE_TX); // send as msg object 1
    index_string_msg++;
    }
    }


    void delay(unsigned int milliseconds) {
    SysCtlDelay((sysClock / 3) * (milliseconds / 1000.0f));
    }

    // CAN interrupt handler
    void CANIntHandler(void) {
    unsigned long status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE); // read interrupt status
    if(status == CAN_INT_INTID_STATUS) { // controller status interrupt
    status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL); // read back error bits, do something with them?
    while ( status != CAN_STATUS_TXOK);
    errFlag = 1;
    } else if(status == 1) { // message object 1
    CANIntClear(CAN1_BASE, 1); // clear interrupt
    errFlag = 0; // clear any error flags
    } else { // should never happen
    UARTprintf("Unexpected CAN bus interrupt\n");
    }
    }
  • Hi Amit,

    I though by putting a while loop on CAN_STATUS_TXOK , will give me the right timing to send another message, But. seems like it doesn't...



    status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL); // read back error bits, do something with them?
    while ( status != CAN_STATUS_TXOK);


    Thank you

  • Hello Siauhwa,

    Actually I have not used a polling mechanism in CAN, but relied on the Interrupt mechanism rather. I would gauge that if the Interrupt is not enabled then you have to read the CANINT register to be non-zero before reading the CANSTS to show an update and transmit the next message.

    Regards
    Amit
  • Hi,
    Could you please give example code to do it in interrupt context.
    Actually, I did it on interrupt context as well, as shown on my code above...
  • Hello Siauhwa

    For TM4C123 there is an example already in TivaWare

    C:\ti\TivaWare_C_Series-2.1.0.12573\examples\peripherals\can

    In this code, the status from the Interrupt Handler as to a good transmission must be used to replace the SysCtlDelay in while(1) loop. For TM4C129 there is a similar code example that I had attached to a forum post almost 3-4 months back. You may have to search for the same in the forum.

    Regards
    Amit