Chinaunix首页 | 论坛 | 博客
  • 博客访问: 88178
  • 博文数量: 22
  • 博客积分: 938
  • 博客等级: 准尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-16 21:27
文章存档

2010年(22)

我的朋友

分类: 嵌入式

2010-05-16 10:16:04

经过数个星期的研究,终于完成了一个能在TQ2440开发板上运行的简单bootloader,其实目前功能很简单,就是做一些初始化并在串口显示一段文字,好多功能还没有实现。经过这一番“痛苦”的过程,自己还是有一些感想的:

多看源码

所谓“书读百变,其意自现”,读代码也是同样的道理。多读几遍之后,你就会发现原来让你一看就烦躁、郁闷的代码,其实也并不那么难理解。推荐看开发板提供给我们的代码,以及目前比较流行的通用bootloader(例如UBoot)。

多查文档

对于写这种偏底层的开发,文档时必需的。bootloader大部分的工作其实就是读写各种寄存器(或是某内存单元),其实有时令人郁闷的不是怎么设置一些值,而是查找这些值背后含义以及原理的过程。文档上面写的清清楚楚,就看你能不能找到以及理解背后的原理。

多做试验

bootloader还是很复杂的,一下子就把所有功能实现基于是不可能的。那就要从一个最简单的功能做起,比如LED或是串口输出,以这个目标去做bootloader应该会比较容易实现。可以把开发板提供给我们的bootloader仔细研究研究,注释掉一些功能,看看有什么影响,如果有影响,说明这段代码对于某个功能起了作用,这样可以把研究范围缩小。

 

下面就是bootloader的主要代码,供大家参考,欢迎留言讨论。

startup.s

;CPSR[4:0]中各模式 
USRMODE        *    0X10    ;用户模式 
FIQMODE        *    0X11    ;FIQ模式 
IRQMODE        *    0X12    ;IRQ模式 
SUPMODE        *    0X13    ;管理模式 
ABTMODE        *    0X17    ;中断模式 
UDFMODE        *    0X1B    ;未定义模式 
SYSMODE        *    0X1F    ;系统模式 
MODEMSK        *    0X1F    ;00011111    用于清除[4:0] 
NOINT        *    0XC0    ;AIFT = 1100

;The location of stacks 
_STACK_BASEADDRESS    EQU 0×33ff8000 
USRSTACK            EQU    (_STACK_BASEADDRESS-0×3800)    ;0×33ff4800 ~ 
SUPSTACK            EQU    (_STACK_BASEADDRESS-0×2800)    ;0×33ff5800 ~ 
UDFSTACK            EQU    (_STACK_BASEADDRESS-0×2400)    ;0×33ff5c00 ~ 
ABTSTACK            EQU    (_STACK_BASEADDRESS-0×2000)    ;0×33ff6000 ~ 
IRQSTACK            EQU    (_STACK_BASEADDRESS-0×1000)    ;0×33ff7000 ~ 
FIQSTACK            EQU    (_STACK_BASEADDRESS-0×0)    ;0×33ff8000 ~

;UPLL 
U_MDIV    *    56 
U_PDIV    *    2 
U_SDIV    *    2 
;MPLL 
M_MDIV    *    92 
M_PDIV    *    1 
M_SDIV    *    1

BIT_SELFREFRESH    *    1<<22

    IMPORT  |Image$$RO$$Base|    ; Base of ROM code 
    IMPORT  |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data) 
    IMPORT  |Image$$RW$$Base|   ; Base of RAM to initialise 
    IMPORT  |Image$$ZI$$Base|   ; Base and limit of area 
    IMPORT  |Image$$ZI$$Limit|  ; to zero initialise 
    GET 2440addr.s 
    GET    memcfg.s

    AREA init, CODE, READONLY

    ENTRY 
resetEntry 
    B    reset                    ;复位 
;    B    undefined_instruction    ;未定义指令 
;    B    software_interupt        ;软件中断 
;    B    prefetch_abort            ;预取指令错误 
;    B    data_abort                ;预取数据错误 
;    B    .                        ;保留中断向量 
;    B    irq                        ;irq异常 
;    B    fiq                        ;fiq异常 
    EXPORT    reset 
reset 
;关闭看门狗 
    ldr    r0, =WTCON 
    ldr    r1, =0×0 
    str    r1, [r0]        
;关闭所有中断 
    ldr    r0, =INTMSK 
    ldr r1, =0xFFFFFFFF 
    str r1, [r0] 
    ldr r0, =INTSUBMSK    ;关闭所有子中断 
    ldr r1, =0×7FFFF    ;INTSUBMSK只有[14:0]被使用 
    str    r1, [r0] 
;初始化时钟 
    ldr    r0, =LOCKTIME 
    ldr    r1, =0xFFFFFFFF 
    str r1, [r0] 
    ldr    r0, =CLKDIVN 
    ldr    r1, =5            ;1:4:8 
    str    r1, [r0] 
    ;UPLL 
    ldr    r0, =UPLLCON 
    ldr    r1, =(U_MDIV<<12) + (U_PDIV<<4) + U_SDIV    ;Fin = 12MHz    UCLK = 48MHz 
    str    r1, [r0] 
    nop    ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed. 
    nop 
    nop 
    nop 
    nop 
    nop 
    nop 
    ;MPLL 
    ldr    r0, =MPLLCON 
    ldr    r1, =(M_MDIV<<12) + (M_PDIV<<4) + M_SDIV    ;Fin = 12MHz    PCLK = 400MHz 
    str    r1, [r0] 
;工作在异步模式 
    mrc p15,0,r0,c1,c0,0 
    orr r0,r0,#0xc0000000 
    mcr p15,0,r0,c1,c0,0

;LED显示 
    ldr    r0,=GPBCON 
    ldr    r1,=0×155500 
    str    r1,[r0] 
    ldr    r0,=GPBDAT 
    ldr    r1,=0×0 
    str    r1,[r0]        ;LED=**** 
;初始化SDRAM 
    ldr    r0, =BWSCON 
    ldr    r1, =(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    str    r1, [r0] 
    ldr    r0, =BANKSIZE 
    ldr    r1, =0×32        
    str    r1, [r0]

    ldr r0, =REFRESH 
    ldr    r1, =((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)        
    str    r1, [r0] 
    ldr    r0, =MRSRB6 
    ldr    r1, =0×32 
    str    r1, [r0] 
;初始化堆栈 
    bl    InitStack

;copy_proc_beg 
    adr    r0, resetEntry 
    ldr    r2, BaseOfROM 
    cmp    r0, r2 
    beq    Over    
    ldr r3, TopOfROM 
0    
    ldmia    r0!, {r4-r7} 
    stmia    r2!, {r4-r7} 
    cmp    r2, r3 
    bcc    %B0   

    IMPORT    Main 
Over 
    bl    Main            ;C程序入口 
    b    .

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;;初始化堆栈    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
InitStack 
    mrs    r0, cpsr 
    bic r0, r0, #MODEMSK 
    ;初始化未定义模式栈 
    orr    r1, r0, #UDFMODE|NOINT 
    msr    cpsr_cxsf, r1        ;cpsr_all = cpsr_cxsf 
    ldr    sp, =UDFSTACK 
    ;初始化FIQ栈 
    orr    r1, r0, #FIQMODE|NOINT 
    msr    cpsr_cxsf, r1 
    ldr    sp, =FIQSTACK 
    ;初始化IRQ栈 
    orr    r1, r0, #IRQMODE|NOINT 
    msr    cpsr_cxsf, r1 
    ldr    sp, =IRQSTACK 
    ;初始化ABORT栈 
    orr    r1, r0, #ABTMODE|NOINT 
    msr    cpsr_cxsf, r1 
    ldr    sp, =ABTSTACK 
    ;初始化管理模式栈 
    orr    r1, r0, #SUPMODE|NOINT 
    msr    cpsr_cxsf, r1 
    ldr    sp, =SUPSTACK 
    mov    pc, lr                   

BaseOfROM    DCD    |Image$$RO$$Base| 
TopOfROM    DCD    |Image$$RO$$Limit| 
BaseOfBSS    DCD    |Image$$RW$$Base| 
BaseOfZero    DCD    |Image$$ZI$$Base| 
EndOfBSS    DCD    |Image$$ZI$$Limit| 
    END

 

main.c

#include "2440addr.h" 
#include  
#include  
#include  
#include  
#include

int PCLK = 50000000;        //50MHz

void Port_Init(void) 

    //CAUTION:Follow the configuration order for setting the ports. 
    // 1) setting value(GPnDAT) 
    // 2) setting control register  (GPnCON) 
    // 3) configure pull-up resistor(GPnUP) 

    //32bit data bus configuration  
    //*** PORT A GROUP 
    //Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12  
    //Signal : nFCE nRSTOUT nFRE   nFWE  ALE   CLE  nGCS5 nGCS4 nGCS3 nGCS2 nGCS1 
    //Binary :  1     1      1  , 1   1   1    1   ,  1     1     1     1 
    //Ports  : GPA11   GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1  GPA0 
    //Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0 
    //Binary :  1       1      1      1   , 1       1      1      1   ,  1       1     1      1         
    rGPACON = 0×7fffff;

    //**** PORT B GROUP 
    //Ports  : GPB10    GPB9    GPB8    GPB7    GPB6     GPB5    GPB4   GPB3   GPB2     GPB1      GPB0 
    //Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard 
    //Setting: INPUT  OUTPUT   INPUT  OUTPUT   INPUT   OUTPUT   OUTPUT OUTPUT OUTPUT   OUTPUT    OUTPUT 
    //Binary :   00  ,  01       00  ,   01      00   ,  01       01  ,   01     01   ,  01        01  
    //rGPBCON = 0×000150;(youlong) 
    rGPBCON = 0×015550; 
    rGPBUP  = 0×7ff;     // The pull up function is disabled GPB[10:0]

    //*** PORT C GROUP for youlong 
    //Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7   GPC6   GPC5 GPC4 GPC3  GPC2  GPC1 GPC0 
    //Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND  
    //Binary :  10   10  , 10    10  , 10    10  , 10   10  , 10     10  ,  10   10 , 10     10 , 10   10 
    //rGPCCON = 0xaaaaaaaa;       
    //rGPCUP  = 0xffff;     // The pull up function is disabled GPC[15:0] 
    //*** PORT C GROUP 
    //Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7   GPC6   GPC5 GPC4 GPC3  GPC2  GPC1 GPC0 
    //Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND  
    //Binary :  10   10  , 10    10  , 10    10  , 10   01  , 01     01  ,  01   10 , 10     10 , 10   10 
    rGPCCON = 0xaaa956aa;       
    rGPCUP  = 0xffff;     // The pull up function is disabled GPC[15:0]    

    //*** PORT D GROUP 
    //Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0 
    //Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8 
    //Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10 
    rGPDCON = 0xaaaaaaaa;       
    rGPDUP  = 0xffff;     // The pull up function is disabled GPD[15:0]

    //*** PORT E GROUP 
    //Ports  : GPE15  GPE14 GPE13   GPE12   GPE11   GPE10   GPE9    GPE8     GPE7  GPE6  GPE5   GPE4  
    //Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK IN 
    //Binary :  10     10  ,  10      10  ,  10      10   ,  10      10   ,   10    10  , 10     00  ,     
    //——————————————————————————————————- 
    //Ports  :  GPE3   GPE2  GPE1    GPE0    
    //Signal :  IN     IN    IN      IN  
    //Binary :  00     00  ,  00      00 
    //rGPECON = 0xaaaaaaaa;       
    //rGPEUP  = 0xffff;     // The pull up function is disabled GPE[15:0] 
    rGPECON = 0xa02aa800; // For added AC97 setting      
    rGPEUP  = 0xffff;    

     //*** PORT F GROUP 
    //Ports  : GPF7   GPF6   GPF5   GPF4      GPF3     GPF2  GPF1   GPF0 
    //Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0 
    //Setting: Output Output Output Output    EINT3    EINT2 EINT1  EINT0 
    //Binary :  01      01 ,  01     01  ,     10       10  , 10     10 
    rGPFCON = 0×55aa; 
    rGPFUP  = 0xff;     // The pull up function is disabled GPF[7:0]

    //*** PORT G GROUP 
    //Ports  : GPG15 GPG14 GPG13 GPG12 GPG11    GPG10    GPG9     GPG8     GPG7      GPG6    
    //Signal : nYPON  YMON nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI 
    //Setting: nYPON  YMON nXPON XMON  EINT19  Output   Output   Output   SPICLK1    SPIMOSI1 
    //Binary :   11    11 , 11    11  , 10      01    ,   01       01   ,    11         11 
    //—————————————————————————————– 
    //Ports  :    GPG5       GPG4    GPG3    GPG2    GPG1    GPG0    
    //Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA 
    //Setting:  SPIMISO1  LCD_PWRDN EINT11   nSS0   EINT9    EINT8 
    //Binary :     11         11   ,  10      11  ,  10        10 
    rGPGCON = 0×00a2aaaa;// GPG9 input without pull-up 
    rGPGUP  = 0xffff;    // The pull up function is disabled GPG[15:0]

    //*** 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 :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10 
    rGPHCON = 0×00faaa; 
    rGPHUP  = 0×7ff;    // The pull up function is disabled GPH[10:0]

    // Added for S3C2440X, DonGo 
    //*** PORT J GROUP 
    //Ports  : GPJ12   GPJ11       GPJ10    GPJ9    GPJ8      GPJ7      GPJ6      GPJ5      GPJ4      GPJ3      GPJ2      GPJ1     GPJ0 
    //Signal : CAMRESET CAMPCLKOUT CAMHREF CAMVSYNC CAMPCLKIN CAMDAT[7] CAMDAT[6] CAMDAT[5] CAMDAT[4] CAMDAT[3] CAMDAT[2] CAMDAT[1] CAMDAT[0] 
    //Binary :   10      10       10        10       10        10        10        10       10         10        10        10      10 
    rGPJCON = 0×02aaaaaa; 
    rGPJUP  = 0×1fff;    // The pull up function is disabled GPH[10:0] 
    //External interrupt will be falling edge triggered. 
    rEXTINT0 = 0×22222222;    // EINT[7:0] 
    rEXTINT1 = 0×22222222;    // EINT[15:8] 
    rEXTINT2 = 0×22222222;    // EINT[23:16] 
}

void Uart_Init(int pclk,int baud) 

    int i; 
    if(pclk == 0) 
    pclk    = PCLK; 
    rUFCON0 = 0×0;   //UART channel 0 FIFO control register, FIFO disable 
    rUFCON1 = 0×0;   //UART channel 1 FIFO control register, FIFO disable 
    rUFCON2 = 0×0;   //UART channel 2 FIFO control register, FIFO disable 
    rUMCON0 = 0×0;   //UART chaneel 0 MODEM control register, AFC disable 
    rUMCON1 = 0×0;   //UART chaneel 1 MODEM control register, AFC disable 
//UART0 
    rULCON0 = 0×3;   //Line control register : Normal,No parity,1 stop,8 bits 
     //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0] 
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode 
     //     0          1       0    ,     0          1        0           0     ,       01          01 
     //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling 
    rUCON0  = 0×245;   // Control register 
    rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0 
    /* 
//UART1 
    rULCON1 = 0×3; 
    rUCON1  = 0×245; 
    rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 ); 
//UART2 
    rULCON2 = 0×3; 
    rUCON2  = 0×245; 
    rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );    
*/ 
    for(i=0;i<100;i++); 
}

void Uart_SendByte(int data) 

    if(data==’\n’) 
    { 
        while(!(rUTRSTAT0 & 0×2)); 
        // Delay(1);                 //because the slow response of hyper_terminal 
        WrUTXH0(‘\r’); 
    } 
    while(!(rUTRSTAT0 & 0×2));   //Wait until THR is empty. 
    //  Delay(1); 
    WrUTXH0(data); 
}     

void Uart_SendString(char *pt) 

    while(*pt) 
        Uart_SendByte(*pt++); 
}

void Uart_Printf(char *fmt,…) 

    va_list ap; 
    char string[256];

    va_start(ap,fmt); 
    vsprintf(string,fmt,ap); 
    Uart_Printf(string); 
    va_end(ap); 
}

 

void Led_Display(int data) 

          //Active is low.(LED On) 
          // GPF7  GPF6   GPF5   GPF4 
          //nLED_8 nLED4 nLED_2 nLED_1 
//    rGPFDAT = (rGPFDAT & 0xf) | !((data & 0xf)<<4); 
//    rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);    
          //Active is low.(LED On) 
          // GPF7  GPF6   GPF5   GPF4 
          //nLED_8 nLED4 nLED_2 nLED_1 
    //    rGPFDAT = (rGPFDAT & 0xf) | !((data & 0xf)<<4); 
    rGPBDAT = (rGPBDAT & ~(0xf<<5)) | ((~data & 0xf)<<5);  
    //rGPCDAT = (rGPBDAT & ~(0xf<<5)) | ((~data & 0xf0)<<5);    
}

char* msg = "Hello, embedded!\n"; 
int Main () 

    Led_Display(10); 
    Port_Init(); 
    Uart_Init(0, 115200); 
    Uart_SendString(msg); 
    return 0; 
}

阅读(2402) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~