EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2000 startup code - bootloader

Started by Jean-Sebastien Stoezel May 18, 2010
Well it does not look like this works. I get the following linker error:

C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o:(.startup+0x0): relocation
truncat
ed to fit: R_ARM_PC24 against `.text'
C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o: In function `_swi':
(.startup+0x24): undefined reference to `vPortYieldProcessor'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(freer.o): In function `_malloc_trim_r':
mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(makebuf.o): In function `__smakebuf':
makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
makebuf.c:(.text+0x110): undefined reference to `isatty'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(mallocr.o): In function `_malloc_r':
mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(stdio.o): In function `__sclose':
stdio.c:(.text+0xc): undefined reference to `_close_r'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(stdio.o): In function `__sseek':
stdio.c:(.text+0x30): undefined reference to `_lseek_r'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(stdio.o): In function `__swrite':
stdio.c:(.text+0x84): undefined reference to `_lseek_r'
stdio.c:(.text+0xac): undefined reference to `_write_r'
c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
ibc.a(stdio.o): In function `__sread':
stdio.c:(.text+0xd0): undefined reference to `_read_r'
collect2: ld returned 1 exit status
make: *** [rtosdemo.elf] Error 1
What I think this is, is the reset vector in RAM points to flash at 0x10000.
And I think this is too long of a call to handle by the processor. Or is it?

Jean

On Tue, May 18, 2010 at 11:46 AM, Jean-Sebastien Stoezel <
j...@gmail.com> wrote:

> Alright so to relocate the vectors to RAM, it looks like I would have to
> modify the user application as follow:
>
> - set MEMMAP to 0x02 (User RAM Mode. Interrupt vectors are re-mapped to
> Static RAM.)
> - change the loader script so the vector section is located at the
> beginning of the RAM block.
> - I shouldn't have to modify the mode of the CPU
>
> I will try this right away.
> Thanks for your help,
> Jean
> On Tue, May 18, 2010 at 11:28 AM, rtstofer wrote:
>
>> --- In l... ,
>> Jean-Sebastien Stoezel
>>
>> > The first few lines setup the stacks for each mode. By the way, I am not
>> > sure I understand the following lines:
>> > /* msr CPSR_c, #MODE_SYS|I_BIT|F_BIT */ /* User Mode */
>> > msr CPSR_c, #MODE_SYS|F_BIT /* User Mode */
>> > mov sp, r0
>> >
>>
>> OK, this leaves the chip in supervisor mode with the I-Bit clear which
>> enables IRQ interrupts. Note that the F-Bit is set which disables FIQ
>> interrupts.
>>
>> The problems with comments is that they are almost always wrong. Code gets
>> fixed, remarks never do.
>>
>> In the end, you don't care much what the existing boot loader does as long
>> as you are in supervison mode when the loader branches to your entry point.
>>
>> You will have another boot.s file that will set up the stacks, enable
>> interrupts (if you want FIQ) and, most importantly, build the interrupt
>> vector table and copy it to RAM. Then you use MEMMAP to remap the vectors
>> such that the CPU uses your new table.
>>
>> I don't know anything about MEMMAP, I have never used it. But the gist of
>> it is that the interrupt vectors can reside in one of two places: the start
>> of flash or the start of RAM.
>>
>> Make sure your linker file has a dedicated block of ram for the vectors
>> such that it gets initialized but not reallocated for .data or .bss. There
>> must be manye examples of this around but I don't have any.
>>
>> Richard
>>
>>
>>

An Engineer's Guide to the LPC2100 Series

--- In l..., Jean-Sebastien Stoezel wrote:
>
> Well it does not look like this works. I get the following linker error:
>
> C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o:(.startup+0x0): relocation
> truncat
> ed to fit: R_ARM_PC24 against `.text'
> C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o: In function `_swi':
> (.startup+0x24): undefined reference to `vPortYieldProcessor'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(freer.o): In function `_malloc_trim_r':
> mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(makebuf.o): In function `__smakebuf':
> makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
> makebuf.c:(.text+0x110): undefined reference to `isatty'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(mallocr.o): In function `_malloc_r':
> mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(stdio.o): In function `__sclose':
> stdio.c:(.text+0xc): undefined reference to `_close_r'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(stdio.o): In function `__sseek':
> stdio.c:(.text+0x30): undefined reference to `_lseek_r'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(stdio.o): In function `__swrite':
> stdio.c:(.text+0x84): undefined reference to `_lseek_r'
> stdio.c:(.text+0xac): undefined reference to `_write_r'
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> ibc.a(stdio.o): In function `__sread':
> stdio.c:(.text+0xd0): undefined reference to `_read_r'
> collect2: ld returned 1 exit status
> make: *** [rtosdemo.elf] Error 1
> What I think this is, is the reset vector in RAM points to flash at 0x10000.
> And I think this is too long of a call to handle by the processor. Or is it?
>

Yes, the first error has to do with a destination too far to reach.

The reset vector itself shouldn't point to the destination in flash. It should load the PC with the contents of a word in the table following the vectors whose contents point to the destination in flash. This allows a full 32 bit load. Every boot.s I have seen (and there haven't been all that many) use this indirect branch approach.

Next, there is usually a file named something like syscalls.c that provides all of these hardware specific routines that are missing. You might look at the demo code for the LPC2148 here: www.jcwren.com/arm JC implements all of the syscalls - great code BTW. It utilizes just about every feature of the 2148 and implements both a VCOM serial port and a mass storage device. Oh, and it's built around FreeRTOS.

That said, I'll go back to my earlier recommendation about writing a 50 line interrupt driven blinking LED before you try to port a huge package like FreeRTOS. Make sure the fundamentals are understood.

Richard

Thank you for providing this information. I fixed all linker errors except
one:

In function `__swi': (.startup+0x48): undefined reference to
`vPortYieldProcessor' collect2: ld returned 1 exit status
make: *** [rtosdemo.elf] Error 1

__swi is part of the startup call, it handles the SWI interrupt. As per
freeRTOS architecture, it calls vPortYieldProcessor to handle context
switches.

vPortYieldProcessor is defined in portISR.c, which is part of the build. I
can see it compiled, however it looks like vPortYieldProcessor is skimmed
out of the generated object file. All the functions defined in portISR.c
but vPortYieldProcessor appear in the map file.
I turned the optimization off (went from -O3 to -O) but the function still
does not make it to the object file.

Any idea what happening?
On Tue, May 18, 2010 at 1:52 PM, rtstofer wrote:

> --- In l... , Jean-Sebastien
> Stoezel wrote:
> >
> > Well it does not look like this works. I get the following linker error:
> >
> > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o:(.startup+0x0): relocation
> > truncat
> > ed to fit: R_ARM_PC24 against `.text'
> > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o: In function `_swi':
> > (.startup+0x24): undefined reference to `vPortYieldProcessor'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(freer.o): In function `_malloc_trim_r':
> > mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
> > mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
> > mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(makebuf.o): In function `__smakebuf':
> > makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
> > makebuf.c:(.text+0x110): undefined reference to `isatty'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(mallocr.o): In function `_malloc_r':
> > mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
> > mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(stdio.o): In function `__sclose':
> > stdio.c:(.text+0xc): undefined reference to `_close_r'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(stdio.o): In function `__sseek':
> > stdio.c:(.text+0x30): undefined reference to `_lseek_r'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(stdio.o): In function `__swrite':
> > stdio.c:(.text+0x84): undefined reference to `_lseek_r'
> > stdio.c:(.text+0xac): undefined reference to `_write_r'
> >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > ibc.a(stdio.o): In function `__sread':
> > stdio.c:(.text+0xd0): undefined reference to `_read_r'
> > collect2: ld returned 1 exit status
> > make: *** [rtosdemo.elf] Error 1
> >
> >
> > What I think this is, is the reset vector in RAM points to flash at
> 0x10000.
> > And I think this is too long of a call to handle by the processor. Or is
> it?
> > Yes, the first error has to do with a destination too far to reach.
>
> The reset vector itself shouldn't point to the destination in flash. It
> should load the PC with the contents of a word in the table following the
> vectors whose contents point to the destination in flash. This allows a full
> 32 bit load. Every boot.s I have seen (and there haven't been all that many)
> use this indirect branch approach.
>
> Next, there is usually a file named something like syscalls.c that provides
> all of these hardware specific routines that are missing. You might look at
> the demo code for the LPC2148 here: www.jcwren.com/arm JC implements all
> of the syscalls - great code BTW. It utilizes just about every feature of
> the 2148 and implements both a VCOM serial port and a mass storage device.
> Oh, and it's built around FreeRTOS.
>
> That said, I'll go back to my earlier recommendation about writing a 50
> line interrupt driven blinking LED before you try to port a huge package
> like FreeRTOS. Make sure the fundamentals are understood.
>
> Richard
>
>
>
Hi Jean,

I agree with Richard here: Don't do too much in one step.

Check the very simple version first. Just modify the jump for SWI in your bootloader, and I expect FreeRTOS to run.
If you really need the vectors in RAM, do this at a later stage. However, I'm almost certain this will not be required.

Rolf

--- In l..., Jean-Sebastien Stoezel wrote:
>
> Thank you for providing this information. I fixed all linker errors except
> one:
>
> In function `__swi': (.startup+0x48): undefined reference to
> `vPortYieldProcessor' collect2: ld returned 1 exit status
> make: *** [rtosdemo.elf] Error 1
>
> __swi is part of the startup call, it handles the SWI interrupt. As per
> freeRTOS architecture, it calls vPortYieldProcessor to handle context
> switches.
>
> vPortYieldProcessor is defined in portISR.c, which is part of the build. I
> can see it compiled, however it looks like vPortYieldProcessor is skimmed
> out of the generated object file. All the functions defined in portISR.c
> but vPortYieldProcessor appear in the map file.
> I turned the optimization off (went from -O3 to -O) but the function still
> does not make it to the object file.
>
> Any idea what happening?
> On Tue, May 18, 2010 at 1:52 PM, rtstofer wrote:
>
> >
> >
> >
> >
> > --- In l... , Jean-Sebastien
> > Stoezel wrote:
> > >
> > > Well it does not look like this works. I get the following linker error:
> > >
> > > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o:(.startup+0x0): relocation
> > > truncat
> > > ed to fit: R_ARM_PC24 against `.text'
> > > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o: In function `_swi':
> > > (.startup+0x24): undefined reference to `vPortYieldProcessor'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(freer.o): In function `_malloc_trim_r':
> > > mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
> > > mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
> > > mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(makebuf.o): In function `__smakebuf':
> > > makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
> > > makebuf.c:(.text+0x110): undefined reference to `isatty'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(mallocr.o): In function `_malloc_r':
> > > mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
> > > mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(stdio.o): In function `__sclose':
> > > stdio.c:(.text+0xc): undefined reference to `_close_r'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(stdio.o): In function `__sseek':
> > > stdio.c:(.text+0x30): undefined reference to `_lseek_r'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(stdio.o): In function `__swrite':
> > > stdio.c:(.text+0x84): undefined reference to `_lseek_r'
> > > stdio.c:(.text+0xac): undefined reference to `_write_r'
> > >
> > c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > ibc.a(stdio.o): In function `__sread':
> > > stdio.c:(.text+0xd0): undefined reference to `_read_r'
> > > collect2: ld returned 1 exit status
> > > make: *** [rtosdemo.elf] Error 1
> > >
> > >
> > > What I think this is, is the reset vector in RAM points to flash at
> > 0x10000.
> > > And I think this is too long of a call to handle by the processor. Or is
> > it?
> > >
> >
> > Yes, the first error has to do with a destination too far to reach.
> >
> > The reset vector itself shouldn't point to the destination in flash. It
> > should load the PC with the contents of a word in the table following the
> > vectors whose contents point to the destination in flash. This allows a full
> > 32 bit load. Every boot.s I have seen (and there haven't been all that many)
> > use this indirect branch approach.
> >
> > Next, there is usually a file named something like syscalls.c that provides
> > all of these hardware specific routines that are missing. You might look at
> > the demo code for the LPC2148 here: www.jcwren.com/arm JC implements all
> > of the syscalls - great code BTW. It utilizes just about every feature of
> > the 2148 and implements both a VCOM serial port and a mass storage device.
> > Oh, and it's built around FreeRTOS.
> >
> > That said, I'll go back to my earlier recommendation about writing a 50
> > line interrupt driven blinking LED before you try to port a huge package
> > like FreeRTOS. Make sure the fundamentals are understood.
> >
> > Richard
> >
> >
>

Alright,

I've fixed all these linker issues, and I'm compiling a simple
timer-irq-driven blinky but I still can't get the interrupts to go when the
interrupt vectors are relocated to RAM.

I've tried several demo projects, including this application note:
http://www.nxp.com/documents/application_note/AN10254.pdf

In most of the examples I've come across, here is the vector table for both
ROM and RAM modes:

// Runtime Interrupt Vectors
// -------------------------
Vectors:
b _start // reset - _start
ldr pc,_undf // undefined - _undf
ldr pc,_swi // SWI - _swi
ldr pc,_pabt // program abort - _pabt
ldr pc,_dabt // data abort - _dabt
nop // reserved
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
ldr pc,_fiq // FIQ - _fiq

I believe I understand how the IRQs are branched in ROM mode, though I don't
understand how this can work in RAM mode. Since this vector table is located
at 0x40000000, how can we fetch the proper VIC address using that offset???

I've seen this RAM based code used in demo code for freeRTOs, NXP demo code
and other projects on the yahoo group's files. I understand it will work if
you run from RAM, with the ROM vector table is identical as this one (easy
to do if you've programmed your uc at least once in ROM mode), and you don't
modify memmap to relocate the vectors. But I don't get it if you relocate
the vector table.

Anyhow I have been able to run a simple RAM based program with this.

Jean
On Wed, May 19, 2010 at 4:08 AM, rolf_meeser wrote:

> Hi Jean,
>
> I agree with Richard here: Don't do too much in one step.
>
> Check the very simple version first. Just modify the jump for SWI in your
> bootloader, and I expect FreeRTOS to run.
> If you really need the vectors in RAM, do this at a later stage. However,
> I'm almost certain this will not be required.
>
> Rolf
> --- In l... , Jean-Sebastien
> Stoezel wrote:
> >
> > Thank you for providing this information. I fixed all linker errors
> except
> > one:
> >
> > In function `__swi': (.startup+0x48): undefined reference to
> > `vPortYieldProcessor' collect2: ld returned 1 exit status
> > make: *** [rtosdemo.elf] Error 1
> >
> > __swi is part of the startup call, it handles the SWI interrupt. As per
> > freeRTOS architecture, it calls vPortYieldProcessor to handle context
> > switches.
> >
> > vPortYieldProcessor is defined in portISR.c, which is part of the build.
> I
> > can see it compiled, however it looks like vPortYieldProcessor is skimmed
> > out of the generated object file. All the functions defined in portISR.c
> > but vPortYieldProcessor appear in the map file.
> > I turned the optimization off (went from -O3 to -O) but the function
> still
> > does not make it to the object file.
> >
> > Any idea what happening?
> >
> >
> > On Tue, May 18, 2010 at 1:52 PM, rtstofer wrote:
> >
> > >
> > >
> > >
> > >
> > > --- In l... > 40yahoogroups.com>, Jean-Sebastien
>
> > > Stoezel wrote:
> > > >
> > > > Well it does not look like this works. I get the following linker
> error:
> > > >
> > > > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o:(.startup+0x0):
> relocation
> > > > truncat
> > > > ed to fit: R_ARM_PC24 against `.text'
> > > > C:\DOCUME~1\DEVELO~1\LOCALS~1\Temp/cciOaaaa.o: In function `_swi':
> > > > (.startup+0x24): undefined reference to `vPortYieldProcessor'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(freer.o): In function `_malloc_trim_r':
> > > > mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
> > > > mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
> > > > mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(makebuf.o): In function `__smakebuf':
> > > > makebuf.c:(.text+0x3c): undefined reference to `_fstat_r'
> > > > makebuf.c:(.text+0x110): undefined reference to `isatty'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(mallocr.o): In function `_malloc_r':
> > > > mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
> > > > mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(stdio.o): In function `__sclose':
> > > > stdio.c:(.text+0xc): undefined reference to `_close_r'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(stdio.o): In function `__sseek':
> > > > stdio.c:(.text+0x30): undefined reference to `_lseek_r'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(stdio.o): In function `__swrite':
> > > > stdio.c:(.text+0x84): undefined reference to `_lseek_r'
> > > > stdio.c:(.text+0xac): undefined reference to `_write_r'
> > > >
> > >
> c:/winarm/winarm-20060606/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\l
> > > > ibc.a(stdio.o): In function `__sread':
> > > > stdio.c:(.text+0xd0): undefined reference to `_read_r'
> > > > collect2: ld returned 1 exit status
> > > > make: *** [rtosdemo.elf] Error 1
> > > >
> > > >
> > > > What I think this is, is the reset vector in RAM points to flash at
> > > 0x10000.
> > > > And I think this is too long of a call to handle by the processor. Or
> is
> > > it?
> > > >
> > >
> > > Yes, the first error has to do with a destination too far to reach.
> > >
> > > The reset vector itself shouldn't point to the destination in flash. It
> > > should load the PC with the contents of a word in the table following
> the
> > > vectors whose contents point to the destination in flash. This allows a
> full
> > > 32 bit load. Every boot.s I have seen (and there haven't been all that
> many)
> > > use this indirect branch approach.
> > >
> > > Next, there is usually a file named something like syscalls.c that
> provides
> > > all of these hardware specific routines that are missing. You might
> look at
> > > the demo code for the LPC2148 here: www.jcwren.com/arm JC implements
> all
> > > of the syscalls - great code BTW. It utilizes just about every feature
> of
> > > the 2148 and implements both a VCOM serial port and a mass storage
> device.
> > > Oh, and it's built around FreeRTOS.
> > >
> > > That said, I'll go back to my earlier recommendation about writing a 50
> > > line interrupt driven blinking LED before you try to port a huge
> package
> > > like FreeRTOS. Make sure the fundamentals are understood.
> > >
> > > Richard
> > >
> > >
> > >
> >
>
--- In l..., Jean-Sebastien Stoezel wrote:
>
> Alright,
>
> I've fixed all these linker issues, and I'm compiling a simple
> timer-irq-driven blinky but I still can't get the interrupts to go when the
> interrupt vectors are relocated to RAM.
>
> I've tried several demo projects, including this application note:
> http://www.nxp.com/documents/application_note/AN10254.pdf
>
> In most of the examples I've come across, here is the vector table for both
> ROM and RAM modes:
>
> // Runtime Interrupt Vectors
> // -------------------------
> Vectors:
> b _start // reset - _start
> ldr pc,_undf // undefined - _undf
> ldr pc,_swi // SWI - _swi
> ldr pc,_pabt // program abort - _pabt
> ldr pc,_dabt // data abort - _dabt
> nop // reserved
> ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
> ldr pc,_fiq // FIQ - _fiq
>
> I believe I understand how the IRQs are branched in ROM mode, though I don't
> understand how this can work in RAM mode. Since this vector table is located
> at 0x40000000, how can we fetch the proper VIC address using that offset???
>
> I've seen this RAM based code used in demo code for freeRTOs, NXP demo code
> and other projects on the yahoo group's files. I understand it will work if
> you run from RAM, with the ROM vector table is identical as this one (easy
> to do if you've programmed your uc at least once in ROM mode), and you don't
> modify memmap to relocate the vectors. But I don't get it if you relocate
> the vector table.
>
> Anyhow I have been able to run a simple RAM based program with this.
>
> Jean
>

Ah! Light comes on...

Clearly that will be the wrong address for the VIC. You can calculate the proper address and change the instruction. I think you can still reach the VIC.

You just need to subtract 0x00010000 more so
ldr pc,[pc,#-0x10FF0] // IRQ - read the VIC

The idea is to know where the PC is pointing when the subtraction is done and come up with a constant that, when subtracted from the PC, results in 0xFFFF F030 to get to the VICVectAddr register.

Richard

Jean-Sebastien Stoezel wrote:
> I believe I understand how the IRQs are branched in ROM mode, though I
> don't understand how this can work in RAM mode. Since this vector table
> is located at 0x40000000, how can we fetch the proper VIC address using
> that offset???

Because interrupt vector table is always at address zero - i.e. on IRQ the CPU
jumps always to 0x00000018. Mapping the table into the RAM means that RAM
locations 0x40000000-0x4000003F are also seen at 0x00000000-0x0000003F. Read UM
4-7.

--

Timo

> Ah! Light comes on...
>
> Clearly that will be the wrong address for the VIC. You can calculate the proper address and change the instruction. I think you can still reach the VIC.
>
> You just need to subtract 0x00010000 more so
> ldr pc,[pc,#-0x10FF0] // IRQ - read the VIC
>
> The idea is to know where the PC is pointing when the subtraction is done and come up with a constant that, when subtracted from the PC, results in 0xFFFF F030 to get to the VICVectAddr register.
>
> Richard
>

Well, that was wrong!

The vectors can either be at the start of RAM or the start of Flash but not at 0x10000. My bad...

However, there is another way to do the same thing and get an interrupt wrapper which will allow nested interrupts which the standard handling does not. I'm not sure how this interacts with FreeRTOS but that isn't the point here (in my narrow view).

Here are the vectors and the branch table (position independent):

_vectors:
ldr PC, Reset_Addr
ldr PC, Undef_Addr
ldr PC, SWI_Addr
ldr PC, PAbt_Addr
ldr PC, DAbt_Addr
nop
ldr PC, IRQ_Addr
ldr PC, FIQ_Addr

Reset_Addr: .word Reset_Handler
Undef_Addr: .word UNDEF_Routine
SWI_Addr: .word SWI_Routine
PAbt_Addr: .word UNDEF_Routine
DAbt_Addr: .word UNDEF_Routine
IRQ_Addr: .word IRQ_Wrapper
FIQ_Addr: .word FIQ_Routine
.word 0 /* round out the space */

All of the above must be in RAM but the destinations can be wherever. The IRQ_Wrapper COULD be the address of a routine in Flash like:

IRQ_Wrapper:

stmfd sp!, { lr } /* save return address on IRQ stack */
mrs lr, spsr /* use lr to save spsr_irq */
stmfd sp!, { r4-r5, lr } /* save work regs & spsr on stack */

ldr r4, =VICVECTADDR /* get the ISR address from VIC */
ldr r5, [r4]

msr cpsr_c, #MODE_SVC|F_BIT /* supervisor mode, interrupts ON */

stmfd sp!, { r0-r3, r12, lr } /* save work regs & lr_svc on stack */
mov lr, pc /* set return to common exit of ISR */

mov pc, r5 /* go handle the interrupt */

ldmfd sp!, { r0-r3, r12, lr } /* restore regs & lr_svc */

msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ mode, interrupts OFF */

str lr, [r4] /* update VICVectAddr */

ldmfd sp!, { r4-r5, lr } /* restore work regs and spsr_irq */
msr spsr_cxsf, lr /* put back spsr_irq */
ldmfd sp!, { lr } /* restore return address */

subs pc, lr, #0x4 /* return, restoring CPSR from SPSR */
.endfunc

You wouldn't have to use the entire wrapper (although I would) but it does show how to read the VICVectAddr. Note that it uses the IRQ stack so be certain that some space is allocated.

Richard

Hello,
another approach could be to "simulate" RTOS processor-based SWI with a VIC-based IRQ. In LPC2xxx VIC, interrupt slot 1 is explicitly reserved for software interrupt (btw, you can use any of other unused IRQs). You just need to configure VIC so that IRQ#1 points to vPortYieldProcessor, and portYIELD() is coded to trigger SoftInt#1.
This way you can leave the original SFE Bootloader as is, and you don't have to use RAM vectors / MEMMAP and so on. The cost is a bit more latency.
Bye

Hello,

Thank you for all the feedback. Eventually I got the RAM based exceptions to
work.
I am now copying the vector section to RAM and setting the MCU to use
relocated vectors.

Thanks for your help,
Jean
As explained earlier the code is relocated at 0x10000, so the exceptions are
located at this offset. Though they will never get called from there. So
what I've done is copy the relocated

On Thu, May 20, 2010 at 3:45 AM, suppgrg wrote:

> Hello,
> another approach could be to "simulate" RTOS processor-based SWI with a
> VIC-based IRQ. In LPC2xxx VIC, interrupt slot 1 is explicitly reserved for
> software interrupt (btw, you can use any of other unused IRQs). You just
> need to configure VIC so that IRQ#1 points to vPortYieldProcessor, and
> portYIELD() is coded to trigger SoftInt#1.
> This way you can leave the original SFE Bootloader as is, and you don't
> have to use RAM vectors / MEMMAP and so on. The cost is a bit more latency.
> Bye
>
>
>

The 2024 Embedded Online Conference