EmbDev.net

Forum: ARM programming with GCC/GNU tools Preventing function from using a specific CPU register


von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
I have an assembly function which is called by the fault interrupt. 
This assembly code places the stack pointer (SP) into a register (r0). 
This assembly code then calls a C function which has one parameter, and 
the value value of r0 gets passed into it.  The problem is, the C 
function messes with r0 at the beginning and sometimes trashes it.  It 
never returns from this C function since its job is to display fault 
info on an LCD, then the micro must be reset.

So, how can I prevent GCC from using a specific register so its 
integrity is maintained?

von Abdul K. (ehydra)


Rate this post
useful
not useful
I don't know about GCC, but 'register' is the standard.

von (prx) A. K. (prx)


Rate this post
useful
not useful
There is no such thing as a "standard" for an inherently nonstandard 
operation ;-). Nevertheless GCC does have a (very nonstandard) way to 
assign specific registers and it does indeed use the keyword "register". 
See http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html.

Note though that this could turn out to be an answer to the wrong 
question. I do not understand what you really want to achieve. And a 
function should no trash its parameter if it is used later, though it 
could move it to some other place.

von Rolf Magnus (Guest)


Rate this post
useful
not useful
Why does that C function overwrite its own parameters before using them?

von Abdul K. (ehydra)


Rate this post
useful
not useful
A. K. wrote:
> There is no such thing as a "standard" for an inherently nonstandard
> operation ;-). Nevertheless GCC does have a (very nonstandard) way to
> assign specific registers and it does indeed use the keyword "register".
> See http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html.
>

OK, read 'common'.


> Note though that this could turn out to be an answer to the wrong
> question. I do not understand what you really want to achieve. And a
> function should no trash its parameter if it is used later, though it
> could move it to some other place.

An example is Keil C51 and Cypress PSoC. I don't remember the right one.
There is a short parameter passing within registers, and a long 
parameter passing in the 'common' way on the stack. Parameter lists 
exceeding the free register map are loaded on the stack.

If Assembler and C think different, the code crashes!

von mizch (Guest)


Rate this post
useful
not useful
I assume you're talking about AVR CPUs.

Then, r0 is a poor choice for parameter passing, since it is the target 
of some assembly language instructions (lpm and mul come to mind).  They 
overwrite r0 and I doubt any compiler will take care of saving r0 before 
and restoring it after those particular instructions.

von mizch (Guest)


Rate this post
useful
not useful
Sorry, youst see you're taking about an ARM.  Forget my comment above.

von Axel H. (axelh)


Rate this post
useful
not useful
APCS says that function parameters are passed in r0 to r3. And this 
usually works fine when calling C-Code from assembler code. So it 
appears there is a problem with your C function. How does it look like 
and what is the assebler code that is generated by the compiler?

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
I think I need to elaborate a bit.  This is an ARM Cortex-M3.  I'm 
trying to write a fault handler that will display the fault exception 
stack on my LCD.

So I have this function, which is the ISR for any faults:

IntDefaultHandler:
     TST LR, #4
  ITE EQ
  MRSEQ R0, MSP
  MRSNE R0, PSP
  b hard_fault_handler_c


I didn't come up with this strategy as it seems to be a common way of 
writing a fault handler.  But the idea is that the C function will take 
the contents of r0 as the first parameter, which should be the location 
on the stack that contains the fault exception frame.
Initially, the above code was inside a C function using __asm() but GCC 
put some extra instructions at the beginning.  So I moved it to a 
assembly file.

Here's essentially what is in hard_fault_handler_c:


void hard_fault_handler_c(unsigned int * hardfault_args)
{
     unsigned char y[20]; //used for string processing
     //display hardfault_args[0], hardfault_args[1]...hardfault_args[7]
     while(1);  never leave
}


But, in looking at the generated asm I see that GCC is messing with r0:

void hard_fault_handler_c(unsigned int * hardfault_args)
{
   10e30:  b580        push  {r7, lr}
   10e32:  b088        sub  sp, #32
   10e34:  af00        add  r7, sp, #0
   10e36:  6078        str  r0, [r7, #4]
  unsigned char y[20];


What happens sometimes is that hardfault_args is one word, 4 bytes, 
offset from where it should be.  I'm going off the assumption that the 
asm code at the start of hard_fault_handler_c is modifying r0.

So, that's why I'm trying to prevent hard_fault_handler_c from modifying 
r0.  Or, if there's a better way, I'd gladly do that.

von (prx) A. K. (prx)


Rate this post
useful
not useful
The assembly code shown above obvously is not messing around with r0, it 
just saves its contents to some place on the stack. Maybe because there 
is some significant amount of varables handled before the parameter is 
used, so the compiler frees r0 for better use, or maybe because 
optimzation is disabled and the regular unoptimized place of variables 
is in memory.

von (prx) A. K. (prx)


Rate this post
useful
not useful
A failsafe version of a hard fault handler should initialize its stack 
pointer with a known safe value before first use within the handler, 
because one likely reason of a hard fault is an invalid stack pointer 
value.

von (prx) A. K. (prx)


Rate this post
useful
not useful
Are we talking about unimplemented interrupts in general or about the 
CM3's hard fault vector? For unimplemented interrupts, you may safely 
assume a valid stack frame. Not so for true hard faults however, because 
the hard fault handler may get entered because some stack push operation 
by a regular fault handler failed. So it is not safe to assume a 
regular exeption frame on the stack on entry of the hard fault handler.

Look at BFAR.

von (prx) A. K. (prx)


Rate this post
useful
not useful
Correction: The bus fault status register should be consulted prior to 
any assumption on stack contents.

If bus and memory faults are enabled, the same caution could be 
necessary for them as well. IMHO the CM3 core manual isn't very clear in 
this respect.

von Abdul K. (ehydra)


Rate this post
useful
not useful
If it 'sometimes' occur, than think of the possibility of an stack 
overflow.

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Abdul K. wrote:
> If it 'sometimes' occur, than think of the possibility of an stack
> overflow.

I should be more clear on "sometimes".  My stack is definitely not 
overflowing.  I've checked and it's far from hitting the limit.

What I've done is placed artificial bugs in different areas that I can 
trigger selectively.  I write a value to an invalid memory location to 
test the fault handler.  There are three of these artificial bugs.  Two 
of them generate a correct pointer to the stack frame.  The third one 
generates a pointer to a stack from that is offset by 1 word.  It's 
perfectly repeatable.  My code in general is stable; I just want a good 
fault handler in case it does fault.

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
A. K. wrote:
> Are we talking about unimplemented interrupts in general or about the
> CM3's hard fault vector? For unimplemented interrupts, you may safely
> assume a valid stack frame. Not so for true hard faults however, because
> the hard fault handler may get entered because some stack push operation
> by a regular fault handler failed. So it is not safe to assume a
> regular exeption frame on the stack on entry of the hard fault handler.
>
> Look at BFAR.

It would be great if I could just display BFAR, but it never seems to 
contain a valid value.  The only time I've gotten it to display a valid 
value was when I (intentionally) wrote to a peripheral without enabling 
it first.  Otherwise, BFAR contains it's own address after the 
artificial bugs I've introduced (see my previous post about that)

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
A. K. wrote:
> The assembly code shown above obvously is not messing around with r0, it
> just saves its contents to some place on the stack. Maybe because there
> is some significant amount of varables handled before the parameter is
> used, so the compiler frees r0 for better use, or maybe because
> optimzation is disabled and the regular unoptimized place of variables
> is in memory.

Ok, yes you're correct.  I'm not an ARM asm expert and was interpreting 
the str instruction incorrectly.

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Jerry Milner wrote:
> A. K. wrote:
>> Are we talking about unimplemented interrupts in general or about the
>> CM3's hard fault vector? For unimplemented interrupts, you may safely
>> assume a valid stack frame. Not so for true hard faults however, because
>> the hard fault handler may get entered because some stack push operation
>> by a regular fault handler failed. So it is not safe to assume a
>> regular exeption frame on the stack on entry of the hard fault handler.
>>
>> Look at BFAR.
>
> It would be great if I could just display BFAR, but it never seems to
> contain a valid value.  The only time I've gotten it to display a valid
> value was when I (intentionally) wrote to a peripheral without enabling
> it first.  Otherwise, BFAR contains it's own address after the
> artificial bugs I've introduced (see my previous post about that)

Sorry about all the posts.  I'm dealing with the hard, bus, and usage 
fault vectors.

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> It would be great if I could just display BFAR, but it never seems to
> contain a valid value.

Maybe you didn't actually have a bus fault.

> What I've done is placed artificial bugs in different areas that I
> can trigger selectively.  I write a value to an invalid memory
> location to test the fault handler.  There are three of these
> artificial bugs.  Two of them generate a correct pointer to the
> stack frame.  The third one generates a pointer to a stack from that
> is offset by 1 word.  It's perfectly repeatable.

This is great, so can tell us exactly what the respective stack
pointer values were immediately before the fault was triggered and
what the r0 looks like immediately before entering
hard_fault_handler_c(). It might also help to see a little more of
hard_fault_handler_c()'s code.

Note that Cortex-M3 supports optional automatic exception stack
alignment. If the stack was less than eight byte aligned when the
exception occurred, exception entry will subtract four (a word) from
the stack pointer.

--
Marcus
http://www.doulos.com/arm/

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:
> Jerry Milner wrote:
>> It would be great if I could just display BFAR, but it never seems to
>> contain a valid value.
>
> Maybe you didn't actually have a bus fault.
>

I think it is, because CFSR indicates an imprecise bus fault, and if I 
put a unique function in the bus fault location on the interrupt vector 
table, it jumps to it.  However, the plan is to have hard, bus, and 
usage faults vector to the same function.

>> What I've done is placed artificial bugs in different areas that I
>> can trigger selectively.  I write a value to an invalid memory
>> location to test the fault handler.  There are three of these
>> artificial bugs.  Two of them generate a correct pointer to the
>> stack frame.  The third one generates a pointer to a stack from that
>> is offset by 1 word.  It's perfectly repeatable.
>
> This is great, so can tell us exactly what the respective stack
> pointer values were immediately before the fault was triggered and
> what the r0 looks like immediately before entering
> hard_fault_handler_c(). It might also help to see a little more of
> hard_fault_handler_c()'s code.
>

I'll collect this information later today and post here.

As for what is in hard_fault_handler_c(), I'm just using a sprintf type 
function to place the string in "y", then a function I wrote that 
displays "y".
1
usprintf (y, "R0:   0x%08x", hardfault_args[0]);
2
lcd_DspStr(y, LCD_LINE_NUM(20), INVERT_OFF, Terminal6x8);
3
//and repeating for hardfault_args[1], hardfault_args[2], etc


> Note that Cortex-M3 supports optional automatic exception stack
> alignment. If the stack was less than eight byte aligned when the
> exception occurred, exception entry will subtract four (a word) from
> the stack pointer.

I found this information, but am a little confused by it.  At first I 
thought if the value of (in this case) r0 wasn't evenly divisible by 8, 
I'd adjust it by one word.  However that didn't reliably fix it.  So 
then I tried setting STKALIGN during initialization.  That didn't fix it 
either, and actually might have been worse.  I don't know if what I 
tried is correct, but it was how I interpreted it.

>
> --
> Marcus
> http://www.doulos.com/arm/

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> Marcus Harnisch wrote:
>> Maybe you didn't actually have a bus fault.
>
> I think it is, because CFSR indicates an imprecise bus fault, and if I
> put a unique function in the bus fault location on the interrupt vector
> table, it jumps to it.  However, the plan is to have hard, bus, and
> usage faults vector to the same function.

With imprecise faults all bets are off anyway. An imprecise fault may
be pended and can occur way after the offending instruction has
executed. Registers might have changed and therefore the stack might
not contain information that is helpful in nailing down the issue.

So you are saying that two of your injected faults are behaving
nicely. Are these two also triggering imprecise faults? If these two
are precise faults and only the "odd" one is imprecise you are done.

What you also need to tell us is how you make the exceptions reuse the
same handler. Are you putting the same function name into the vector
table with all these exceptions enabled or are you taking advantage of
fault escalation?

>> This is great, so can tell us exactly what the respective stack
>> pointer values were immediately before the fault was triggered and
>> what the r0 looks like immediately before entering
>> hard_fault_handler_c().
>
> I'll collect this information later today and post here.

Thanks.

>> Note that Cortex-M3 supports optional automatic exception stack
>> alignment.
>
> I found this information, but am a little confused by it.  At first I
> thought if the value of (in this case) r0 wasn't evenly divisible by 8,
> I'd adjust it by one word.  However that didn't reliably fix it.

Of course not. If your SW (printf perhaps) depends on an aligned
stack, aligning r0 doesn't help. The stack pointer register (MSP or
PSP needs to be aligned). Since a copy of your stack pointer will be
stored in r0 it'll consequently be aligned, too.

> So then I tried setting STKALIGN during initialization.  That didn't
> fix it either, and actually might have been worse.

In which way?

--
Marcus

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:
> Jerry Milner wrote:
>
> With imprecise faults all bets are off anyway. An imprecise fault may
> be pended and can occur way after the offending instruction has
> executed. Registers might have changed and therefore the stack might
> not contain information that is helpful in nailing down the issue.
>
> So you are saying that two of your injected faults are behaving
> nicely. Are these two also triggering imprecise faults? If these two
> are precise faults and only the "odd" one is imprecise you are done.
>

All three are imprecise.  CFSR is 0x400 and BFAR always contains it's 
own address with any of the three faults.

> What you also need to tell us is how you make the exceptions reuse the
> same handler. Are you putting the same function name into the vector
> table with all these exceptions enabled or are you taking advantage of
> fault escalation?
>

I'm putting the same function name into the vector table.  Although, I 
could just as well not enable the other exceptions and let it escalate 
to the hard fault, if that is preferable.  Actually I was doing that for 
awhile, but now it doesn't make sense to do that if I'm using the same 
handler.


>>> Note that Cortex-M3 supports optional automatic exception stack
>>> alignment.
>>
>> I found this information, but am a little confused by it.  At first I
>> thought if the value of (in this case) r0 wasn't evenly divisible by 8,
>> I'd adjust it by one word.  However that didn't reliably fix it.
>
> Of course not. If your SW (printf perhaps) depends on an aligned
> stack, aligning r0 doesn't help. The stack pointer register (MSP or
> PSP needs to be aligned). Since a copy of your stack pointer will be
> stored in r0 it'll consequently be aligned, too.

I'm not sure if usprintf depends on an aligned stack.  But, in using the 
JTAG debugger in hard_fault_handler_c() I can see that r0 in these cases 
points to the incorrect stack location, at least based upon what the 
stacked PC should approximately be.  When r0 doesn't point to the 
correct location, it's always one word away from what seems like a 
plausible stacked PC value.

>
>> So then I tried setting STKALIGN during initialization.  That didn't
>> fix it either, and actually might have been worse.
>
> In which way?

I'll have to go back and check this one when I can get to the setup 
later, but it seems like r0 was incorrect even for the injected faults 
that previously produced good results.  But, I need to verify this one. 
I had high hopes STKALIGN would fix my problem, but it didn't so I 
abandoned it shortly afterward.

>
> --
> Marcus

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> All three are imprecise.  CFSR is 0x400 and BFAR always contains it's
> own address with any of the three faults.

Imprecise aborts don't update BFAR.

> I'm putting the same function name into the vector table.  Although, I
> could just as well not enable the other exceptions and let it escalate
> to the hard fault, if that is preferable.  Actually I was doing that for
> awhile, but now it doesn't make sense to do that if I'm using the same
> handler.

An escalated imprecise bus fault won't be pended but force the handler
to be called.

> I'm not sure if usprintf depends on an aligned stack.  But, in using the
> JTAG debugger in hard_fault_handler_c() I can see that r0 in these cases
> points to the incorrect stack location, at least based upon what the
> stacked PC should approximately be.  When r0 doesn't point to the
> correct location, it's always one word away from what seems like a
> plausible stacked PC value.

But what did r0 look like before entering hard_fault_handler_c()? In
other words, did r0 ever contain the expected value?

--
Marcus

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:

>
>> I'm not sure if usprintf depends on an aligned stack.  But, in using the
>> JTAG debugger in hard_fault_handler_c() I can see that r0 in these cases
>> points to the incorrect stack location, at least based upon what the
>> stacked PC should approximately be.  When r0 doesn't point to the
>> correct location, it's always one word away from what seems like a
>> plausible stacked PC value.
>
> But what did r0 look like before entering hard_fault_handler_c()? In
> other words, did r0 ever contain the expected value?

Good question.  I'll check this too.  For some reason the registers 
don't always appear in my Eclipse/OpenOCD setup.  I don't know which is 
at fault, but I can get them to appear sometimes by restarting the 
session or restarting Eclipse.

>
> --
> Marcus

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:
>
>> I'm not sure if usprintf depends on an aligned stack.  But, in using the
>> JTAG debugger in hard_fault_handler_c() I can see that r0 in these cases
>> points to the incorrect stack location, at least based upon what the
>> stacked PC should approximately be.  When r0 doesn't point to the
>> correct location, it's always one word away from what seems like a
>> plausible stacked PC value.
>
> But what did r0 look like before entering hard_fault_handler_c()? In
> other words, did r0 ever contain the expected value?

Here's what I found: the value that r0 acquired in IntDefaultHandler 
(the asm ISR) was passed to hardfault_args in hard_fault_handler_c() 
every time intact, and stayed intact.

I actually added a fourth "bug" in a completely different function to 
make things interesting.  It's the exact same errant code as the other 
three bugs.  Below is a summary of how each fault behaves.  I'll number 
each function that contains a bug.  Remember that one function contains 
two faults that can be separately activated; one fault in this function 
is inside an if(), and the second one is inside a corresponding else 
if().  The if() and else if() each have their own local variables that I 
assume would have to be pushed onto the stack.

Function  "Bug" Address   Correct?            Stacked PC        r0
#1            0x100D8       correct             0x100E6    0x20002ED8
#1            0xFF7E        incorrect (in LR)   0x18E0     0x20002ED8
#2            0x5C28        incorrect (in LR)   0xD90      0x20003030
#3            0x3D48        correct             0x3D5A     0x20003028


The second column is the address of the instruction that writes to an 
illegal address and causes the fault.

The third column indicates if the stacked PC value seems correct; if 
not, I indicated what position it appears in.  So, for this data, when 
the stacked PC value didn't seem correct, I instead found the value that 
I believe should have been the PC in the LR position.  In other words, I 
believe that r0/hardfault_args is one word too small in these cases.

The fourth column is the value in the stacked PC position.  In the 
"correct" ones, the stacked PC value is very close to the "bug" address. 
In the "incorrect" ones, I found a similarly close value offset by one, 
in the stacked LR position (if r0/hardfault_args is pointing to the 
stacked r0 value, then stepping thru the rest of the stacked values: r1, 
r2, r3, r12, LR, PC).

The last column is the pointer to the supposed stacked r0 value, in 
other words, r0/hardfault_args.

As for STKALIGN, I tried writing 0x20 to it at initialization, and it 
made no difference.

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> So, for this data, when the stacked PC value didn't seem correct, I
> instead found the value that I believe should have been the PC in
> the LR position. In other words, I believe that r0/hardfault_args
> is one word too small in these cases.

Would that assumption correspond with the other stacked register values?

Try disabling Bus Fault and Mem Manage Fault and escalate them to Hard
Fault. See if that makes a difference.

Again: The observed faults are imprecise and that means the return
address may not be related to the instruction that caused the
abort. The fact that you see a "close" value in stacked lr might just
be a coincidence.

--
Marcus

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:
> Jerry Milner wrote:
>> So, for this data, when the stacked PC value didn't seem correct, I
>> instead found the value that I believe should have been the PC in
>> the LR position. In other words, I believe that r0/hardfault_args
>> is one word too small in these cases.
>
> Would that assumption correspond with the other stacked register values?

I frequently see the same/similar values in the immediate vicinity, but 
can't say for sure how consistent that is unless I start keeping track. 
I do however frequently see 0xfffffff1 or 0xfffffff9 in the word after 
the pointer, and usually see the invalid address I'm writing to in the 
vicinity (0x30000000).


>
> Try disabling Bus Fault and Mem Manage Fault and escalate them to Hard
> Fault. See if that makes a difference.

I'll try that later today when I'm able to get to the setup and I'll 
report back.

>
> Again: The observed faults are imprecise and that means the return
> address may not be related to the instruction that caused the
> abort. The fact that you see a "close" value in stacked lr might just
> be a coincidence.
>

Understood, and I can't safely assume anything.  However, in the case of 
the two faults that are providing incorrect stack pointer values, I 
believe the probability of both containing a plausible stacked PC value 
in LR strictly by chance is fairly small.  Is it possible that LR would 
contain the return address?  The CM3 manual says:

The LR receives the return address from PC when a Branch and
Link (BL) or Branch and Link with Exchange (BLX) instruction is
executed.
The LR is also used for exception return.


Maybe there's a good way to identify more markers I could use, for 
example, if I could display the values of r0-r3 and r12 immediately 
before the faulty line of code, then try to match it up with the stacked 
values?  I'm not sure how well that would work.  It might be worth a try

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> Understood, and I can't safely assume anything.  However, in the case of
> the two faults that are providing incorrect stack pointer values, I
> believe the probability of both containing a plausible stacked PC value
> in LR strictly by chance is fairly small.  Is it possible that LR would
> contain the return address?

I certain special cases perhaps. One instruction causes an imprecise
(asynchronous) fault. A subsequent instruction is a BX lr which
returns from a subroutine. The exception executes right there. If the
timing is just right, I suppose the exception return address (stacked
pc) could be the same as stacked lr.

> The LR is also used for exception return.

Yes, but not as return address. It is used to inform the exception
exit how to return. The return address comes from the stacked pc --
always.

> Maybe there's a good way to identify more markers I could use, for
> example, if I could display the values of r0-r3 and r12 immediately
> before the faulty line of code, then try to match it up with the stacked
> values?  I'm not sure how well that would work.  It might be worth a try

That's what I meant with this:
>> Would that assumption correspond with the other stacked register values?

--
Marcus
http://www.doulos.com/arm/

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Just something to add I discovered.  The stacked PC values that seem to 
be incorrect are in fact the addresses of functions which are called 
very soon or immediately after the faulty line of code.  So this would 
seem to explain things, but LR's purpose must be to contain the return 
address back to the original function.

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Jerry Milner wrote:
> The stacked PC values that seem to be incorrect are in fact the
> addresses of functions which are called very soon or immediately
> after the faulty line of code.

There you go.

> So this would seem to explain things, but LR's purpose must be to
> contain the return address back to the original function.

Not in case of exceptions. It only appears to be the case to keep the
programmers model as simple and straightforward as possible. That way
you can return from exceptions and subroutines the same way. Note that
this is unique to ARM Cortex-M processors. Other ARM cores use a
different model.

--
Marcus

von jrmymllr j. (jrmymllr)


Rate this post
useful
not useful
Marcus Harnisch wrote:

> There you go.
>
>> So this would seem to explain things, but LR's purpose must be to
>> contain the return address back to the original function.
>
> Not in case of exceptions. It only appears to be the case to keep the
> programmers model as simple and straightforward as possible. That way
> you can return from exceptions and subroutines the same way. Note that
> this is unique to ARM Cortex-M processors. Other ARM cores use a
> different model.
>
> --
> Marcus

I disabled the other exceptions, forcing them to escalate to hard 
faults, and get the same results.  So I think it's safe to say this is 
working as it should, but maybe not as I expect!

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.