Файл: Real-time processing with the Philips LPC ARM mcu using GCC and uCOS II RTOS (D.W. Hawkins, 2006).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 479

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

AR1803

May 10, 2006

/ DWARF 2 /

. d e b u g

i n f o

0

: { ( . d e b u g

i n f o . gnu . l i n k o n c e . wi . ) }

. debug

abbrev

0

: { ( . debug

abbrev ) }

. d e b u g

l i n e

0

: { ( . d e b u g

l i n e ) }

. debug

frame

0

: { ( . debug

frame ) }

. d e b u g

s t r

0

: { ( . d e b u g

s t r ) }

. d e b u g

l o c

0

: { ( . d e b u g

l o c ) }

. debug

macinfo 0 : { ( . debug

macinfo ) }

/ SGI/MIPS DWARF 2

e x t e n s i o n s /

. debug

weaknames

0

: {

( . debug

weaknames )

}

. debug

funcnames 0

: {

( . debug

funcnames )

}

. debug

typenames 0

: {

( . debug

typenames )

}

. debug

varnames

0

: {

( . debug

varnames )

}

}

Executable code (.text), and read-only data (.rodata) are linked to Flash addresses. Initialized variables (.data) are linked to SRAM at addresses between symbols _data and _edata, but the values of the initialized variables are stored in Flash after the .text and .rodata sections, at address _etext. The symbols are defined by the linker and are refereed to in the startup routine. The startup routine defines variables (storage) initialized to the linker symbol values. The startup routine then uses the data section symbols to copy values from Flash to SRAM. The application refers to the SRAM versions of the variables. The .bss section contains uninitialized data. The linker combines the .bss sections from the various object files that make up an application, and the linker script defines start (_bss) and end (_ebss) addresses for the uninitialized variables in the final linked application image. The startup code must zero the SRAM address range between _bss and _ebss. The startup code used for the examples is

/ e x 4

s t a r t . s /

. g l o b a l

main

. g l o b a l

s t a r t

/ Symbols d e f i n e d by

t he

l i n k e r s c r i p t

/

. g l o b a l

e t e x t

. g l o b a l

d a t a

. g l o b a l

e d a t a

. g l o b a l

b s s

. g l o b a l

e b s s

. t e x t

. arm

s t a r t :

/ Vectors (8 t o t a l ) /

b r e s e t

/ r e s e t /

b l o o p

/ u n defin ed i n s t r u c t i o n /

b l o o p

/ s o f t w a r e i n t e r r u p t /

b l o o p

/ p r e f e t c h a b o r t /

b l o o p

/ data a b o r t /

checksum /

nop

/ r e s e r v e d

f o r

t he b o o t l o a d e r

bl o o p / IRQ /

bl o o p / FIQ /

16


AR1803 May 10, 2006

/ Setup C runtime :

− copy . data s e c t i o n t o SRAM− c l e a r . b s s

− s et u p s t a c k p o i n t e r− jump t o main

/

r e s e t :

/ Copy . data /

l d r r0 , d a t a

s o u r c e

l d r

r1 ,

d a t a

s t a r t

l d r

r2 ,

d a ta

e n d

c o p y

d a t a :

cmp

r1 , r 2

l d r n e r3 , [ r 0 ] , #4

s t r n e r3 , [ r 1 ] , #4

bne

c o p y

d a t a

/ Clear . b s s /

l d r r0

, =0

l d r

r1 ,

b s s

s t a r t

l d r

r2 ,

b s s

e n d

c l e a r

b s s :

cmp

r1 ,

r

2

s t r n e r0 ,

[ r 1 ] , #4

bne

c l e a r

b s s

/ Stack p o i n t e r / l d r sp , s t a c k a d d r

b l

main

/ Catch

r et u r n from

main /

l o o p :

b

l o o p

/ Constants /

/ LPC SRAM

s t a r t s

at

0x40000000 , and t h e r e i s 32Kb = 8000 h /

s t a c k

a d d r :

. word

0 x40008000

/ Linker symbols /

d a t a

s o u r c e :

. word

e t e x t

d a t a

s t a r t :

. word

d a t a

d a t a

e n d :

. word

e d a t a

b s s

s t a r t :

. word

b s s

b s s

e n d :

. word

e b s s

. end

17


AR1803

May 10, 2006

Example 4(b) uses an initialized vector, so uses the .data section

/ ex4b main . c /

#include ” l e d . h”

static

int l e d

v a l u e [ 2 ] = {0x55 ,

0xAA} ;

int main ( void )

{

i ;

int

l e d

i n i t ( ) ;

while ( 1 ) {

l e d ( l e d

v a l u e [ 0 ] ) ;

for ( i

= 0 ;

i < 0 x50000 ;

i ++);

l e d ( l e d

v a l u e [ 1 ] ) ;

}

for ( i

= 0 ;

i < 0 x50000 ;

i ++);

return 0 ;

}

Example 4(b) can be compiled using

arm-elf-gcc -O2 -mcpu=arm7tdmi -nostartfiles -T../lpc2138_flash.ld \ ex4_start.s ex4b_main.c led.c -o ex4b.elf

(where it is assumed that the LED functions are in the same directory as the example source) and then the sections dumped using

arm-elf-objdump -h ex4b.elf

ex4b.elf: file format elf32-littlearm

Sections:

Idx Name

Size

VMA

LMA

File off

Algn

0

.text

0000012c

00000000

00000000

00008000

2**2

CONTENTS,

ALLOC, LOAD, READONLY, CODE

1

.data

00000008

40000000

0000012c

00010000

2**2

CONTENTS,

ALLOC, LOAD, DATA

2

.bss

00000000

40000008

00000134

00010008

2**0

ALLOC

3

.comment

00000024

00000000

00000000

00010008

2**0

CONTENTS,

READONLY

The .data section LMA (load memory address) in Flash is the address at which the initial values are stored, while the VMA (virtual memory address) in SRAM is the start address at which the application refers to initialized variables.

18


AR1803

May 10, 2006

Table 1: LPC213x PLL control registers (p17 [10])

Name

Description

Access

Reset Value

Address

PLLCON

PLL Control

R/W

0

0xE01F C080

PLLCFG

PLL Configuration

R/W

0

0xE01F C084

PLLSTAT

PLL Status

RO

0

0xE01F C088

PLLFEED

PLL Feed

WO

N/A

0xE01F C08C

3.5Example 5: LPC2138 processor initialization

Processor initialization code for all ARM-based processors follows a similar sequence of steps, however each processor has processor-specific steps. The Philips LPC21xx series of microcontrollers require the following processor initialization steps;

1.Exception vector setup

2.Phase-locked loop setup

3.Memory accelerator module setup

4.Setup stack pointers for each processor mode

5.Copy .data section to SRAM

6.Clear .bss

7.Jump to main

The initialization sequence starts with exception vector setup, since those vectors are located starting at address zero. The phase-locked loop (PLL) and memory accelerator module (MAM) are then setup so that the remaining code runs at the full processor clock speed. The memory accelerator module allows the LPC-microcontroller processor core to fetch instructions e ciently from slower on-chip flash RAM. The LPC213x User Manual [10] describes the PLL and MAM.

3.5.1PLL setup

The MCB2130 evaluation board contains an LPC2138 microcontroller connected to a 12MHz crystal. The PLL control registers are shown in Table 1, the crystal oscillator is described in Section 3.4 (p18 [10]) and the PLL is described in Section 3.7 (p26 [10]). The LPC2138 can operate with a processor clock frequency of up to 60MHz, so with a 12MHz crystal the PLL needs to be configured to e ectively multiply the crystal by 5. The phase-locked loop consists of a phase-detector, a Current Controller Oscillator (CCO), a divide-by-2×P output divider, and a divide-by-M feedback divider that follows the divide-by-2×P divider (so the PLL feedback division for the CCO is 2×M×P) (p28 [10] has a block diagram). The CCO operates over the frequency range 156MHz to 320MHz, and the output divider generates the processor clock frequency. The output divider options are 2, 4, 8, and 16, so for a desired 60MHz processor clock, the CCO can be operated at 240MHz with a divide-by-4 divider setting. The feedback multiplier required to get from 60MHz down to 12MHz is 5. The PLLCFG register settings are then PSEL[1:0] = PLLCFG[6:5] = 01b (P = 2) and MSEL[4:0] = PLLCFG[4:0] = 00100b (M = 5), i.e., PLLCFG = 0100100b = 24h (p29 [10]).

Programming of the PLL requires a special unlock (or feed) sequence, to avoid erroneous programming of the PLL. The PLL takes some time to lock, and so a status bit needs to be polled to

19


AR1803

May 10, 2006

check for lock (or an interrupt can also be generated). Once the PLL is locked, it can be used to clock the processor core. The sequence for programming the PLL (without using an interrupt) is;

1.Write the PLL PSEL and MSEL settings to the PLLCFG register (eg. 24h for the MCB2130).

2.Write 1 to the PLL enable bit 0 (PLLE) in the PLL control register (PLLCON) (p29 [10]).

3.Enable the PLL by writing the feed sequence to the PLLFEED register, i.e., 0xAA then 0x55 (p30 [10]). The feed sequence causes the values written during the first two steps to activate the PLL to lock and generate a 60MHz processor clock.

4.Poll bit 10 (PLOCK) in the PLL status register (PLLSTAT) until it becomes 1 (p30 [10]).

5.Write 1 to the PLL connect bit 1 (PLLC) in the PLL control register (PLLCON) (p29 [10]) (the enable bit, bit 0, should also remain set).

6.Connect the PLL clock to the processor core by writing the feed sequence to the PLLFEED register, i.e., 0xAA then 0x55.

Since the PLL is to be configured prior to stack setup, the PLL initialization sequence needs to be coded in assembler. An alternative processor initialization would be to setup the stacks first, and then call an _init function coded in C, prior to jumping to main. A C-coded PLL initialization sequence is

#define PLLCON (*(volatile unsigned int *)0xE01FC080) #define PLLCFG (*(volatile unsigned int *)0xE01FC084) #define PLLSTAT (*(volatile unsigned int *)0xE01FC088) #define PLLFEED (*(volatile unsigned int *)0xE01FC08C)

#define PLLCON_PLLE

(1 << 0)

#define PLLCON_PLLC

(1 << 1)

#define PLLSTAT_PLOCK

(1 << 10)

#define PLLFEED1

0xAA

#define PLLFEED2

0x55

#define PLLCFG_VALUE

0x24

void pll_init(void)

{

PLLCFG

= PLLCFG_VALUE;

PLLCON

= PLLCON_PLLE;

PLLFEED = PLLFEED1;

PLLFEED = PLLFEED2;

while ((PLLSTAT & PLLSTAT_PLOCK) == 0);

PLLCON

= PLLCON_PLLC|PLLCON_PLLE;

PLLFEED = PLLFEED1; PLLFEED = PLLFEED2;

}

This function can be compiled to assembler, and the output hand-optimized. An assembly-coded version of the PLL initialization is

/* Constants (and storage, used in ldr statements) */ PLLBASE: .word 0xE01FC080

20