adamgreen / mri

MRI - Monitor for Remote Inspection. The gdb compatible debug monitor for Cortex-M devices.
Apache License 2.0
151 stars 55 forks source link

Issue trying to port DWT code from MRI to personal project. #12

Closed iddq closed 7 years ago

iddq commented 7 years ago

Hello Adam,

Could you please help me in the following strange situation. I'm trying to use some part of your code because I would like to play the DWT function of cortex m4.

I'm initializing DWT and setup one watchpoint in the following way:

     enableDWTandITM();
      initDWT();
      clearMonitorPending();
      enableDebugMonitorAtPriority0();
      enableDWTWatchpoint(0x2001E893, 4, DWT_FUNCTION_READ);

I don't change the priority of the other interrupts to 1 or higher and I've removed the inline modifiers.

This memory address periodically accessed by OSTaskIdleHook function in an uc/OS-II kernel.

The __mriDebugException function is very simple:

void mriDebugException(void) { void *sp; asm__("mov %0,r13" : "=r" (sp)); printf("mri sp: %x\n", sp); }

After some debug exception a hard fault occurs.

The value of sp in __mriDebugException does not change so I think it's not a stack overflow.

Some info from the hard fault handler:

LR [R14] = 804e14b subroutine call return address PC [R15] = 80323ec program counter PSR = 200 BFAR = e000ed38 CFSR = 20000 HFSR = 40000000 DFSR = 4 AFSR = 0 SCB_SHCSR = 0

The values of LR and PC are same like in debug handler so PC points after the instruction that read that address specified at watchpoint.

CFSR bit 17 is one, referring to the documentation it is INVSTATE: Invalid state usage fault. When this bit is set to 1, the PC value stacked for the exception return points to the instruction that attempted the illegal use of the EPSR. This bit is not set to 1 if an undefined instruction uses the EPSR.

0: No invalid state usage fault 1: The processor has attempted to execute an instruction that makes illegal use of the EPSR.

Do you have any idea what's happening?

It is an stm32f405 mcu.

adamgreen commented 7 years ago

After some debug exception a hard fault occurs.

Are you saying that this works for awhile and then you get the hard fault?

LR [R14] = 804e14b subroutine call return address PC [R15] = 80323ec program counter PSR = 200 BFAR = e000ed38 CFSR = 20000 HFSR = 40000000 DFSR = 4 AFSR = 0 SCB_SHCSR = 0

CFSR bit 17 is one, referring to the documentation it is INVSTATE: Invalid state usage fault. When this bit is set to 1, the PC value stacked for the exception return points to the instruction that attempted the illegal use of the EPSR. This bit is not set to 1 if an undefined instruction uses the EPSR.

From what you have reported, it looks like you are somehow corrupting the value of the XPSR. That value you show above of 0x200 definitely doesn't look valid and would lead to this hard fault.

It's pretty hard for me to say much more about it than that since I can't actually see your code. What are you trying to do and why can't you use a debugger to accomplish it?

adamgreen commented 7 years ago
void __mriDebugException(void) {
void *sp;
asm("mov %0,r13" : "=r" (sp));
printf("mri sp: %x\n", sp);
}

I should mention that calling printf() from an exception or interrupt handler is typically not the best thing to do. During bare metal programming, I have seen it lead to heap corruption.

iddq commented 7 years ago

ofcourse the hard fault also happen with an empty __mriDebugException function.

adamgreen commented 7 years ago

Would it be possible for me to look at a .elf/.axf of this failing code? Preferably with complete symbols intact. Without that, there isn't much more I can do since this isn't an issue in MRI itself.

iddq commented 7 years ago

Is it work for you on cortex m4?

iddq commented 7 years ago

If you see the Exception return section in PM0214 documentation you can see you don't need to get the return address from the stack and do that magic.

Now I'm using this simple exception handler and the hard fault problem is not exists anymore.

void DebugMon_Handler()
{
  uint32_t *regs;

  __asm__("TST LR, #4");
  __asm__("ITE EQ");
  __asm__("MRSEQ R0, MSP");
  __asm__("MRSNE R0, PSP");
  __asm__("mov %0,r0" : "=r" (regs));
}
adamgreen commented 7 years ago

Glad you got your code fixed and working.