ARM2440 NBOOT的实现(1调试工具-串口实现)!

时间:2021-10-23 16:10:32

        其实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有两个PLLMPLLUPLLUPLL专用与USB设备。MPLL用于CPU及其他外围器件。

所以对于串口我们用到的是MPLL时钟,准确的说是MPLL分频后的PCLOCK。

DS是这样说的:通过MPLL会产生三个部分的时钟频率:FCLKHCLKPLCKFCLK用于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=MpllHCLK=FCLK/3PLCK=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反复调用,不再累赘!!