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

cross mob
Not applicable
Hello again.

As stated before, I'm new to XMC4500. I have the basic CAN comms working. I have two of my devel boards back-to-back
and one of the boards sends a command and the other side receives the data.

That's all fine, but I'm trying to wrap my head around configuring multiCAN. I have been reading the app note:
"Getting started with MultiCAN for the XMC4000 products". I'm trying to setup the FIFO both rx and tx.

So I am trying to do the MultiCAN FIFO as it says in Section 2.4.3.

So I want to allocate 10 CAN MO's for RX and 10 CAN MO's for RX.

My confusion is on the setting up for the doubley linked list. As I allocate the tx it looks something like:


// NOTE: can_tx_msg_MO[] is an array of CAN_MO0, CAN_MO1, CAN_MO2....
can_tx_msg.can_mo_ptr = can_tx_msg_MO;
can_tx_msg.can_identifier = i;
XMC_CAN_AllocateMOtoNodeList(CAN, 1, i);
XMC_CAN_MO_Config(&can_tx_msg);


Where

#define MAX_TX_MSG 10
XMC_CAN_MO_t can_tx_msg[MAX_TX_MSG]


How the heck do I set the base and slave objects?
Something like:

tx_fifo_cfg.fifo_base = 0;
tx_fifo_cfg.fifo_bottom = 0;
tx_fifo_cfg.fifo_top = MAX_TX_MSG - 1;

XMC_CAN_TXFIFO_ConfigMOBaseObject(&can_tx_msg[0],tx_fifo_cfg);
XMC_CAN_TXFIFO_ConfigMOSlaveObject(&can_tx_msg[0],tx_fifo_cfg);


I am using only the XMCLib calls not any DAVE stuff.

Any help would be greatly appreciated.

-stv
0 Likes
6 Replies
User6793
Level 4
Level 4
Here is my setup for 1 TX MO and the rest used as RX MOs.
Hope it helps 🙂
https://www.infineonforums.com/threads/2890-How-to-configure-all-64-message-object-for-single-node.....
0 Likes
Not applicable
Thanks OMR.

I think it's using older API's, but I think I can work with this. I'll update more once I get some progress.
0 Likes
User6793
Level 4
Level 4
Indeed it does, but that code is now out on thousands of CAN nodes working flawlessly, so if it ain't broke ... 🙂
0 Likes
Dirk
Employee
Employee
Hi,

I have to thank OMR in advace for his code. The code gave me a lot of inputs to solve my CAN Library problems without static APP stuff.
I did it for the XMC 1400/4100 and wanted to use MultiCAN and to define the RX ident and mask where i listen to the can message. So that the controler must not listen to all packets on the bus.
The solution was a CAN HAL Driver to handle the message queue and sending to CAN.
Antoher thing was to use the MSPND List of the controller to know where a message has been received and in which list.
List 1 = CAN 1 List 2 = CAN2 List 3-7 is. The higher list are single list is for a RX fifo.
Your best friend is the reference manual for xmc1400, as i think its newer. 🙂

This is the Part of my setup_rxMO function.

enCAN_HAL_status CAN_HAL_setup_rxMO(
CAN_HAL_CNTRL_t *_pCtrl, //my handling structure
uint16_t ident,
uint16_t mask,
uint16_t RX_index, //Index for my struct to handle my can node rx messages
uint8_t MO_index, //RX MO which receives the CAN Message and transfer it to the RX FIFO Obejcts
uint8_t MO_start, //Start FIFO RX MO
uint8_t MO_end, //End MO
enEventNodePo rx_sr, //The SR from XMC

)
{
uint32_t nextMsgList;
//kein FIFO, Base object
CAN_MO_TypeDef *pBaseMO = (CAN_MO_TypeDef*)(CAN_DEV_MO_getMO(MO_index));
_pCtrl->rxArray[RX_index].pBaseMO = pBaseMO;
//Initialisieren des BASE rx Message Objekt (rxMO), mit dem Service Request
CAN_DEV_InitializeRxMO(_pCtrl->global_ptr, _pCtrl->node_ptr, &pBaseMO, MO_index, ident, mask);//, rx_sr);
CAN_DEV_InitializeMOEvent(pBaseMO, enSR_RXSR, rx_sr);
if (MO_start != MO_end)
{
//FIFO Elemente zu dem BaseObject hinzufügen
nextMsgList = CAN_DEV_MO_getNextFreeMessageList((CAN_MO_TypeDef *)CAN_DEV_MO_BASE, CAN_DEV_MAX_MO, 2);
//Initialisiere die RX FIFO Elemente als starre Elemente.
CAN_DEV_InitializeRXFIFO(_pCtrl->global_ptr, _pCtrl->node_ptr, &pBaseMO, nextMsgList, MO_start, (MO_end - MO_start + 1));
//Adresse der Pending Message List speichern
_pCtrl->rxArray[RX_index].pMPSND = (uint32_t *)&_pCtrl->global_ptr->MSPND[nextMsgList];
nextMsgList = CAN_DEV_MO_getList(pBaseMO);
//Verschiebe das BASE Object in Liste 0 + an die Position der gewählten Msg Liste für das Base Object.
pBaseMO->MOIPR = ((pBaseMO->MOIPR & (~CAN_MO_MOIPR_MPN_Msk)) | (nextMsgList << CAN_MO_MOIPR_MPN_Pos));

}
...
}


The copy of the xmc APP a little bit advanced, because i don't want the static App defines

CAN_DEV_STATUS_t CAN_DEV_InitializeRxMO(
XMC_CAN_t *_pcan_global_ptr,
XMC_CAN_NODE_t *_pnode_ptr,
CAN_MO_TypeDef **_pmo_obj,
uint16_t _index,
uint16_t _ident,
uint16_t _mask
//enEventNodePo _rx_sr
)
{
XMC_CAN_MO_t *pCAN_NODE_0_LMO_XX;
pCAN_NODE_0_LMO_XX = (XMC_CAN_MO_t *) malloc(sizeof(XMC_CAN_MO_t));
if (*_pmo_obj == NULL)
{
pCAN_NODE_0_LMO_XX->can_mo_ptr = (CAN_MO_TypeDef*)(CAN_DEV_MO_getMO(_index));
}
else
{
pCAN_NODE_0_LMO_XX->can_mo_ptr = *_pmo_obj;
}

pCAN_NODE_0_LMO_XX->can_mo_type = XMC_CAN_MO_TYPE_RECMSGOBJ;
pCAN_NODE_0_LMO_XX->can_id_mode = XMC_CAN_FRAME_TYPE_STANDARD_11BITS;
pCAN_NODE_0_LMO_XX->can_priority = XMC_CAN_ARBITRATION_MODE_IDE_DIR_BASED_PRIO_2;
pCAN_NODE_0_LMO_XX->can_identifier = (uint32_t)(_ident & 0x07FFU);
pCAN_NODE_0_LMO_XX->can_id_mask = (uint32_t)(_mask & 0x07FFU); //0x7ffU;
pCAN_NODE_0_LMO_XX->can_ide_mask = 1U;

pCAN_NODE_0_LMO_XX->can_data_length = 8U;
pCAN_NODE_0_LMO_XX->can_data[1] = 0x0U ;
pCAN_NODE_0_LMO_XX->can_data[0] = 0x0U ;

/* set CCE and INIT bit NCR for node configuration */
XMC_CAN_NODE_EnableConfigurationChange(_pnode_ptr);
XMC_CAN_NODE_SetInitBit(_pnode_ptr);

XMC_CAN_PanelControl(_pcan_global_ptr, XMC_CAN_PANCMD_STATIC_ALLOCATE, _index, CAN_DEV_NODE_NUMBER(_pnode_ptr));
/* wait until panel as done the command */
while (_pcan_global_ptr->PANCTR & CAN_PANCTR_BUSY_Msk)
{
/*Do nothing*/
};
//CAN_NODE_MO_Init(pCAN_NODE_0_LMO_XX_Config); <- Aus dieser Funktion
XMC_ASSERT("CAN_NODE_MO_Init: lmo_ptr null", pCAN_NODE_0_LMO_XX->can_mo_pt != NULL);

XMC_CAN_MO_Config(pCAN_NODE_0_LMO_XX);
#if 0
if (_rx_sr >= 0)
{
XMC_CAN_MO_SetEventNodePointer(pCAN_NODE_0_LMO_XX , XMC_CAN_MO_POINTER_EVENT_RECEIVE, _rx_sr);
XMC_CAN_MO_EnableEvent(pCAN_NODE_0_LMO_XX ,XMC_CAN_MO_EVENT_RECEIVE);
}
#endif
/* reset CCE and INIT bit NCR for node configuration */
XMC_CAN_NODE_DisableConfigurationChange(_pnode_ptr);
XMC_CAN_NODE_ResetInitBit(_pnode_ptr);

if (*_pmo_obj == NULL)
{
*_pmo_obj = pCAN_NODE_0_LMO_XX->can_mo_ptr;
}
free(pCAN_NODE_0_LMO_XX);

return CAN_DEV_STATUS_SUCCESS;
}


The main magic with inputs from OMR and the heavy manual was the RXFIFO Part

CAN_DEV_STATUS_t CAN_DEV_InitializeRXFIFO(
XMC_CAN_t *_pCanglobal_ptr,
XMC_CAN_NODE_t *_pnode_ptr,
CAN_MO_TypeDef ** _pMOBase,
uint32_t _NodeList,
uint32_t _start,
uint32_t _Size
)
{
CAN_MO_TypeDef * pMOSlave = NULL;
uint32_t MOBase_NUM = CAN_DEV_MO_NUM((*_pMOBase));
volatile uint32_t moipr;
if ((*_pMOBase) != NULL)
{
//Füge alle Slave Objecte des RXFIFO in eine NodeListe nacheinander ein
for (int i=0; i<_Size; i++)
{
//MO Object konfigurieren mit Addr 0 / Mask 0
pMOSlave = NULL;
//Interrupt für den RX Interrupt auf den Slave RX FIFO übertragen, dass dieser auslöst für den FIFO
CAN_DEV_InitializeRxMO(_pCanglobal_ptr, _pnode_ptr, &pMOSlave, i+_start, 0x0, 0x0);//, ((*_pMOBase)->MOIPR & 0xfU));
CAN_DEV_InitializeMOEvent(pMOSlave, enSR_RXSR, ((*_pMOBase)->MOIPR & 0xfU));
//RXEN Enable abschalten
pMOSlave->MOCTR = (uint32_t)CAN_MO_MOCTR_RESRXEN_Msk;
if (_NodeList < 😎
{
moipr = ((uint32_t)_NodeList << 13) ;
}
pMOSlave->MOIPR |= moipr;
pMOSlave->MOFGPR = (0<<24) | (MOBase_NUM <<16) | (0<<8)| (0<<0);
pMOSlave->MOFCR |= XMC_CAN_MO_EVENT_RECEIVE;
//In Liste einfügen
//[CMD][MO]

    XMC_CAN_PanelControl(_pCanglobal_ptr, XMC_CAN_PANCMD_STATIC_ALLOCATE, i+_start, _NodeList);
    /* wait until panel as done the command */
    while (_pCanglobal_ptr->PANCTR & CAN_PANCTR_BUSY_Msk)
    {
    /*Do nothing*/
    };

    }

    // setup Base FIFO Object
    // SEL CUR TOP BOT
    (*_pMOBase)->MOFGPR = (_start << CAN_MO_MOFGPR_SEL_Pos)
    | (_start << CAN_MO_MOFGPR_CUR_Pos)
    | ((_Size+_start-1) << CAN_MO_MOFGPR_TOP_Pos)
    | (_start << CAN_MO_MOFGPR_BOT_Pos);

    (*_pMOBase)->MOFCR |= (1 << CAN_MO_MOFCR_MMC_Pos); //RxFIFO base MMC=1
    //Rest -> SEE @ref CAN_DEV_InitializeRXFIFO_OverflowIE für den TXINP der den ISR auslöst.

    }
    else
    {
    return CAN_DEV_STATUS_MO_NOT_ACCEPTABLE;
    }
    return CAN_DEV_STATUS_SUCCESS;
    }


    If I forgot something ask me
    I'll try to explain in detail
0 Likes
Not applicable
So I have the rx working on interrupts. I totally had things screwed up. Once I get this done, I'll post what I have done.

OMR, hopefully you are still paying attention to this thread as I think you'll be able to answer me. But it'd be nice if an infineon person chimed in.

I'm only working on RX for now. I have two of my dev boards (XMC4500) back to back. One is just using a simple TX mode where it sends out a CAN message
every second.

The other side which I have configured for RXFIFO fills in the RxFIFO as I would expect.
However the MSPNDx is not being set properly.

Here is a snip of my init code...



XMC_CAN_NODE_EnableConfigurationChange(CAN_NODE1);

/* Sets bit MPN[7:5] which demuxes to MSPND1 for the RX Message Objects */
#define RX_FIFO_MSPND (1 << (CAN_MO_MOIPR_MPN_Pos + 5))

/* Sets bit MPN[7:5] which demuxes to MSPND0 for the TX Message Objects */
#define TX_FIFO_MSPND (0 << (CAN_MO_MOIPR_MPN_Pos + 5))

#define CAN_RX_FIFO_TOP 20

for(i=CAN_TX_FIFO_DEPTH; i< CAN_TX_FIFO_DEPTH + CAN_RX_FIFO_DEPTH; i++)
{
tmp_mo = GET_MSG_NO(i);
XMC_CAN_AllocateMOtoNodeList(CAN,1,i); /* really LIST2 because we are on NODE1 */
if(CAN_RX_FIFO_BASE == i)
{
XMC_CAN_FIFO_CONFIG_t rx_fifo;

rx_fifo.fifo_base = i;
rx_fifo.fifo_bottom = i;
rx_fifo.fifo_top = CAN_RX_FIFO_TOP - 1;

/* from my tailq list, fill in the default values for the rx_desc */
memcpy(&can_queue_buf.can_msg_obj,&can_rx_desc,sizeof(can_rx_desc));
can_queue_buf.can_msg_obj.can_mo_ptr = tmp_mo;
TAILQ_INSERT_TAIL(&rx_can_q_head, &can_queue_buf, link);
XMC_CAN_MO_Config(&can_queue_buf.can_msg_obj);
XMC_CAN_RXFIFO_ConfigMOBaseObject(&can_queue_buf.can_msg_obj,rx_fifo);
tmp_mo->MOIPR |= (RX_FIFO_MSPND | (RX_FIFO_INT << CAN_MO_MOIPR_RXINP_Pos)); /* INT_O2, index already set in XMC_CAN_MO_Config*/

}else{
memcpy(&can_queue_buf.can_msg_obj,&can_rx_desc,sizeof(can_rx_desc));
can_queue_buf.can_msg_obj.can_mo_ptr = tmp_mo;
TAILQ_INSERT_TAIL(&rx_can_q_head, &can_queue_buf, link);
XMC_CAN_RXFIFO_ConfigMOSlaveObject(&can_queue_buf.can_msg_obj);
XMC_CAN_MO_Config(&can_queue_buf.can_msg_obj);
tmp_mo->MOIPR |= (RX_FIFO_MSPND | (RX_FIFO_INT << CAN_MO_MOIPR_RXINP_Pos)); /* INT_O2, index already set in XMC_CAN_MO_Config*/
tmp_mo->MOCTR = 0x0000080; // reset RXEN in RxFIFO slave object, so that all Rx goes through Rx_base
}
}
/* also set the mask */
CAN->MSIMASK = 0;
for (i=CAN_TX_FIFO_DEPTH; i< CAN_TX_FIFO_DEPTH + CAN_RX_FIFO_DEPTH; i++) // Setup global pending index mask
CAN->MSIMASK |= (1 << (i));
}

void CAN0_2_IRQHandler(void)
{
/* This is where I would expect to be able to check MSPDN and see which rx message object is pending, but it's always 0x00000020 */
}

XMC_CAN_NODE_DisableConfigurationChange(PAK_CAN_NODE);
XMC_CAN_NODE_ResetInitBit(PAK_CAN_NODE);



#Edit:
MCR.MPSEL = 0, so I'm going for Allocation Case 1 in the reference manual(ver 1.5xx) section 13.3.7

I think that should be enough for someone to look at and help me out. Am I supposed to configure something else?

Thanks again!

-stv
0 Likes
Not applicable
Got it boys.. forget it.

I wasn't setting the MOFCRn->RXIE, ugh.. one line I overlooked.

I'll post some sample code here once I'm done with getting the DMA to work.
0 Likes