XMC4500 CAN Transmit FIFO Problem: Occasional TXEN1 not set by Hardware

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hello,

I have the following problem: I implemented a CAN Transmit FIFO containing 11 message objects static allocated to one message list in numerical order. The CAN Fifo is used by the XCP Protocol to transmit a set of DAQ-Messages with each event (every 1000ms, burst of x messages). When I configure the XCP to send a set of 4 messages each 1000ms everything is ok, but when I try to send 5 or more messages each 1000ms it works for about 20-30message and then I get an error (my function detects TXRQ not reset and returns FUNC_RETURN_ERROR). When I check the registers with the debugger all TXRQ bits of the message Objects are set but no message Object has the TXEN1 bit set (which should be done by Hardware after submitting the message of the previous object in the FIFO).
To update the Content of the FIFO my software uses the SEL-pointer within the MOFGPR-register of the FIFO base object (the SEL pointer is pointing to the next message object in the FIFO where the Software can put new data in). Before updating the Message object pointed to by the SEL of the base object I clear the MSGVAL bit. After setting up the new frame data I set the NEWDAT bit, reset the RTSEL bit and set the MSGVAL bit again. After that I set the TXRQ bit to enable the object for transmission when the CUR pointer of the base object is set to this object and the Hardware sets the TXEN1 bit.
Is it a problem when MSGVAL bit is reset when the Hardware moves the CUR pointer to this object and tries to set the TXEN1-Bit? Or is the problem the reset of the RTSEL bit after configuring the message object? I havent found anything for this topic within the user manual...

I paste the code of the transmit function down below. The parameter objIdx is the Index of the FIFO base object.

/**
* @brief Update data and length of TX message object and set Transmit Request for selected message
* @note -
* @param[in] objIdx Index of the HW message object (0..63 for a XMC4500)
* @param[in] length Number of data bytes the message object contains (0..8)
* @param[in] data Pointer to data array
* @retval Status of operation: FUNC_RETURN_OK if data in message object is updated, else FUNC_RETURN_ERROR
*/
sint32_t MCAN0_UpdateMsgObjTxDataAndTransmit(uint8_t objIdx, uint8_t length, const uint8_t * data)
{
sint32_t status = FUNC_RETURN_OK;
uint32_t objIdx_intern = objIdx;
CAN_MO_TypeDef * msgObj = (CAN_MO_TypeDef *)CAN_MO0_BASE;

// *** Check parameter ***
// Check objIdx
if ( objIdx_intern >= MCAN0_MSG_OBJ_CNT )
{
status = FUNC_RETURN_ERROR;
}
else if ( length > 8 )
{
status = FUNC_RETURN_ERROR;
}
else
{ // Parameter ok..
if ( (msgObj[objIdx_intern].MOSTAT & CAN_MO_MOSTAT_DIR_Msk) != 0 )
{
// DIR Bit in MOSTAT is set -> transmit message object

if ( (msgObj[objIdx_intern].MOFCR & CAN_MO_MOFCR_MMC_Msk) != 0 )
{
// Fifo or Gateway Source...
if ( (msgObj[objIdx_intern].MOFCR & CAN_MO_MOFCR_MMC_Msk) == (((uint32_t)2< {
// Transmit Fifo Base Object
uint32_t next, sel, top, bot;

sel = (msgObj[objIdx_intern].MOFGPR & CAN_MO_MOFGPR_SEL_Msk) >> CAN_MO_MOFGPR_SEL_Pos;
top = (msgObj[objIdx_intern].MOFGPR & CAN_MO_MOFGPR_TOP_Msk) >> CAN_MO_MOFGPR_TOP_Pos;
bot = (msgObj[objIdx_intern].MOFGPR & CAN_MO_MOFGPR_BOT_Msk) >> CAN_MO_MOFGPR_BOT_Pos;
if ( sel == top )
{
next = bot;
}
else
{
next = sel+1U; // TODO: msg-objects could be out of order in case of dynamic list linking!
}

if ( (msgObj[sel].MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk) != 0 )
{
// Message object is busy TODO
status = FUNC_RETURN_ERROR;
}
else
{
uint8_t i;
uint32_t tmp;

msgObj[objIdx_intern].MOFGPR &= ~(uint32_t)CAN_MO_MOFGPR_SEL_Msk;
msgObj[objIdx_intern].MOFGPR |= (uint32_t)(((uint32_t)next<
objIdx_intern = sel;

// Reset Message Object valid bit
msgObj[objIdx_intern].MOCTR = CAN_MO_MOCTR_RESMSGVAL_Msk;

// Configure data length
tmp = msgObj[objIdx_intern].MOFCR & ~CAN_MO_MOFCR_DLC_Msk; // clear old settings
msgObj[objIdx_intern].MOFCR = tmp | (((uint32_t)length << CAN_MO_MOFCR_DLC_Pos) & CAN_MO_MOFCR_DLC_Msk);

// Configure Data registers
for ( i = 0U; i < length; i++ )
{
if (i < 4U)
{
uint32_t pos = (uint32_t)i*8UL;
uint32_t mask = CAN_MO_MODATAL_DB0_Msk << ((uint32_t)i*8UL);
uint8_t dataByte = data;
msgObj[objIdx_intern].MODATAL = msgObj[objIdx_intern].MODATAL & ~mask; // delete old byte
msgObj[objIdx_intern].MODATAL |= ((uint32_t)dataByte << pos) & mask;
}
else
{
uint32_t pos = ((uint32_t)i-4UL)*8UL;
uint32_t mask = CAN_MO_MODATAL_DB0_Msk << (((uint32_t)i-4UL)*8UL);
uint8_t dataByte = data;
msgObj[objIdx_intern].MODATAH = msgObj[objIdx_intern].MODATAH & ~mask; // delete old byte
msgObj[objIdx_intern].MODATAH |= ((uint32_t)dataByte << pos) & mask;
} // if(i < 4)
} // for ( i = 0U; i < length; i++ )
// Set NEWDAT bit
msgObj[objIdx_intern].MOCTR = CAN_MO_MOCTR_SETNEWDAT_Msk;

// Reset RTSEL and Set MSGVAL bits
msgObj[objIdx_intern].MOCTR = (CAN_MO_MOCTR_RESRTSEL_Msk |
CAN_MO_MOCTR_SETMSGVAL_Msk );

if( (msgObj[objIdx_intern].MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk) != 0U )
{
status = FUNC_RETURN_ERROR;
}
else
{
// set TXRQ bit
msgObj[objIdx_intern].MOCTR = CAN_MO_MOCTR_SETTXRQ_Msk;
}
} // if ( (msgObj[objIdx_intern].MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk) != 0 ) ... else

}
else
{
// not supported...
status = FUNC_RETURN_ERROR;
}
}
} // if ( (msgObj[objIdx_intern].MOSTAT & CAN_MO_MOSTAT_DIR_Msk) != 0 )
else
{
// selected an RX Message Object for TX operation
status = FUNC_RETURN_ERROR;
}
}
return status;
} // sint32_t MCAN0_UpdateMsgObjTxDataAndTransmit(uint8_t objIdx, uint8_t length, const uint8_t * data)
0 Likes
6 Replies
Not applicable
I have also experienced this behavour. If TXEN1 is not set the FIFO stops as there are no messages sent, and therefor can be no new TXEN1 bits set. I Think it the failure to set TXEN appear in a situation when a message fails leading to some particular type of error. Have yet not found a better solution than to check all message objects for a TXEN1 as a part of sending a message.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
RBM wrote:
I have also experienced this behavour. If TXEN1 is not set the FIFO stops as there are no messages sent, and therefor can be no new TXEN1 bits set. I Think it the failure to set TXEN appear in a situation when a message fails leading to some particular type of error. Have yet not found a better solution than to check all message objects for a TXEN1 as a part of sending a message.



A message can only be transmitted if all four bits in registers MOSTATn, MSGVAL (Message Valid), TXRQ (Transmit Request), TXEN0 (Transmit Enable 0), TXEN1 (Transmit Enable 1) are set.


The TXEN bit is used in transmit FIFOs to select the message object that is transmit active within the FIFO structure. For message objects that are not transmit FIFO elements, TXEN1 can either be set permanently to 1 or can be used as a second independent transmission enable bit.
0 Likes
Not applicable
Hello again,

my transmit FIFO seemed to work now without any problems, but I did some streß test now and encountered situations where the HW does not seem to work correct. I wrote a Software which does a question and answer game with bus loads of 90% to 100%.
The communication works really fine for some time (approx. 50k messages), but then the tx FIFO does not send answers any more...
When I take a look at the registers of the MCAN0 there are no errors (NSR:LEC=0, NSR:EWRN=0, NSR:BOFF=0...).
When I take a look at the Message Objects of the tx FIFO than I see the following:
Tx-FIFO Base object: MOFGPR: BOT=0x10, TOP=0x17, CUR=0x18 and SEL=0x10 -> the CUR pointer points to a Message object not part of the tx FIFO -> the CUR pointer is only changed by HW...
all Tx-FIFO objects: TXEN1 reset -> should be set inside of one Message Object (pointed to by the CUR pointer) by HW... all Objects TXRQ is set -> message is waiting for transmission -> FIFO Full...
I could not find anything within the chip errata, but it seems to be a silicon error in my opinion.
Is there a FAE of Infineon available to show the problem and to talk about workarounds...? If the problem can not be solved, the whole project must switch to another Controller/Manufacturer short before series production...

I attached a Debugger export of the MCAN0-Registers. MessageObject 16 is the FIFO Base Object of the FIFO and the FIFO is 8 objects long (16..23).
My chip is a XMC4500F144F1024 Step AB, ZA230015M09

Best regards

Mario
0 Likes
Not applicable
The Users Manual (Reference Manual MultiCAN, V2.5 page 18-46 of XMC4500 V1.5 2014-07) tells the following:

In the FIFO base object, the FIFO boundaries are defined. Bit field MOFGPRn.BOT of
the base object points to (includes the number of) the bottom slave object in the FIFO
structure. The MOFGPRn.TOP bit field points to (includes the number of) the top slave
object in the FIFO structure. The MOFGPRn.CUR bit field points to (includes the number
of) the slave object that is actually selected by the MultiCAN module for message
transfer. When a message transfer takes place with this object, CUR is set to the next
message object in the list structure of the slave objects (CUR = PNEXT of current
object). If CUR was equal to TOP (top of the FIFO reached), the next update of CUR will
result in CUR = BOT (wrap-around from the top to the bottom of the FIFO).
This scheme
represents a circular FIFO structure where the bit fields BOT and TOP establish the link
from the last to the first element.


This HW mechanism seems not to work under some (unknown) circumstances... The Test I did can reproduce the behaviour, I encountered even that the CUR Pointer pointed to message object 19 (2 objects behind TOP of FIFO)...
0 Likes
Not applicable
Hello again,

finally I found the bug inside of the Software. I used the MOFGPR:SEL of the FIFO Base message object to inform the Software where the next free message object to put a message in is (I used the FIFO to be able to get 100% bus utilisation, so I put in new messages while the FIFO is running).
After the Software stored a message in the object SEL points to, the SEL pointer was set to the next message object inside of the FIFO structure. This update of the SEL pointer is not an atomic instruction, because MOFGPR is read, the SEL bits are set to zero and then the new value is ored into MOFGPR.

The only thing I do not understand is that MOFGPR:CUR (set by Hardware) is able to point to message objects not part of the FIFO. I could understand that it could happen that the modification of the CUR pointer by HW is lost by the not atomic register change done by Software, but that this can result in a pointer pointig to something out of range is not explainable for me...

My workaround for this problem is to use the MOFGPR:SEL of the message object next to the FIFO base object, this one is not changed by HW. With this workaround the FIFO is running at the moment over 1hour at 100% busload 🙂

Best regards

Mario
0 Likes
Not applicable
MarioW wrote:


I attached a Debugger export of the MCAN0-Registers. .......


Hello Mario,
How did you export register settings as text file.? Please let me know.

Best regards
Heinz
0 Likes