cancel
Showing results for 
Search instead for 
Did you mean: 

stack problem and privilege mode

ezrab
Associate II
Posted on June 16, 2011 at 14:48

hi.

i am using the STM32f103 chip and i am having all sord of problem that takes me to the Hard Fault inturpt .

when i check the SCB->CFSR register i am getting all sord of errors like :

''the processor has attempted to access a coprocessor.''

or

''The processor has attempted to execute an undefined instruction.''

i read alot and i found that i can change the privilege mode for safty reason so that the software cannot accsess importent register in the cpu i am hoping that it will help me solve the problems.

my question is how do i change that from what i can find i need to change the control register but how can i chnage that what is he called?

i found all that data here by the way:

http://www.st.com/stonline/products/literature/pm/15491.pdf

 

thanks.
23 REPLIES 23
Posted on June 17, 2011 at 14:04

Sounds like you'll just have to handle more faults if you lock it in user mode.

You really need to address the faults you're already seeing properly first. If it's complaining about undefined instructions, you need to see what it's executing and why.

If you have access to TRACE, use that to figure out what's gone wrong. If you don't get some more telemetry/instrumentation into your code and fault handlers, look at stack dumps and call trees, to figure out why the process is getting into this mess.

With stack issues, fill the stack with a visible pattern, view it in a memory window under the debugger, add a guard zone under the stack, and add code to monitor it periodically, or at key check points.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezrab
Associate II
Posted on June 19, 2011 at 07:58

hi thanks for your replay.

i dont have trace ability in the card.

how can i monitor the stack and stack dumps and call trees without debugger only throw RS232.

is it possiable?

how do i:

''

add a guard zone under the stack, and add code to monitor it periodically, or at key check points.''

thanks.

i have added my project .

i tried to attach the file but i get error so here is alink to download it:

thanks very much.

Posted on June 20, 2011 at 02:30

I think you're just going to have to get more sophisticated about buffering the serial port, implementing diagnostics and fault handlers, and the ARM/Cortex-M3 architecture in general. Not sure I can teach you how to do that. I'd recommend Joseph Yiu's book on the Cortex-M3 as a good starting point.

For the Hard Fault Handler, you should look at this thread, about half way down.

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fHardFault%20Exception%20Why%20oh%20why!&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F...

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/HardFault Exception Why oh why!&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=3274

For stack related data, look at how your compiler (IAR), deal with stacks, and stack sizes. Look at the .MAP file, you have a 512 byte stack, located at 0x20000000,0x20000200, if you overflow this stack (ie below 0x20000000) it's going to HARD FAULT, and have a significantly hard time generating any data to do diagnostics with. I would suggest making it substantially larger (>2KB?). Fill 0x20000000..0x20000040 (64 bytes) with some clearly identifiable pattern (0xDEADBEEF,0xCAFECAFE), and check it periodically. If the pattern in this GUARD ZONE is corrupted/changed, then you will know that the stack has descended TOO FAR.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 20, 2011 at 04:31

Your debug output routines are quite a mess. Let's use some subroutines, and some less complex logic to clear them up a tad.

void debug_char(char x)

{

  while(((USART3->SR)&USART_SR_TXE)==0);//if transmit buffer is empty

  USART3->DR = x;

}

void debug_string(char *s)

{

  while(*s) debug_char(*s++);

}

void debug_int(int x)

{

  char str[12];

  char *s;

  if (x < 0) // Negative

  {

    debug_char('-');

    x = -x;

  }

  s = str + sizeof(str);

  *(--s) = 0;

  do

  {

    *(--s) = '0' + (char)(x % 10);

    x = x / 10;

  }while(x);

  debug_string(s);

  debug_char('\n');

}

void debug_mark_stack(void)

{

  unsigned long *p = (unsigned long *)0x20000000; // assuming stack 0x20000000 to 0x20000xxx

  int i;

  for(i=0; i<16; i++) // bottom 64-bytes, give yourself more margin, as required.

    p[i] = 0xDEADBEEF;

}

int debug_check_stack(void)

{

  unsigned long *p = (unsigned long *)0x20000000;

  if (p[15] != 0xDEADBEEF)

  {

    debug_string(''Stack bottoming out, failure imminent\n'');

    return(1);

  }

  return(0);

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezrab
Associate II
Posted on June 20, 2011 at 18:20

hi.

first of all i would like to thank you for your help. your code is alot simpler and smaller then mine .

i defined 0x400 stack size but when i run the simulation on IAR i can see when the code puts the first 0xDEADBEEF in address 0x20000000 i get stack overflow.

when i look at the CSTACK windows i can see this attached image.

 

Posted on June 20, 2011 at 18:49

i defined 0x400 stack size but when i run the simulation on IAR i can see when the code puts the first 0xDEADBEEF in address 0x20000000 i get stack overflow.

 

when i look at the CSTACK windows i can see this attached image.

 

May be they are doing their own stack checking, I'm not using IAR, and I'm not seeing anything helpful in the screen shot.

It's not showing the overflow error, or the bottom of the stack frame, or the failure point in the code.

Suggest you look at the bottom of the stack, and how IAR are marking it.

Try just marking the p[15] location, that might permit you to get an early warning without firing IAR's overflow check. By the time your stack overflows it will be too late to do anything. Normally if it were above the heap it would descend in to that, corrupting it as it goes. Where you have it placed, if it overflows it will exit the RAM and begin to HARD FAULT. Attempts to push processor state will also fail because the stack is unwritable. This is a good case for a system vs user stack, but that's probably a bit over complicated to explain/implement for you now.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezrab
Associate II
Posted on June 21, 2011 at 07:47

thanks for your response.

from what i could figure out the IAR simulator does have stack monitor and becuse the stack filles up from the butttom up it says full stack if put avalue in the first address.

any way i used the code and test it there was no stack overflow.

could it be becuse of DMA error i use it in the ADC and if so how can i check it?

and how can i check what was the last command the CPU tried to do and in what address?

thanks.

by the way is there any good book you know for embeded programing?

Posted on June 21, 2011 at 21:35

It's hard to guess exactly where your problems lie, the key will be to identify the points in the code where the failures occur, and decide if they are caused by bad coding, random corruption, or whatever.

Try improving the hard fault handling to provide specific information, you will have to change the output code if you aren't able to use printf.

After the example by Joseph Yiu, should work for IAR, might need tweaking, I don't use IAR

In startup_stm32fxxx_xx.s

Replace

        PUBWEAK HardFault_Handler

        SECTION .text:CODE:REORDER(1)

HardFault_Handler

        B HardFault_Handler

with

        EXTERN HardFault_Handler_C

        PUBWEAK HardFault_Handler

        SECTION .text:CODE:REORDER(1)

HardFault_Handler

        TST LR, #4

        ITE EQ

        MRSEQ R0, MSP

        MRSNE R0, PSP

        B HardFault_Handler_C

In you main.c or stm32f10x_it.c, or whatever

void HardFault_Handler_C(unsigned int * hardfault_args)

{

  unsigned int stacked_r0;

  unsigned int stacked_r1;

  unsigned int stacked_r2;

  unsigned int stacked_r3;

  unsigned int stacked_r12;

  unsigned int stacked_lr;

  unsigned int stacked_pc;

  unsigned int stacked_psr;

  stacked_r0 = ((unsigned long) hardfault_args[0]);

  stacked_r1 = ((unsigned long) hardfault_args[1]);

  stacked_r2 = ((unsigned long) hardfault_args[2]);

  stacked_r3 = ((unsigned long) hardfault_args[3]);

  stacked_r12 = ((unsigned long) hardfault_args[4]);

  stacked_lr = ((unsigned long) hardfault_args[5]);

  stacked_pc = ((unsigned long) hardfault_args[6]);

  stacked_psr = ((unsigned long) hardfault_args[7]);

  printf (''[Hard fault handler]\n'');

  printf (''R0 = %x\n'', stacked_r0);

  printf (''R1 = %x\n'', stacked_r1);

  printf (''R2 = %x\n'', stacked_r2);

  printf (''R3 = %x\n'', stacked_r3);

  printf (''R12 = %x\n'', stacked_r12);

  printf (''LR = %x\n'', stacked_lr);

  printf (''PC = %x\n'', stacked_pc);

  printf (''PSR = %x\n'', stacked_psr);

  printf (''BFAR = %x\n'', (*((volatile unsigned long *)(0xE000ED38))));

  printf (''CFSR = %x\n'', (*((volatile unsigned long *)(0xE000ED28))));

  printf (''HFSR = %x\n'', (*((volatile unsigned long *)(0xE000ED2C))));

  printf (''DFSR = %x\n'', (*((volatile unsigned long *)(0xE000ED30))));

  printf (''AFSR = %x\n'', (*((volatile unsigned long *)(0xE000ED3C))));

  exit(0); // terminate or die

  return;

}

As for books, for the Cortex-M3, Joseph Yiu's book is a good start. I got to embedded through years of assembler coding and familiarity with micro processors/controllers.

On firmware books by Jack Crenshaw,  Jack Ganssle and Jean Labrosse, are generally pretty good

http://www.alibris.com/booksearch?author=Jack%20Crenshaw&aid=1101896

http://www.alibris.com/booksearch?author=Jack%20G%20Ganssle&aid=1754621

http://www.alibris.com/booksearch?author=Jean%20J%20Labrosse&aid=2822925

I'd probably avoid William Hohl's book on ARM Assembly, nice book, but ARM7 and ARM9 coverage is a couple of decades too late.

Try looking at Embedded systems and programming topics on Amazon, and read a few chapters, see what covers the material/areas you want.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezrab
Associate II
Posted on June 22, 2011 at 10:17

this is the code i used:

void HardFault_Handler_C(unsigned int * hardfault_args)

{

  int byte_temp,byte_temp2,indication;

  unsigned long stacked_r0;

  unsigned long stacked_r1;

  unsigned long stacked_r2;

  unsigned long stacked_r3;

  unsigned long stacked_r12;

  unsigned long stacked_lr;

  unsigned long stacked_pc;

  unsigned long stacked_psr;

  stacked_r0 = ((unsigned long) hardfault_args[0]);

  stacked_r1 = ((unsigned long) hardfault_args[1]);

  stacked_r2 = ((unsigned long) hardfault_args[2]);

  stacked_r3 = ((unsigned long) hardfault_args[3]);

  stacked_r12 = ((unsigned long) hardfault_args[4]);

  stacked_lr = ((unsigned long) hardfault_args[5]);

  stacked_pc = ((unsigned long) hardfault_args[6]);

  stacked_psr = ((unsigned long) hardfault_args[7]);

  debug_string(''[Hard fault handler]'');

  debug_char(0x0d);

  debug_string(''R0 ='');

  debug_long(stacked_r0);

 

   debug_string(''R1 ='');

  debug_long(stacked_r1);

 

   debug_string(''R2 ='');

  debug_long(stacked_r2);

 

   debug_string(''R3 ='');

  debug_long(stacked_r3);

 

   debug_string(''R12 ='');

  debug_long(stacked_r12);

 

  debug_string(''LR ='');

  debug_long(stacked_lr);

 

  debug_string(''PC ='');

  debug_long(stacked_pc);

 

  debug_string(''PSR ='');

  debug_long(stacked_psr);

  debug_string(''BFAR ='');

  debug_long((*((volatile unsigned long *)(0xE000ED38))));

 

   debug_string(''CFSR ='');

  debug_long((*((volatile unsigned long *)(0xE000ED28))));

 

   debug_string(''HFSR ='');

  debug_long((*((volatile unsigned long *)(0xE000ED2C))));

 

   debug_string(''DFSR ='');

  debug_long((*((volatile unsigned long *)(0xE000ED30))));

 

     debug_string(''AFSR ='');

  debug_long((*((volatile unsigned long *)(0xE000ED3C))));

 

 

   GPIOC->ODR&=~0x200;

   GPIOA->ODR&=~0x2000;

while(1)

{

  /* Go to infinite loop when Hard Fault exception occurs */

     if (((USART3->SR)&USART_SR_RXNE)>0)

    {

    byte_temp= USART3->DR;

    if (byte_temp=='p')

    {

      USART3->DR=byte_temp2;

      while(((USART3->SR)&USART_SR_TXE)==0);

      USART3->DR=indication;

    }

    USART3->DR='f';

  }

}

}

void debug_long(unsigned long x)

{

  char str[32];

  char *s;

  s = str + sizeof(str);

  *(--s) = 0;

  do

  {

    *(--s) = '0' + (char)(x % 10);

    x = x / 10;

  }while(x);

  debug_string(s);

  debug_char(0x0d);

}

 here is what i get 10 tryies:

[Hard fault handler]

R0 =0

R1 =74

R2 =134225680

R3 =0

R12 =134226192

LR =134220807

PC =134218150

PSR =2164260864

BFAR =3758157112

CFSR =65536

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =1073811468

R1 =0

R2 =134225680

R3 =0

R12 =134226192

LR =134220807

PC =135702776

PSR =2147483648

BFAR =3758157112

CFSR =256

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =1073811468

R1 =536879356

R2 =134225752

R3 =0

R12 =134226264

LR =134220807

PC =134218370

PSR =2164260864

BFAR =3758157112

CFSR =1024

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =1746356329

R1 =74

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218608

PSR =2164260864

BFAR =4175427689

CFSR =33280

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =4294938477

R1 =2960374715

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218240

PSR =1627389952

BFAR =4294967295

CFSR =33280

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =0

R1 =74

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218050

PSR =2164260864

BFAR =3758157112

CFSR =65536

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =12300288

R1 =3148873732

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =4175388864

PSR =1627389952

BFAR =3758157112

CFSR =1

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =0

R1 =74

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218050

PSR =2164260864

BFAR =3758157112

CFSR =524288

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =0

R1 =74

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218118

PSR =2164260864

BFAR =3758157112

CFSR =524288

HFSR =1073741824

DFSR =0

AFSR =0

[Hard fault handler]

R0 =0

R1 =74

R2 =134225684

R3 =0

R12 =134226196

LR =134220807

PC =134218150

PSR =2164260864

BFAR =3758157112

CFSR =524288

HFSR =1073741824

DFSR =0

AFSR =0

its all in decimal .

what can i see from that?

plus i dont realy understand somthing in the code :

stacked_r0 is defined as ''unsigned int'' but gets avalue of ''unsigned long'' as so all the stacked value.

why?

so i changed them to ''unsigned long''.

thanks for your help.