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.

DCAN- EoB Set based on user message requirement?

Other Parts Discussed in Thread: HALCOGEN

Im using the RM57 uC(DCAN module) and in that while implementing a FIFO Buffer i came across that EoB will set only when the last message object in the FIFO Buffer for a given identifier receives a message. I am implementing a scheme where il be using an identifier scheme in which the identifier for each CAN Msg is a combination of Source Node Address+Destination Node Address and not message ID's. Each Node has the potential to reply back varying msg lengths(N*8bytes) for each service requested and hence its required that the EoB be configurable. For Ex, sometimes when the FIFO is Half Full,Sometimes just when 1 CAN msg is received etc.Is there any way in which i can configure when the EoB can get set??

  • FIFO mode is a bit confusing. I assume that you are using the RM57 to receive the CAN frames. FIFO mode allows you to receive a group of frames with the same ID (or same ID after filtering) and only generate an interrupt to the CPU when the last one comes in. Setup a block of mailboxes with the same identifier and mask. For example, if the most bytes you need to receive in this group is 64, then configure 8 mailboxes with the same identifier and mask. For example let's use mailboxes 1-8. The first 7 (1-7) set EoB (end of buffer) to 0 and RxIE (receive interrupt enable) to 0. On the eighth mailbox set EoB to 1 and RxIE to 1.

    Now let's assume that one of the nodes needs to send 24 bytes. It sends the first two frame with EoB=0 and the third frame with EoB=1. The first two frames end up in mailboxes 1 and 2, the third frame ends up in mailbox 8 and generates an interrupt. In the interrupt routine for mailbox 8, since you know it is the end of a FIFO, you start reading from mailbox 1. You must check the NewDat bit of each mailbox as you read it. When you hit mailbox 3, NewDat=0, so you can now skip to mailbox 8 and read the last frame from the group.

    It is very important that you service the interrupt and read then clear the NewDat bit of the first mailbox before the next group of frames comes in. Otherwise, in our example above, the first frame of the next block would be stored in mailbox 3, and the RM57 would think that the first block consisted of 32 bytes of data. The groups of data would be hopelessly corrupted.

  • How do you configure the EoB as you have mentioned above? Halcogen doesnt offer such configurations neither does the code generated by Halcogen. Must i manually write a driver to configure that in the IF1/IF2 Message control registers?
  • Do you use canFillMessageObjectData() and edit the function to take in 1 more parameter value called EoB. This EoB can then be used inside the function to Load appropriate EoB values as you have mentioned above after assigning the Message box number in IF1NO register and just before returning success=1?
  • You are correct, HALCoGen does not support the FIFO mode. To setup the receive buffer I would make my own  copy of canInit() setting canREG1->IFxMCTL=0x00001000U... for the mailboxes in the FIFO that are not EoB. To transmit a FIFO, yes I would create my own version of canFillMessageObjectData() that had an additional parameter for EoB.

  • Another way to do the transmit FIFO would be to use a modified canInit() that configures a group of mailboxes with the same ID and all but the last has EoB cleared. This is the same as for a receive buffer, but these mailboxes are for transmit. Then use the standard canFillMessageObjectData() function. Just make sure that you put the last frame of the block into the mailbox with EoB set. For example I setup a FIFO of 8 transmit mailboxes, the first 7 have EoB=0, the eighth has EoB=1. When I want to send a block of 24 bytes, I put the first 16 bytes in mailboxes 1 and 2, then put the last eight bytes in mailbox 8.
  • you mean clearing canREG1->IFxMCTL(bit 7)... for the mailboxes in the FIFO that are not supposed to hold the EoB=1 messages and setting canREG1->IFxMCTL(bit 7) for the mailbox that will be used to hold the data will the other node transmits EoB=1 in canInit().While transmitting a message,just load the EoB values appropriately in the canFillMessageObjectData() and send.
  • For your second answer you're talking about a situation where Section 26.9 of the TRM for RM57 states that

    "Transmission of multiple message objects may be requested at the same time".

    This is perfect for when i want to send multiple message objects at the same time(taking advantage of the fact that mess obj are sent based on priority). But then again,the HalCogen drivers must be customised by enabling all the message objects i want to send at the same time in the TxRQ register by Setting corresponding message object bits

  • Bob- I have setup 3 sets of 8 mailboxes(FIFO 1,2,3-for 3 separate nodes) just like how u had described earlier. That is, enable interrupt only for the last mailbox when E0B=1. Assume that FIFO1 causes an interrupt,it will enter can1LowLevelInterrupt(). At the same time, what if FIFO 2 also receives data from another node?? The interrupt wont trigger until i service FIFO 1 right? Is there any identification to know which Mailbox caused the Interrupt?
  • void canCnfgRxMailboxes(uint8 u8CanNo,uint8 u8BlockNo)
    {
    	 /* Create a pointer of type canBASE_t to point to NULL by default */
    	canBASE_t *canRegX = NULL;
    	u8BlockNo -=1U;
    	uint8 u8MessObjNo[7]={9U,17U,25U,33U,41U,49U,57U};/*Mess Object Numbers*/
    	uint8 u8MessIDNo[7]={19U,18U,20U,21U,22U,23U,24U};/*Mess ID Numbers*/
    	uint8 u8LoopCnt=0U;
    
    	/* Based on CAN number select appropriate registers*/
    	switch (u8CanNo)
    	{
    		case CAN1:
    			canRegX=(canBASE_t *)canREG1;
    		break;
    
    		case CAN2:
    			canRegX=(canBASE_t *)canREG2;
    		break;
    
    		case CAN3:
    			canRegX=(canBASE_t *)canREG3;
    		break;
    
    		case CAN4:
    			canRegX=(canBASE_t *)canREG4;
    		break;
    
    		default:
    			break;
    	}
    
    	/* Based on Block Number number select appropriate Mailboxes to program*/
    	for(u8LoopCnt=0;u8LoopCnt<8;u8LoopCnt++)
    	{
    		while ((canRegX->IF1STAT & 0x80U) ==0x80U)
    		{
    		} /* Wait */
    
    		canRegX->IF1MSK  = 0xC0000000U | (uint32)((uint32)((uint32)0x000007FFU & (uint32)0x000007FFU) << (uint32)18U);
    		canRegX->IF1ARB  = (uint32)0x80000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)((uint32)u8MessIDNo[u8BlockNo] & (uint32)0x000007FFU) << (uint32)18U);
    		canRegX->IF1MCTL = 0x00001080U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U;
    		canCnfgEoBMCTL(u8CanNo,EoBCLR); /* EoB=0 msg*/
    		canRegX->IF1CMD  = (uint8) 0xF8U;
    		canRegX->IF1NO   = u8MessObjNo[u8BlockNo];
    		u8MessObjNo[u8BlockNo]++;/*Next Message object Number*/
    	}
    
    	/*Last Message Object of Block*/
    	while ((canREG1->IF2STAT & 0x80U) ==0x80U)
    	{
    	} /* Wait */
    
    	canREG1->IF2MSK  = 0xC0000000U | (uint32)((uint32)((uint32)0x000007FFU & (uint32)0x000007FFU) << (uint32)18U);
    	canREG1->IF2ARB  = (uint32)0x80000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)((uint32)u8MessIDNo[u8BlockNo] & (uint32)0x000007FFU) << (uint32)18U);
    	canREG1->IF2MCTL = 0x00001080U | (uint32)0x00000400U | (uint32)0x00000000U | (uint32)8U; /*Rx Interrupt enable*/
    	canCnfgEoBMCTL(u8CanNo,EoBSET); /*EoB=1 msg*/
    	canREG1->IF2CMD  = (uint8) 0xF8U;
    	canREG1->IF2NO   = u8MessObjNo[u8BlockNo];/*Last message Object*/
    
    }

  • I am not sure I understand the question. Let me explain and then you can ask again if I have not answered your question.

    You have three FIFOs, each with 8 mailboxes. Only the last mailbox in each FIFO has the interrupt request enabled. When the 8th element in FIFO one is filled, you get an interrupt request. The function can1LowLevelInterrupt() calls canMessageNotification(). In that function you can add a read of DCAN INTPND X register (offset 0xAC) to determine which FIFO generated the interrupt. It is possible that more than one FIFO is full if the CPU was busy in another interrupt routine. When you read the last item in the FIFO, the interrupt request for that FIFO is cleared. If another FIFO became full after you read the DCAN INTPND X register, the code will re-enter the interrupt routine as soon as you return from the first interrupt.

  • RM57 TRM-" INTPND X register-Each bit of this register represents a group of eight message objects". Which means,since RM57 has only 64 message objects possibility,only Bit 7-0 is applicable for RM57 and Bit 0 corresponds to msg obj 1-8,Bit 1 corresponds to msg obj 9-16 and so on? If Bit 1 gets set,il know FIFO 1 has rexeived,if Bit 1 -> FIFO 2 and so on?

  • Before can1LowLevelInterrupt() calls canMessageNotification(),the interrupt gets cleared ( canREG1->IF1CMD = 0x08U). So, using INTPND X register in canMessageNotification() wont give the status of the interrupted FIFO right(cos thats wat the Halcogen comment for the  can1LowLevelInterrupt() states-" Setup IF1 for clear pending interrupt flag")? The TRM for RM57 states that writing a 1 to the IFxCMD bit 19 has no effect and does not clear the interrupt pending,so,your logic will then work by checking which FIFO interrupted and clear the Interrupt in canMessageNotification(). Which approach is right? If you are right,the comment is wrong. Else, if the comment is right,i cant check Fifo interrupt status in canMessageNotification() as the interrupt pending would have been cleared

  • You are correct, can1LowLevelInterrupt() reads which mailbox generated the interrupt and clears the interrupt request bit. The mailbox number is then passed as an argument to the function canMessageNotificaiton(). What the TRM says about bit 19 is  "Direction = Write: This bit is ignored". Direction refers to bit 23, "WR_RD". In HALCoGEN "canREG1->IF1CMD = 0x08U;" sets bit 23 to 0 and bit 19 to 1. The operation of the IF register is "Direction = READ", so bit 19 does cause the interrupt request to be cleared.

    canREG1->IF1CMD = 0x08U

  • Wow that was complicated to understand. Since Bit 23 is set to Direction=Read,Setting Bit 19 will cause the uC to interpret the action corresponding to Direction=Read. 

  • "RM57 TRM-" INTPND X register-Each bit of this register represents a group of eight message objects". Which means,since RM57 has only 64 message objects possibility,only Bit 7-0 is applicable for RM57 and Bit 0 corresponds to msg obj 1-8,Bit 1 corresponds to msg obj 9-16 and so on? If Bit 1 gets set,il know FIFO 1 has rexeived,if Bit 1 -> FIFO 2 and so on?"----->Is this correct?