Pointer to struct for FlexCAN

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Pointer to struct for FlexCAN

872件の閲覧回数
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

ラベル(1)
0 件の賞賛
返信
6 返答(返信)

643件の閲覧回数
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 件の賞賛
返信

643件の閲覧回数
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 件の賞賛
返信

643件の閲覧回数
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 件の賞賛
返信

643件の閲覧回数
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 件の賞賛
返信

643件の閲覧回数
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 件の賞賛
返信

643件の閲覧回数
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 件の賞賛
返信