其实NBOOT的功能很简单,就是复制、跳转!复制:就是把EBOOT.NB0复制到SDRAM的指定地址。跳转:就是跳到SDRAM的指定地址,去执行EBOOT.NB0。
编代码调试是必经之路,所谓的不经历风雨怎能见彩虹,所以第一步就是让串口输出这些磨砺我们的风雨!
1.设置串口的第一步就是设置系统时钟:
; CLKDIVN
ldr r0,=CLKDIVN
ldr r1,=0x7 ; 0x0 = 1:1:1 , 0x1 = 1:1:2 , 0x2 = 1:2:2 , 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
str r1,[r0]
; delay
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5
; MMU_SetAsyncBusMode FCLK:HCLK= 1:2
ands r1, r1, #0x2
beq %F1
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
1
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((110<<12)+(3<<4)+1) ;Fin=16.9344MHz,Fout=399.65MHz
str r1,[r0]
mov r0, #DELAY
5 subs r0, r0, #1
bne %B5
;Configure UPLL
ldr r0, =UPLLCON
ldr r1, =((60<<12)+(4<<4)+2) ;Fin=16MHz, Fout=48MHz
str r1, [r0]
mov r0, #0x200
5 subs r0, r0, #1
bne %B5
S3C2440有两个PLL:MPLL和UPLL,UPLL专用与USB设备。MPLL用于CPU及其他外围器件。
所以对于串口我们用到的是MPLL时钟,准确的说是MPLL分频后的PCLOCK。
DS是这样说的:通过MPLL会产生三个部分的时钟频率:FCLK、HCLK、PLCK。FCLK用于CPU核,HCLK用于AHB总线的设备(比如SDRAM),PCLK用于APB总线的设备(比如UART)。
根据DS:
MPLL Control Register
Mpll = (2 * m * Fin) / (p * 2S)
m = (MDIV + 8), p = (PDIV + 2), s = SDIV
Input Frequency Output Frequency MDIV PDIV SDIV
16.9344MHz 399.65 MHz 110(0x6e) 3 1
应为我的板子的外部时钟是16.9344M,所以设置MDIV=110,PDIV=3,SDIV=1。从而根据Mpll = (2 * m * Fin) / (p * 2S)
算出Mpll =399.65 MHz。
有因为
ldr r0,=CLKDIVN
ldr r1,=0x7 ; 0x0 = 1:1:1 , 0x1 = 1:1:2 , 0x2 = 1:2:2 , 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 = 1:4:8, 0x6 = 1:3:3, 0x7 = 1:3:6
所以FCLK=Mpll、HCLK=FCLK/3、PLCK=FCLK/6.
应为upll是给USB的时钟,这里暂不讨论。
2.I/O初始化:
//*** PORT H GROUP
//Ports : GPH10 GPH9 GPH8 GPH7 GPH6 GPH5 GPH4 GPH3 GPH2 GPH1 GPH0
//Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
//Binary : 01 , 01 10 , 11 11 , 10 10 , 10 10 , 10 10
rGPHCON = 0x16faaa;
// rGPHCON = 0x165555;
rGPHUP = 0x7ff; // The pull up function is disabled GPH[10:0]
使GPH5 GPH4 GPH3 GPH2 功能为串口。
3.串口代码的实现:
3.1根据之前的总线时钟的设置,设置下面的宏:
#define FCLK 399650000
#define HCLK FCLK/3
#define PCLK HCLK/2
#define BAUD_RATE 115200//设置波特率
3.2初始化:
void Uart_Init(void)
{
int i;
rUFCON0 = 0x0; // FIFO disable
rUMCON0 = 0x0; // AFC disable
rULCON0 = 0x3; // Normal,No parity,1 stop,8 bits
rUCON0 = 0x245;
rUBRDIV0=( (int)(PCLK/(16.0*BAUD_RATE)) -1 );//arm2440的波特率计算公式
for(i=0;i<100;i++); //等待寄存器设置完成
}
3.3具体实现
void Uart_SendByte(int data)
{
if(data=='/n')
{
while(!(UART_STATUS & 0x2));
Delay(10); //because the slow response of hyper_terminal
WRITE_UART('/r');
}
while(!(UART_STATUS & 0x2)); //Wait until THR is empty.//等待串口传输完成,等待直到状态位为1
Delay(10);
WRITE_UART(data);//直接向寄存器写数据,实现传输
}
至此:串口的功能实现了,如果要实现字符串、数字的输出,就是对Uart_SendByte反复调用,不再累赘!!