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.

RM46L852: VIM parity error handler

Part Number: RM46L852
Other Parts Discussed in Thread: HALCOGEN

Hi,

To start, I am currently testing the VIM parity error handler as follows:

- VIM_PARTCTL (0xFFFFFDF0) is set to 0xA

- My VIM table is copied to vimRAM (0xFFF82000)

- VIM_FBPARERR (0xFFFFFDF8) is set to the address of the parity error handler, the implementation was generated through HALCoGen 04.06.01

{
  uint32 vec;

  /* Identify the corrupted address */
  uint32 error_addr = VIM_ADDERR;

  /* Identify the channel number */
  uint32 error_channel = ((error_addr & 0x1FFU) >>2U);

  /* Correct the corrupted location */
  vimRAM->ISR[error_channel] = s_vim_init[error_channel];

  /* Clear Parity Error Flag */
  VIM_PARFLG = 1U;

  /* Disable and enable the highest priority pending channel */
  if (vimREG->FIQINDEX != 0U)
  {
    vec = vimREG->FIQINDEX - 1U;
  }
  else
  {
    vec = vimREG->IRQINDEX - 1U;
  }
  if (vec == 0U)
  {
    vimREG->INTREQ0 = 1U;
    vec = esmREG->IOFFHR - 1U;

    if (vec < 32U)
    {
      esmREG->SR1[0U] = (uint32)1U << vec;
      esmGroup1Notification(vec);
    }
    else if (vec < 64U)
    {
      esmREG->SR1[1U] = (uint32)1U << (vec-32U);
      esmGroup2Notification(vec-64U);
    }
    else if (vec < 96U)
    {
      esmREG->SR4[0U] = (uint32)1U << (vec-64U);
      esmGroup1Notification(vec-32U);
    }
    else
    {
      esmREG->SR4[1U] = (uint32)1U << (vec-96U);
      esmGroup2Notification(vec-64U);
    }
  }
  else if (vec < 32U)
  {
    vimREG->REQMASKCLR0 = (uint32)1U << vec;
    vimREG->REQMASKSET0 = (uint32)1U << vec;
  }
  else if (vec < 64U)
  {
    vimREG->REQMASKCLR1 = (uint32)1U << (vec-32U);
    vimREG->REQMASKSET1 = (uint32)1U << (vec-32U);
  }
  else if (vec < 96U)
  {
    vimREG->REQMASKCLR2 = (uint32)1U << (vec-64U);
    vimREG->REQMASKSET2 = (uint32)1U << (vec-64U);
  }
  else
  {
    vimREG->REQMASKCLR3 = (uint32)1U << (vec-96U);
    vimREG->REQMASKSET3 = (uint32)1U << (vec-96U);
  }
}

- The test code:

{
  uint32* address;

  VIM_PARCTL = 0x0000010A;

  address = (uint32*)(0xFFF82400);
  *address ^= 0x1;

  address = (uint32*)(0xFFF82000);
  *address;
}

The code above causes the parity error (sets VIM_PARFLG and the call-back function runs -- this is observed through a debugger). But once the software leaves the parity error handler, the software throws an undefined instruction exception. Is this normal?

Also, if I try test with a different address, the parity error is not detected (e.g. 0xFFF82404 and 0xFFF82004; or 0xFFF82436 and 0xFFF82036). Has anyone encountered these problems? Can someone let me know if I am doing something wrong or if this behavior is expected?

Thanks.

  • Hello Tran,

    If the TEST bit in PARCTL register is set, the parity bits are mapped to 0xFFF82400. After that, user can force faults into the parity bits. Finally, the parity error can be triggered by reading interrupt vector table (not parity bit) from VIM or CPU. If the parity bit does not match the calculated parity (expected), a parity error is generated and the VIM stores the address of the error in the ADDERR register. The parity flag error (PARFLG) is set.

    When you get the expected parity error in your test code, please clear the parity error flag and restore the content of the VIM. Then test other address.
  • That is exactly what the code I put is doing. The second snippet sets the TEST bit in the PARCTL register and then flips the parity bit. Then it does a read, which sets the parity error flag in the PARFLG register. The fall-back function, which was generated off of HALCoGen 04.06.01, then restores the VIM entry, fixes the parity error, and clears the PARFLG bit. However, after it returns from the function, I get an undefined instruction exception. Have you encountered anything like this before? Also, if I flip the parity bit at 0xFFF82404 (or anything that is not 0xFFF82400), and then do a read on the VIM table entry (in this case, 0xFFF82004), the PARFLG bit is not set.
  • Hello Randy,

    There is no problem to inject parity error at VIM RAM address 0xFFF82000, 0xFFF82004, 0xFFF82038 and set the flag bit of PARFLG register.

    0xFFF82436 will cause problem: Only 32-bit write/read access are allowed on interrupt vector table if parity is required. Non 32-bit access might result in parity errors.
  • Hello Randy,

    This is my vim parity test for 0xFFF82038:

    At address 0xFFF82004:

    The  undefined instruction exception is caused by your handler code.

  • Changing the type of my "address" variable from "uint32*" to "volatile uint32*" worked (the PARFLG is set now). And I accidentally deleted the declaration that the handler was an interrupt (which caused the exception). Thank you for the help!
  • Randy,

    That indicates a compiler optimization at work. You can check the disassembly of the test code to ensure that all writes and reads for this variable are there as expected.

    Regards,
    Sunil
  • Yeah, that's what basically happened. The disassembly shows that the parity bit was flipped but was not written out to RAM until after the read already happened (thus no apparent parity error).