Not applicable
May 13, 2014
08:37 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 13, 2014
08:37 AM
Hello
I work with the MultiCan kernel from the XMC4500. I use a CAN node with a transmit and receive FIFO. The system works very well, but each time when I send multiple messages, one after the other, I have to wait in my CAN transmit function. I have implemented the following while loop
while ( CAN_MOx->MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk );
CAN_MOx is my transmit FIFO base object ( all defined slave objects are used )
With this loop it works well and no messages are lost, but is there a way to send CAN messages, one after the other, without this while loop. The wait time is about 100us.
Regards
Gerhard
I work with the MultiCan kernel from the XMC4500. I use a CAN node with a transmit and receive FIFO. The system works very well, but each time when I send multiple messages, one after the other, I have to wait in my CAN transmit function. I have implemented the following while loop
while ( CAN_MOx->MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk );
CAN_MOx is my transmit FIFO base object ( all defined slave objects are used )
With this loop it works well and no messages are lost, but is there a way to send CAN messages, one after the other, without this while loop. The wait time is about 100us.
Regards
Gerhard
3 Replies
Not applicable
May 14, 2014
12:14 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 14, 2014
12:14 AM
Hi Grehard,
you please try to work in interrupt mode, you can use separate interrupt output lines for Tx & Rx of CAN Message, then there will not be any requirement of waiting for one action to complete.
Thanks & Regards,
Ashish
you please try to work in interrupt mode, you can use separate interrupt output lines for Tx & Rx of CAN Message, then there will not be any requirement of waiting for one action to complete.
Thanks & Regards,
Ashish
Not applicable
May 14, 2014
03:43 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 14, 2014
03:43 AM
Hi Ashish,
thanks for your answer, but I have already done all your suggestions. For the receiving of CAN messages I use the CAN0_0_IRQHandler and for TX the CAN0_1_IRQHandler.
I have implemented another kind of the while loop. If I write my CAN message to the transmit base object, I save the actual value of the Current Object Pointer (MOFGPR register of the transmit base object). Before I write the next CAN message to the transmit base object I wait until the Current Object Pointer was incremented. Accordingly to the reference manual 18.3.9.4 "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" and I think this is done by hardware.
My problem or my question is, why is this taking so long?
Regards
Gerhard
thanks for your answer, but I have already done all your suggestions. For the receiving of CAN messages I use the CAN0_0_IRQHandler and for TX the CAN0_1_IRQHandler.
I have implemented another kind of the while loop. If I write my CAN message to the transmit base object, I save the actual value of the Current Object Pointer (MOFGPR register of the transmit base object). Before I write the next CAN message to the transmit base object I wait until the Current Object Pointer was incremented. Accordingly to the reference manual 18.3.9.4 "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" and I think this is done by hardware.
My problem or my question is, why is this taking so long?
Regards
Gerhard
Not applicable
May 20, 2014
05:35 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 20, 2014
05:35 AM
Hi Gerhard,
I use the TxFifo of the MCAN module without interrupts. The "trick" is to use the MOFGPR.SEL value to select the next msgObj inside the Fifo. I paste you my code, to explain it would be a little bit to complicated...
Best regards,
Mario
I use the TxFifo of the MCAN module without interrupts. The "trick" is to use the MOFGPR.SEL value to select the next msgObj inside the Fifo. I paste you my code, to explain it would be a little bit to complicated...
Best regards,
Mario
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;
}
msgObj[objIdx_intern].MOFGPR &= ~(uint32_t)CAN_MO_MOFGPR_SEL_Msk;
msgObj[objIdx_intern].MOFGPR |= (uint32_t)(((uint32_t)next<
objIdx_intern = sel;
}
else
{
// not supported...
status = FUNC_RETURN_ERROR;
}
}
if ( status == FUNC_RETURN_OK )
{
if ( (msgObj[objIdx_intern].MOSTAT & CAN_MO_MOSTAT_TXRQ_Msk) != 0 )
{
// Message object is busy TODO
status = FUNC_RETURN_ERROR;
}
else
{
uint8_t i;
uint32_t tmp;
// 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 ,TXEN0 and TXEN1 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
} // if ( status == FUNC_RETURN_OK )
} // 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_UpdateMsgObjTxData(uint8_t objIdx, uint8_t length, uint8_t * data)