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.

TM4C123GH6PM: CAN to USB communication

Part Number: TM4C123GH6PM

I am working on a project in which I am transmitting incoming CAN data to PC via USB.

CAN data will receive in every 1ms from an external hardware.This data I will copy into USB ring Buffer. Every 20ms data in the USB buffer will transmit to PC.I am using Bulk transfer mode. I developed my USB application based on the bulk transfer sample program.I am using the TI's PC tool(usb_bulk_example) to check the amount of data received at the PC.

My communication link is like this fig

CANDATASOURCE(1) ------------can------------->TM4C123(2)--------usb------------->PC(3)


Here I am facing 2 problems

1) Data loss between CANDATASOURCE and TM4C123(CAN bus)
Ex: An average loss of 300 messages for every 500000 messages when transmission happens at 1000msgs/second.
Loss is very less(less than 5 messages instead of 300) if the message transmission frequency is less(ex 200msgs/second).
Both transmitter and receiver are at the same sampling point (80%) and baud rate (1mbps).

Values I used to calculate sampling point(80%) and baud rate(1mbps) is given below
Clock = 80MHz
GetBittime.ui32SyncPropPhase1Seg=15;
GetBittime.ui32Phase2Seg=4;
GetBittime.ui32SJW=3;
GetBittime.ui32QuantumPrescaler=4;

What should I do to achieve zero data loss at this rate(1000 msgs/second)?

2) Received CAN data I will copy inside a message object structure (tCANMsgObject).
CANMessageGet(CAN0_BASE, 2, &sMsgObjectRx, 0);

Then this object structure I will copy into USB ring buffer using DMA.Gven below is the function which does that.

void UsbcopyDataToUSB(uint8_t *pui8Data, uint32_t ui32NumBytes) // This function is called inside the CAN RX ISR
{
uint32_t ui32Loop, ui32Space;
uint32_t ui32WriteIndex;
tUSBRingBufObject sTxRing;

//
// Get the current buffer information to allow us to write directly to
// the transmit buffer (we already have enough information from the
// parameters to access the receive buffer directly).
//
USBBufferInfoGet(&g_sTxBuffer, &sTxRing);

//
// How much space is there in the transmit buffer?
//
ui32Space = USBBufferSpaceAvailable(&g_sTxBuffer);

//
// How many characters can we process this time round?
//
ui32Loop = (ui32Space < ui32NumBytes) ? ui32Space : ui32NumBytes;
UsbDataTxBufferCount += ui32Loop;

ui32WriteIndex = sTxRing.ui32WriteIndex;

uDmaInitSWTransfer((void*)pui8Data,(void*)g_pui8USBTxBuffer[ui32WriteIndex],ui32Loop);
}

Everything  mentioned above are happening inside the CAN receiver interrupt.


Every 20ms, I will transmit the data to PC(at this time 20 CAN messages can be present inside the ring buffer). TX ring buffer size is 2K.
I have a counter to track how many bytes of data I have transmitted over USB.The function which transmits data over USB is given below.

void UsbTransmitDataIfAny() // This function is called every 20ms
{
if (UsbDataTxBufferCount)
{
USBBufferDataWritten(&g_sTxBuffer, UsbDataTxBufferCount);
UsbDataTransmitCount += UsbDataTxBufferCount; //ToTal Data tramsmitted over USB in Bytes
UsbDataTxBufferCount = 0;
}
}

In PC side, I am running usb_bulk_example with -e option.I also did some edit in that application to check how much data received.
At lower frequencies (CAN message transmission frequency is 200msgs/second) there used to be a small difference between the total data transmitted count
in the MCU side and total data received count in the PC side.
Ex: total Data transmitted(MCU side) = 100050B
Total Data received(PC side) = 100000B now the PC counter is less than 50B.
At this point if I sent one more packet of data from MCU to PC (consider 1packet = 10Byte),
then total Data transmitted(MCU side) become 100060B ie incremet of new packet size.
but total Data received(PC side) become 100060B ie incremet of 60B(old difference + new packet size).
Why this is happening ?

At higher frequencies(CAN message transmission frequency is 1000msgs/second) these 2 counts are showing a difference around 250B.Unlike the previous case after sending a single packet the difference is still same.MCU is connected to PC directly so If I call USBBufferDataWritten() can I assume that USB library will sent that data? If so, why it is not reaching to PC.
Or is there any problem in the PC side?Please help me?

  • Hi Jithin,
    You get a message lost because the previous message wasn't processed/read by the CPU yet. I think you probably spend too much time in your CAN receive ISR. You are currently trying to copy the received CAN data to USB ring buffer. If you could do this chore outside of the ISR then I think it will improve.