EmbeddedRelated.com
Forums

set up exception vectors

Started by Ewout Boks May 23, 2006
Hi,

I was wondering if anyone had seen this (AT91SAM7S256 with arm-elf-gcc):

I tried to set up my exception vectors using the following way:

startup:
ldr pc,[pc,#0x18] // 0x00 Reset
ldr pc,[pc,#0x18] // 0x04 Undefined instruction
ldr pc,[pc,#0x18] // 0x08 Software Interrupt
ldr pc,[pc,#0x18] // 0x0c Prefetch abort
ldr pc,[pc,#0x18] // 0x10 Data abort
nop // 0x14 unused
ldr pc,[pc,#0x18] // 0x18 IRQ, For AIC use ldr
pc,[pc,#-&F20]
ldr pc,[pc,#0x18] // 0x1c FIQ, For AIC use ldr
pc,[pc,#-&F20]
.reset_vector:
b reset_vector
// b .reset_vector
.undef_vector:
b .undef_vector // currently an infinite loop
.swi_vector:
b .swi_vector // currently an infinite
loop
.preabort_vector:
b .preabort_vector // currently an infinite loop
.data_abort:
b .data_abort // currently an infinite
loop
.IRQ:
B OS_CPU_IRQ_ISR

.FIQ:
B OS_CPU_FIQ_ISR
However, when I run this code, after reset it crashes in 0x0c. Does
anyone know why? My assembly looks fine :

00000000 <__exception_vectors>:
0: e59ff018 ldr pc, [pc, #24] ; 20 <__exception_handlers>
4: e59ff018 ldr pc, [pc, #24] ; 24 <.undef_vector>
8: e59ff018 ldr pc, [pc, #24] ; 28 <.swi_vector>
c: e59ff018 ldr pc, [pc, #24] ; 2c <.preabort_vector>
10: e59ff018 ldr pc, [pc, #24] ; 30 <.data_abort>
14: e1a00000 nop (mov r0,r0)
18: e59ff018 ldr pc, [pc, #24] ; 38 <.FIQ>
1c: e59ff018 ldr pc, [pc, #24] ; 3c <.FIQ+0x4>

00000020 <__exception_handlers>:
20: eafffffe b da

00000024 <.undef_vector>:
24: ea000007 b 24 <.undef_vector>

00000028 <.swi_vector>:
28: ea000008 b 28 <.swi_vector>

0000002c <.preabort_vector>:
2c: ea000009 b 2c <.preabort_vector>

00000030 <.data_abort>:
30: ea00000a b 30 <.data_abort>

00000034 <.IRQ>:
34: eafffffe b 0

00000038 <.FIQ>:
38: eafffffe b 0

I went back to branching straight from 0x0 to the reset vector and I
inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine. Why does
the other one crash in 0x0c ?
Best regards,

Ewout
Hi Ewout,

Try this:

startup:
ldr pc, [pc, #0x18] // 0x00 Reset
ldr pc, [pc, #0x18] // 0x04 Undefined Instruction
ldr pc, [pc, #0x18] // 0x08 Software Interrupt
ldr pc, [pc, #0x18] // 0x0c Pre-fetch Abort
ldr pc, [pc, #0x18] // 0x10 Data Abort
nop // 0x14 unused
ldr pc, [pc, #0x18] // 0x18 IRQ, For AIC use ldr pc, [pc, #-0xF20]
ldr pc, [pc, #0x18] // 0x1c FIRQ, For AIC use ldr pc, [pc, #-0xF20]

_vector_table:
.word reset_vector // Address for reset_vector
.word _dummy_exn
.word _dummy_exn
.word _dummy_exn
.word _dummy_exn
.word _dummy_exn
.word OS_CPU_IRQ_ISR
.word OS_CPU_FIQ_ISR

_dummy_exn:
b _dummy_exn

At the moment I believe that your code would be loading 0xEAFFFFFE into the
PC, which will then result in a Pre-fetch abort. Since you do not have
code at 0xEAFFFFFE.

Regards,
Derick

Ewout Boks wrote:
> Hi,
>
> I was wondering if anyone had seen this (AT91SAM7S256 with arm-elf-gcc):
>
> I tried to set up my exception vectors using the following way:
>
> startup:
> ldr pc,[pc,#0x18] // 0x00 Reset
> ldr pc,[pc,#0x18] // 0x04 Undefined instruction
> ldr pc,[pc,#0x18] // 0x08 Software Interrupt
> ldr pc,[pc,#0x18] // 0x0c Prefetch abort
> ldr pc,[pc,#0x18] // 0x10 Data abort
> nop // 0x14 unused
> ldr pc,[pc,#0x18] // 0x18 IRQ, For AIC use ldr
> pc,[pc,#-&F20]
> ldr pc,[pc,#0x18] // 0x1c FIQ, For AIC use ldr
> pc,[pc,#-&F20]
>
>
> .reset_vector:
> b reset_vector
> // b .reset_vector
> .undef_vector:
> b .undef_vector // currently an infinite loop
> .swi_vector:
> b .swi_vector // currently an infinite
> loop
> .preabort_vector:
> b .preabort_vector // currently an infinite loop
> .data_abort:
> b .data_abort // currently an infinite
> loop
> .IRQ:
> B OS_CPU_IRQ_ISR
>
> .FIQ:
> B OS_CPU_FIQ_ISR
>
>
> However, when I run this code, after reset it crashes in 0x0c. Does
> anyone know why? My assembly looks fine :
>
> 00000000 <__exception_vectors>:
> 0: e59ff018 ldr pc, [pc, #24] ; 20 <__exception_handlers>
> 4: e59ff018 ldr pc, [pc, #24] ; 24 <.undef_vector>
> 8: e59ff018 ldr pc, [pc, #24] ; 28 <.swi_vector>
> c: e59ff018 ldr pc, [pc, #24] ; 2c <.preabort_vector>
> 10: e59ff018 ldr pc, [pc, #24] ; 30 <.data_abort>
> 14: e1a00000 nop (mov r0,r0)
> 18: e59ff018 ldr pc, [pc, #24] ; 38 <.FIQ>
> 1c: e59ff018 ldr pc, [pc, #24] ; 3c <.FIQ+0x4>
>
> 00000020 <__exception_handlers>:
> 20: eafffffe b da
>
> 00000024 <.undef_vector>:
> 24: ea000007 b 24 <.undef_vector>
>
> 00000028 <.swi_vector>:
> 28: ea000008 b 28 <.swi_vector>
>
> 0000002c <.preabort_vector>:
> 2c: ea000009 b 2c <.preabort_vector>
>
> 00000030 <.data_abort>:
> 30: ea00000a b 30 <.data_abort>
>
> 00000034 <.IRQ>:
> 34: eafffffe b 0
>
> 00000038 <.FIQ>:
> 38: eafffffe b 0
>
>
>
> I went back to branching straight from 0x0 to the reset vector and I
> inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine. Why does
> the other one crash in 0x0c ?
>
>
> Best regards,
>
> Ewout
>
>
>
>
>
Ewout Boks schrieb:

> I went back to branching straight from 0x0 to the reset vector and I
> inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine. Why does
> the other one crash in 0x0c ?

Additional to what Derick explained, there is no need for the ldr pc,[]
indirection on the SAM7. You can place relative jumps in the vectors.

Note: Even if you map RAM at 0 you can reach the ROM by a "b ".

--
42Bastian
On Wednesday 24 May 2006 17:29, 42Bastian Schick wrote:
> Ewout Boks schrieb:
> > I went back to branching straight from 0x0 to the reset vector and I
> > inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine. Why does
> > the other one crash in 0x0c ?

I've been watching this and it is a pity nobody explained **why** the code
crashed.

When you use
ldr pc,[....]
then the place that is being looked at is treated as an address (ie pc is bei
ng set to that address]. That is why the thing that is being looked at should
be the **address** of the code you want to go to.

What you had in the original code was not the address, but an actual branch
instruction. The ldr pc,[...] tries to treat the branch instruction as an
address and the core will be trying to access an invalid address which causes
a prefetch abort.

It's a subtle distinction, but if you look at the hex values next to an adress
and a branch to an address you will see the difference.

Don't feel bad about this, we've *****all***** been bitten by this one. Anyone
who says otherwise is fibbing!
>
> Additional to what Derick explained, there is no need for the ldr pc,[]
> indirection on the SAM7. You can place relative jumps in the vectors.
>
> Note: Even if you map RAM at 0 you can reach the ROM by a "b ".

Note that this is true for a SAM7 because there is no way to map executable
space outside of the range of an immediate branch.

However..... this does not hold true for all ARMs, so you may as well use the
address table approach and learn the "right" way to do this so that your code
and thinking is transportable to all ARMs.
IMHO, learning ARM is a big investment but is worth it because so many vendors
make ARM parts. You might as well learn to do things that make this
investment transportable.

Charles

>> there is no need for the ldr pc,[] indirection on the SAM7

> Note that this is true for a SAM7 because there is no way to map executable
> space outside of the range of an immediate branch.

> However..... this does not hold true for all ARMs, so you may as well use the
> address table approach and learn the "right" way to do this so that your code

I don't see why indirection is the "right" way. It just costs another 4
byte of flash (or RAM if remap) (and a few cycles more, where this might
be no problem for the exception, but maybe for the SWI vector).

--
42Bastian




Thanks for the information, I got what you said - it is easily
overlooked especially at one in the morning .......

I actually obtained the exception setup code snippet from a ucos-ii port
for arm9, so I assumed that it worked.

Like Derrick said, you don't need to use the ldr pc, [] instruction, but
before that I tried branching directly to OS_CPU_IRQ_ISR (b
OS_CPU_IRQ_ISR at 0x18) but for some reason that didn't work.

Ewout

> Message 11 From: "Charles Manning" m...@actrix.gen.nz Date: Wed May 24, 2006 0:55am(PDT) Subject: Re: set up exception vectors On Wednesday 24 May 2006 17:29, 42Bastian Schick wrote:
>
>>> Ewout Boks schrieb:
>>
>>>> > I went back to branching straight from 0x0 to the reset vector and I
>>>> > inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine. Why does
>>>> > the other one crash in 0x0c ?
> I've been watching this and it is a pity nobody explained **why** the code
> crashed.
>
> When you use
> ldr pc,[....]
> then the place that is being looked at is treated as an address (ie pc is bei
> ng set to that address]. That is why the thing that is being looked at should
> be the **address** of the code you want to go to.
>
> What you had in the original code was not the address, but an actual branch
> instruction. The ldr pc,[...] tries to treat the branch instruction as an
> address and the core will be trying to access an invalid address which causes
> a prefetch abort.
>
> It's a subtle distinction, but if you look at the hex values next to an adress
> and a branch to an address you will see the difference.
>
> Don't feel bad about this, we've *****all***** been bitten by this one. Anyone
> who says otherwise is fibbing!
>
>>>
>>> Additional to what Derick explained, there is no need for the ldr pc,[]
>>> indirection on the SAM7. You can place relative jumps in the vectors.
>>>
>>> Note: Even if you map RAM at 0 you can reach the ROM by a "b ".
> Note that this is true for a SAM7 because there is no way to map executable
> space outside of the range of an immediate branch.
>
> However..... this does not hold true for all ARMs, so you may as well use the
> address table approach and learn the "right" way to do this so that your code
> and thinking is transportable to all ARMs.
> IMHO, learning ARM is a big investment but is worth it because so many vendors
> make ARM parts. You might as well learn to do things that make this
> investment transportable.
>
> _________________________

--- In A..., Ewout Boks wrote:
> Thanks for the information, I got what you said - it is easily
> overlooked especially at one in the morning .......
>
> I actually obtained the exception setup code snippet from a ucos-ii
port
> for arm9, so I assumed that it worked.

Some of these mechanisms will work sometimes, but not always.
>
> Like Derrick said, you don't need to use the ldr pc, [] instruction,
but
> before that I tried branching directly to OS_CPU_IRQ_ISR (b
> OS_CPU_IRQ_ISR at 0x18) but for some reason that didn't work.

What will and won't work can depend too on your memory mapping and how
you have set up the memory address regions.

On SAM7 the flash and SRAM have fixed addresses and the remapped area
can be flipped between them. If you use the remapped area addresses
then things can get a bit confused. For that reason I always use the
unmapped aaddresses with SAM7.

If you use the "b xxxx" instructions then you will get relative jumps.
THis can get screwed up if you use remapped addresses.

The remapping is pretty clean on a SAM7, when compared to some other
parts (eg Atmel FR4xxx parts). I think it is a good idea to try use
mechanisms that are transportable where possible/practical.

I posted an example project in the files area a while ago that show
what I mean.

>
> Ewout
>
> > Message 11 From: "Charles Manning" manningc2@... Date: Wed May
24, 2006 0:55am(PDT) Subject: Re: set up exception vectors On
Wednesday 24 May 2006 17:29, 42Bastian Schick wrote:
> >
> >>> Ewout Boks schrieb:
> >>
> >>>> > I went back to branching straight from 0x0 to the reset
vector and I
> >>>> > inserted LDR PC, [PC, #-0xF20] on 0x18, and that works fine.
Why does
> >>>> > the other one crash in 0x0c ?
> >
> >
> > I've been watching this and it is a pity nobody explained **why**
the code
> > crashed.
> >
> > When you use
> > ldr pc,[....]
> > then the place that is being looked at is treated as an address
(ie pc is bei
> > ng set to that address]. That is why the thing that is being
looked at should
> > be the **address** of the code you want to go to.
> >
> > What you had in the original code was not the address, but an
actual branch
> > instruction. The ldr pc,[...] tries to treat the branch
instruction as an
> > address and the core will be trying to access an invalid address
which causes
> > a prefetch abort.
> >
> > It's a subtle distinction, but if you look at the hex values next
to an adress
> > and a branch to an address you will see the difference.
> >
> > Don't feel bad about this, we've *****all***** been bitten by this
one. Anyone
> > who says otherwise is fibbing!
> >
> >
> >
> >>>
> >>> Additional to what Derick explained, there is no need for the
ldr pc,[]
> >>> indirection on the SAM7. You can place relative jumps in the
vectors.
> >>>
> >>> Note: Even if you map RAM at 0 you can reach the ROM by a "b
".
> >
> >
> > Note that this is true for a SAM7 because there is no way to map
executable
> > space outside of the range of an immediate branch.
> >
> > However..... this does not hold true for all ARMs, so you may as
well use the
> > address table approach and learn the "right" way to do this so
that your code
> > and thinking is transportable to all ARMs.
> >
> >
> > IMHO, learning ARM is a big investment but is worth it because so
many vendors
> > make ARM parts. You might as well learn to do things that make
this
> > investment transportable.
> >
> >
> >
> >
> >
> > _________________________
>