At91rm9200 startup code analysis

Source: Internet
Author: User

There are four clock sources for at91rm9200:
Slow clock (SLK)
Main clock)
PLLA, pllb
There is a difference between the master clock and the host clock.
The main clock refers to the clock of the input main oscillator.
The host clock (mck) refers to the CPU clock frequency.
The host clock can be selected (the clock selector) as its own clock in four clock sources.
Clock Setting Process

Start some predefined values in the code
;-----------------------------------------------------------------------------
-Arm core mode and status bits ARM Kernel Mode and status bit
;------------------------------------------------------------------------------

Arm_mode_user equ 0x10
Arm_mode_fiq equ 0x11
Arm_mode_irq equ 0x12
Arm_mode_svc equ 0x13
Arm_mode_abort equ 0x17
Arm_mode_undef equ 0x1b
Arm_mode_sys equ 0x1f

I _bit equ 0x80
F_bit equ 0x40
T_bit equ 0x20

;------------------------------------------------------------------
;-Stack area definition stack segment region Definition
;------------------------------------------------------------------
Irq_stack_size equ 0x04
Fiq_stack_size equ 0x04
Abt_stack_size equ 0x04
Und_stack_size equ 0x04
Svc_stack_size equ 0x04
User_stack_size equ 0x100

;----------------------------------------------------------------------------
9200 clock changes after startup
Because the system enters the slow clock Status After resetting, the host clock source is provided by the slow clock. However, because the built-in boot program may have started, you need to reset the slow clock to the host clock source at startup. However, the host clock register requires that the written value cannot be the same as the current value, so it is divided into two steps. The Code is as follows:
// Step 1: Modify pmc_mckr and use pllb as the host clock source.
LDR R1, = at91c_base_pmc; get the base address of PMC
LDR r0, = at91c_pmc_css_pllb_clk
STR r0, [R1, # pmc_mckr]; write a value to the pmc_mckr register
// Check whether the clock settings are successful by testing the 3rd-bit pmc_sr Status Register.
MoV R4, #0x8
Mckr_loop
LDR R3, [R1, # pmc_sr]
And R3, R4, r3
CMP R3, #0x8
BNE mckr_loop

// Step 2: Modify pmc_mckr to select slow clock sck as the host clock source
LDR r0, = at91c_pmc_css_slow_clk: Or: at91c_pmc_pres_clk
STR r0, [R1, # pmc_mckr]
MoV R4, #0x8
Mckr_loop2
LDR R3, [R1, # pmc_sr]
And R3, R4, r3
CMP R3, #0x8
BNE mckr_loop2

// Disable plls to save power consumption.
// In fact, after the machine is reset, plls is disabled by default. However, if a boot program has been run before, plls may have been enabled, therefore, you must disable plls at the beginning of the boot program.
LDR R1, = at91c_base_ckgr; get the base address of CKGR

LDR r0, = at91c_ckgr_diva_0
STR r0, [R1, # ckgr_pllar]: Disable PLLA

LDR r0, = at91c_ckgr_divb_0
STR r0, [R1, # ckgr_pllbr]: Disable pllb

After the preceding actions are completed, the system's host clock source is a slow clock. However, when the system is running normally, it is impossible to use a slow clock as the clock source (for example, PLLA is used as the clock source). Further settings are required.
For the PLL clock, its clock source is the master oscillator clock (that is, the main clock), so you must first open the master clock, the Code is as follows:
// Enable the master clock
// Moscen main clock enable; oscount specifies the number of slow clock cycles as the start time of the main Oscillator
LDR r0, = at91c_ckgr_moscen: Or: at91c_ckgr_oscount
STR r0, [R1, # ckgr_mor]
Select the master clock as the host clock, set the clock frequency, and wait until it is completed in C language. Here, we will continue to use the Assembly for other initialization actions until we run the at91f_lowlevelinit function.
// Set the stack for various processor Modes
; Load the stack base address
Add r0, PC, #-(8 +.-stackdata); R0 = pc-8-. + stackdata, let R0 point to stackdata
Ldmia r0, {r1-r6}; load data from address units pointed to by R0 to R1 ~ R6 Medium

;-Set up supervisor mode and set SVC mode Stack
MSR cpsr_c, # arm_mode_svc: Or: I _bit: Or: f_bit
Bic R1, R1, #3; insure word alignement
MoV sp, R1; init stack sys

;-Set up interrupt mode and set IRQ mode Stack
MSR cpsr_c, # arm_mode_irq: Or: I _bit: Or: f_bit
Bic R2, R2, #3; Ensure Word Alignment
MoV sp, R2; set the IRQ mode Stack pointer

;-Set up fast interrupt mode and set FIQ mode Stack
MSR cpsr_c, # arm_mode_fiq: Or: I _bit: Or: f_bit
Bic R3, R3, #3; insure word alignement
MoV sp, R3; init stack FIQ

;-Set up abort mode and set abort mode Stack
MSR cpsr_c, # arm_mode_abort: Or: I _bit: Or: f_bit
Bic R4, R4, #3; insure word alignement
MoV sp, R4; init stack abort

;-Set up undefined instruction mode and set UNDEF mode Stack
MSR cpsr_c, # arm_mode_undef: Or: I _bit: Or: f_bit
Bic R5, R5, #3; insure word alignement
MoV sp, R5; init stack UNDEF

;-Set up user mode and set UNDEF mode Stack
MSR cpsr_c, # arm_mode_sys: Or: I _bit: Or: f_bit
Bic R6, R6, #3; insure word alignement
MoV sp, R6; init stack UNDEF

B endinitstack

Stackdata
DCD at91_svc_stack_begin
DCD at91_irq_stack_begin
DCD at91_fiq_stack_begin
DCD at91_abt_stack_begin
DCD at91_und_stack_begin
DCD at91_user_stack_begin
Endinitstack

The start time of the primary oscillator is compensated.
LDR r0, = 0x00000010
Looposc
Subs r0, R0, #1
BHI looposc

; Call the C function at91f_lowlevelinit ()
Import at91f_lowlevelinit

LDR r0, = at91f_lowlevelinit
MoV LR, PC
BX R0
;-----------------------------------------------------
; Read/modify/Write CP15 control register
;-----------------------------------------------------
MRC P15, 0, R0, C1, C0, 0; read CP15 control register (CP15 R1) in R0
LDR R3, = 0xc0000080; reset bit: little endian end fast bus mode
LDR R4, = 0xc0000000; Set bit: asynchronous clock mode, not fast bus
Bic r0, R0, r3
ORR r0, R0, r4
MCR P15, 0, R0, C1, C0, 0; write R0 in CP15 control registre (CP15 R1)

;-----------------------------------------------------
; Initialize the C variable
;-----------------------------------------------------

Add R2, PC, #-(8 +.-cinitdata); @ where to read values (relative)
Ldmia R2, {r0, R1, R3, R4}

CMP r0, R1; check that they are different
Beq endrw
Looprw
CMP R1, R3; copy init data
Ldrcc R2, [R0], #4; after loading data from the address indicated by R0 to R2, r2 + 4
Strcc R2, [R1], #4; after the data in R2 is stored to the address pointed to by R1, R1 + 4
BCC looprw
Endrw

MoV R2, #0
Loopzi
CMP R3, R4; zero init
Strcc R2, [R3], #4
BCC loopzi

B endinitc

Cinitdata
Import | image $ Ro $ limit |; ROM code end (= Rom data start)
Import | image $ RW $ base |; base of Ram to initialise
Import | image $ Zi $ base |; base and limit of area
Import | image $ Zi $ limit |; top of zero init segment

DCD | image $ Ro $ limit |; end of ROM code (= start of Rom data)
DCD | image $ RW $ base |; base of Ram to initialise
DCD | image $ Zi $ base |; base and limit of area
DCD | image $ Zi $ limit |; top of zero init segment
Endinitc

;------------------------------------------------------------------------------
;-Branch on C code main function (with interworking)
;----------------------------------------------------
;-Branch must be specified med by An Interworking call as either an arm or thumb
;-Main C function must be supported. This makes the Code not position-
;-Independant. A branch with Link wocould generate errors
;------------------------------------------------------------------------------
Import main
_ Main
_ Main
Export _ main
Export _ main
LDR r0, = Main
MoV LR, PC
BX R0; jump to the mian () function

;------------------------------------------------------------------------------
;-Loop for ever
;---------------
;-End of application. Normally, never occur.
;-Cocould jump on software reset (B 0x0 ).
;------------------------------------------------------------------------------
End
B End
End
Because the master clock is enabled before, but it is not determined whether the start is successful, at91f_lowlevelinit first checks whether the master clock is enabled through the at91f_waitformainclockfrequency function. Code omitted

After the main clock is turned on, you can set the real PLL clock source. The main body of the Code is the at91f_initclocks function.
Since the clock settings must be within a certain range, you must first determine whether the clock meets the requirements. It consists of four steps:
1. Calculate the frequency of the master clock first. For the algorithm, see datasheet.
2. Determine whether the frequency meets the requirements through mainclock and preset values (see the input parameters of the function.
3. If required, write the preset value to the PLL control register.
4. The last step is to modify the host clock source as the required PLL. Likewise, it must be divided into two steps.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.