Pointer to struct for FlexCAN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Pointer to struct for FlexCAN

982 Views
davidzhou
Contributor V

volatile PMBox pTxMB= (PMBox)&(g_pCanReg->MB[TX_MB_num]);

while (1) {

   dwTxDLC = (dwTxDlen << CAN_CS_DLC_SHIFT);

   pTxMB->CS |= CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE);

   pTxMB->WORD0 = dwData0++;            

   pTxMB->WORD1 = htonl(dwData1++);

   pTxMB->CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_ONCE) | dwTxDLC);

   dwRTRBit = pTxMB->CS; // check for RTR bit

   if ((dwRTRBit & CAN_CS_RTR_MASK) == CAN_CS_RTR_MASK) {  

      iRTRNotSetCount++;

   }

  else if ((dwRTRBit & CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE))== CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE)) {

   //Version 1

   g_pCanReg->MB[TX_MB_num].CS &= ~(CAN_CS_CODE_MASK); 

   g_pCanReg->MB[TX_MB_num].CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);

   //Version 2

   //pTxMB->CS &= ~(CAN_CS_CODE_MASK); // Reset the code

   //pTxMB->CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);

  //Version 3

   //pTxMB->CS = pTxMB->CS & ~(CAN_CS_CODE_MASK); // Reset the code

   //pTxMB->CS = pTxMB->CS | (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);

iRTRSetCount++;

}

   // other code omitted ....

} //endof while

 

I tried three versions code as above. But only //version 1 works. I don't know why version2 and version 3 behave differently as version 1.

 

Thank you,

David Zhou

Labels (1)
0 Kudos
Reply
6 Replies

753 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello David,

Sorry i misunderstand it .

And when you define the structure of "PMBox",  have you use the "volatile" ?

If not, please try use it . Do you use CodeWarrior IDE?

BR

Alice

0 Kudos
Reply

753 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello David,

About this "volatile PMBox pTxMB= (PMBox)&(g_pCanReg->MB[TX_MB_num]);"

do you  want to forced the "(g_pCanReg->MB[TX_MB_num])" into "PMBox" ? If yes, here is not

need "&" , i think the right way is

volatile PMBox pTxMB= (PMBox)(g_pCanReg->MB[TX_MB_num]);

Hope it helps

Alice

0 Kudos
Reply

753 Views
davidzhou
Contributor V

Hi Alice,

Sorry for not making clear with PMBox. It is a pointer to the MB struct. I want to force it to the fixed index of MB[16] array. The pointer assignment to the member of MB array is correct.

volatile PMBox pTxMB= (PMBox)&(g_pCanReg->MB[TX_MB_num]);

(without & operator, compilation error).

In the Read Thread, I had pRxMB replaced g_pCanReg->MB[RX_MB_num]. It works.

But in the Write Thread, all pTxMB pointer replaces all g_pCanReg->MB[TX_MB_num].

except:

g_pCanReg->MB[TX_MB_num].CS &= ~(CAN_CS_CODE_MASK);

g_pCanReg->MB[TX_MB_num].CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);

If the above two lines are replaced with pMBox pointer, it has weird behavior.

Thank you,

David

0 Kudos
Reply

753 Views
davidzhou
Contributor V

Hi Alice,

I think the pTxMBox pointer is optimized by the compiler.

I added a line just before the pointer usage:

volatile PMBox pTxMBx=(PMBox)&g_pCanReg->MB[TX_MB_num];

pTxMBx->CS &= ~(CAN_CS_CODE_MASK);

pTxMBx->CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);

That works.

But the question is why the compiler optimized out a volatile pointer?

how to prevent from being optimized out?

Thank you,

David

0 Kudos
Reply

753 Views
TICS_Fiona
NXP Employee
NXP Employee

Hello David

The pointers to volatile variables are very common, especially with memory-mapped I/O registers. 

When you define a pointer using volatile keyword like below, the pointer itself is not volatile, but the object it points  to (in your case, g_pCanReg->MB[TX_MB_num]) is volatile. So the compiler may optimize on your pointer.

volatile PMBox pTxMBx=(PMBox)&g_pCanReg->MB[TX_MB_num];

If you want to define a volatile pointer, it should be:

PMBox volatile pTxMBx=(PMBox)&g_pCanReg->MB[TX_MB_num];

However, volatile pointers to non-volatile data are rare in common use.

For details, please refer to this link:

http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword

Best Regards

Fiona Kuang

Technical Information & Commercial Support

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

753 Views
davidzhou
Contributor V

Hi Fiona & Alice,

This is a weird problem, I added volatile to many places, it still doesn't work. Let me explain here:

The Can Mem Map structure is redefined as:

typedef struct {

  volatile uint32_t CS;

  volatile uint32_t ID;

  volatile uint32_t WORD0;

  volatile uint32_t WORD1;

} MBox, *PMBox;

typedef struct CanMemMap {

  uint32_t MCR;

  //omitted...

  volatile MBox MB[16];

  uint8_t RESERVED_3[1792];

  uint32_t RXIMR[16];

} volatile *CanMemMapPtr;

//for CanReadTask: -I replaced MB[index] with a pointer. It works OK.

void CanRead_Task(uint32_t param) {

PMBox pMB= (PMBox)&(g_pCanReg->MB[RX_MB_num]);  //not even use volatile

while (1) {

  if (_lwevent_wait_ticks(&lwEvent, 1 << RX_MB_num, FALSE, 0) != MQX_OK) {

    pMB->CS; 

    dwID = -1;

    dwDLen = pMB->CS & CAN_CS_DLC_MASK;

    dwDLC = dwDLen >> CAN_CS_DLC_SHIFT;

    if (dwFormat == FLEXCAN_STANDARD) {   

        dwID = ((pMB->ID & CAN_ID_STD_MASK) >> CAN_ID_STD_SHIFT);

        bCode = (uint8_t) (pMB->CS >> CAN_CS_CODE_SHIFT);

        if (bCode == CAN_RX_MSG_BUFFER_FULL) { 

           dwData0 = pMB->WORD0 ;

          dwData1 = pMB->WORD1 ;

       }

       pMB->WORD0 = 0;

       pMB->WORD1 = 0;

       pMB->CS &= ~(CAN_CS_CODE_MASK);

       pMB->CS |= (CAN_CS_CODE(CAN_RX_MSG_BUFFER_EMPTY) | dwDLen);

       g_pCanReg->TIMER; //FLEXCAN_Unlock_mailbox(CAN_DEVICE);

       FLEXCAN_Request_message(CAN_DEVICE, RX_remote_MB_num, dwFormat);

      _time_delay(1);

    }

}

//for CanTxTask  -

void CanWrite_Task(uint32_t param) {

   volatile PMBox volatile pTxMB= (PMBox)&(g_pCanReg->MB[TX_MB_num]);

   while (1) {

      dwTxDLC = (dwTxDlen << CAN_CS_DLC_SHIFT);

      pTxMB->CS |= CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE);

      pTxMB->WORD0 = g_aCanTxBuf[bCanTxBufTail].WORD0;

      pTxMB->WORD1 = g_aCanTxBuf[bCanTxBufTail].WORD1;

      pTxMB->CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_ONCE) | dwTxDLC);

      dwRTRBit = pTxMB->CS; // check for RTR bit

      if ((dwRTRBit & CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE))==         

          CAN_CS_CODE(CAN_TX_MSG_BUFFER_NOT_ACTIVE)) {

          //volatile PMBox pTxMBx= (PMBox)&(g_pCanReg->MB[TX_MB_num]);

         pTxMB->CS &= ~(CAN_CS_CODE_MASK); //LineA

         pTxMB->CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);//LineB

        //g_pCanReg->MB[TX_MB_num].CS &= ~(CAN_CS_CODE_MASK);//LineC

       //g_pCanReg->MB[TX_MB_num].CS |= (CAN_CS_CODE(CAN_MESSAGE_TRANSMIT_RESPONED) | dwTxDLC);//LineD

       _time_delay(1);

      }

}

Note: (both tasks are based on FlexCan/test.c in the example folder. some code is omitted for clearness.)

If pTxMBx is defined, and LineA and LineB are pTxMBx->, then it transmits CAN messages. (OK)

if use LineC, and LineD to replace LineA and LineB, it also works.

I checked pTxMB address, it points to the right memory. It never changes. But only LineA and LineB can not use pTxMB pointer. Otherwise, it doesn't transmit CAN messages. (or may have one message transmitted).

Thank you,

David

0 Kudos
Reply