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.

RM48 MibSPI TG interrupt - corrupt data. OK if read manually.

Hi,
we use an IMU sensor communicating via the MiBSPI interface.
The sensor "sample ready" output is connected to GPIOA0 configured as an interrupt input.

When I write/read the sensor manually it works (getting correct data) but I'm getting corrupt data when I use the
SPI interrupt and a TG trigger source (for sending the command to the sensor).

======================================================
Manually

mibspiSetData(mibSpiReg, 0U, burstReadCmd);
mibspiTransfer(mibSpiReg, 0U);
while (mibspiIsTransferComplete(mibSpiReg, 0U) == false)
{
}
mibspiGetData(mibSpiReg, 0U, (uint16 *) rcvBuf);

The rcvBuf holds correct X,Y,Z acc and gyro values.

======================================================
Auto

////////////////////////////////////////////////
// void mibspiInit(void)

<other MiBSPI setup>

/** enable MIBSPI1 multibuffered mode and enable buffer RAM */
mibspiREG1->MIBSPIE = (mibspiREG1->MIBSPIE & 0xFFFFFFFEU) | 1U;

<snip>

/** - initialize transfer groups */
mibspiREG1->TGCTRL[0U] =
  (uint32)((uint32)1U << 31U) /* TG transfer enable. Tx when trigger source */
  | (uint32)((uint32)0U << 30U) /* no oneshot */
  | (uint32)((uint32)0U << 29U) /* pcurrent reset */
  | (uint32)((uint32)TRG_RISING << 20U) /* trigger event */
  | (uint32)((uint32)TRG_GIOA0 << 16U) /* trigger source */
  | (uint32)((uint32)0U << 8U); /* start buffer */

<snip>

mibspiRAM1->tx[i].control =
  /* Using this I don't get overrun but corrupt data anyway */
  // (uint16)((uint16)5U << 13U) /* buffer mode */
  /* Using this I get overrun and corrupt data */
  (uint16)((uint16)4U << 13U) /* buffer mode */
  | (uint16)((uint16)1U << 12U) /* chip select hold */
  | (uint16)((uint16)0U << 10U) /* enable WDELAY */
  | (uint16)((uint16)0U << 11U) /* lock transmission */
  | (uint16)((uint16)0U << 8U) /* data format */
  /*SAFETYMCUSW 334 S MR:10.5 <APPROVED> "LDRA Tool issue" */
  | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU); /* chip select */

<snip>

////////////////////////////////////////////////
// Code that is run after mibspiInit()

mibspiSetData(mibspiREG1, 0U, burstReadCmd);
mibspiEnableGroupNotification(mibspiREG1, 0U, 0U);


////////////////////////////////////////////////
// void mibspi1HighLevelInterrupt(void)

// I get the interrupt and the FLG.TXINTFLG is 1
uint32 mibspiFlags = (mibspiREG1->FLG & 0x0000FFFFU) & (~mibspiREG1->LVL & 0x035FU);
uint32 vec = mibspiREG1->INTVECT0;

if (vec > 0x21U)
{
   // Error
   mibspiREG1->FLG = (mibspiREG1->FLG & 0xFFFF0000U) | mibspiFlags;
   mibspiNotification(mibspiREG1, mibspiFlags & 0xFFU);
}
else
{
  // vec == 2 -> INT0

  // The TGINTFLG.INTFLGRDY is NOT 0x00010000 (TG0)
  if(((((mibspiREG1->TGINTFLG & 0xFFFF0000U) >> 16U) >> 0U /*group*/) & 1U) == 1U)
  {
     I NEVER GET HERE! IT SEEMS THE INTERRUPT IS FIRED ON THE FIRST WORD TRANSMITTED?
     (EXCEPT IF I PUT A BREAKPOINT AT THE "IF" LINE ABOVE AND THEN STEP, BUT THE DATA IS THE SAME CORRUPT DATA)
     mibspiREG1->TGINTFLG = (mibspiREG1->TGINTFLG & 0x0000FFFFU) | ((uint32)((uint32) 1U << 0U /*group*/) << 16U);

     mibspiGetData(mibspiREG1, 0U, (uint16 *) rcvBuf);
  }

  IF I READ THE BUFFER IGNORING TGINTFLG IT'S CORRUPT DATA
  mibspiGetData(mibspiREG1, 0U, (uint16 *) rcvBuf);

  // mibspiSetData(mibspiREG1, 0U, burstReadCmd); // lvw123
  // mibspiTransfer(mibspiREG1, 0U);
}


If you can help us soon we would be very thankful since we are working on a prototype which will be demonstrated soon. 
We need this fast and self-going SPI <-> sensor communication since we do not want to waste processor time. 

Best regards,
Lars von Wachenfeldt
Bombardier Transportation

  • Hi Lars,

      There is note on the INTFLGRDY register. When the vec = mibspiREG1->INTVECT0 is executed, the flag in INTFLGRDYx is cleared. You need to decode the vec instead of decoding the TGINTFLG as in  if(((((mibspiREG1->TGINTFLG & 0xFFFF0000U) >> 16U) >> 0U /*group*/) & 1U) == 1U). Perhaps this is the problem. Try it and let me know if it makes a difference.

    Transfer-group interrupt flag for a transfer-completed interrupt.
    Note: Read Clear Behavior. Reading the interrupt vector registers TGINTVECT0 or
    TGINTVECT1 automatically clears the interrupt flag bit INTFLGRDYx referenced by the
    vector number given by INTVECT0/INTVECT1 bits, if the SUSPEND[0:1] bit in the vector
    registers is 0.

  • Hi Charles!

    Thank you very much for the quick answer! 

    And it works!

    Now the interrupt test code looks like this: 

    void mibspi1HighLevelInterrupt(void)

    {
      uint32 tgIntFlg = mibspiREG1->TGINTFLG;
      uint32 mibspiFlags = (mibspiREG1->FLG & 0x0000FFFFU) & (~mibspiREG1->LVL & 0x035FU);
      uint32 vec = mibspiREG1->INTVECT0;

      if (vec > 0x21U)
      {
         // Error
         mibspiREG1->FLG = (mibspiREG1->FLG & 0xFFFF0000U) | mibspiFlags;
         mibspiNotification(mibspiREG1, mibspiFlags & 0xFFU);
      }
      else
      {
         if(((((tgIntFlg & 0xFFFF0000U) >> 16U) >> 0U /*group*/) & 1U) == 1U)
         {
             if (vec == 2) // TG0
             {
                mibspiGetData(mibspiREG1, 0U, (uint16 *) rcvBuf); // Read TG0 ram
             }
         }
    }

    One lesson I've learned from this is to read the Notes more thoroughly next time!  ;) 


    Best regards,
    Lars
    Bombardier Transportation, Sweden

  • Glad your problem is resolved.