2013年4月5日 星期五

上電之後-Boot Loader

boot loader,是機器上電後被執行的第一個程式,它主要任務為負責佈置其它程式(系統程式、驅動程式及應用程式)的執行環境,包含CPU的初始化、必要的設備初始化,以及各個程式區段的搬移到正確的記憶体等等。

首先是硬体,電源電流、頻率及和主要線路short/broke.
第一個測試程式:
ICE donwload後:
  • 透過ICE在PC上作遠端除錯,在程式的第一行設中斷點,確定程式有停下來.
  • 檢查CPU的PC(programm counter) register設定是否正確
  • 檢查CPU內部RAM的內容是否和下載的binary file一致
  • 程式的第一行是設定CPU的 status register,執行這一行並檢查其status register如預期改變
  • 單步執行,確認PC register是否有跟著改變。
驗證項目:
  • CPU暫存器操作測試
    •    1: //設定sp

         2: asm("xld.w %15,0x2000");

         3: asm("ld.w %sp,%15");

         4:  

         5: //設定暫存器0x300023的bit 1為1

         6: *(volatile unsigned char*)0x300023|=0x02;

  • stack pointer的設定是否正確,function call 是否可正確執行


    • function call 中的stack


      • function call 時的返回位址記錄

      • function call 的參數傳遞

      • 函數內部的local變數

      • ISR被執行時的cpu status and return address.

    • stack測量方式:在每一個function 前讀取sp值,接著讓測試人員操作所有的功能,最後會得出一個stack曾被使用的最大值.再加上buffer,即為最適合的stack size.( profiling, 可用來統計stack size, function timing, run times, memory usage)




  • 中斷向量表是否正確,中斷向量程式是否可正確運行


    • 將ISR寫入中斷向量表。即中斷系統(boot load)


      • 中斷向量表陣列,並註解每個entry所代表的中斷來源


      •    1: void dummy(void);

           2: 

           3: //define other file,function

           4: extern void boot(void);

           5: extern void drv_isr_timer0 (void);

           6:  

           7: //interrupt vector

           8: const unsigned long vector[]=

           9: {

          10: (unsigned long)boot, //00 reset

          11: (unsigned long)dummy, //01, division by zero

          12: ....

          13: (unsigned long)drv_isr_timer0, //10,timer0

          14: ...

          15: };

          16: 

          17: void dummy(void)

          18: {

          19: //沒有定義之中斷向量表,正常下不會進入

          20: while(1);

          21: }

          22:  

      • 有此是外接中斷控制器,所以先去設定.才可以去測試

      • 設定cpu的"中斷向量表位址暫存器"..有些則是要固定其位址.

      • 設定cpu的中斷控制暫存器,(優先順序, 是否允許中斷產生)

      • 確定中斷被解發後,相應的ISR有被執行.


         1: //isr module

         2:  

         3: void isr_tempate(void)

         4: {

         5: //push all register

         6: asm("pushn %15");

         7: //將alr and ahr 暫存器透過r1存到stack

         8: asm("ld.w %r1,%alr");

         9: asm("ld.w %r0,%alh");

        10: asm("pushn %r1");

        11:  

        12: //call c function,you can change this line

        13: asm("xcall your_isr");

        14:  

        15: //re store the alr ,ahr and rx form stack

        16: asm("popn %r1);

        17: asm("
ld.w %alr,%r1");
  18: asm("
ld.w %ahr,%r0");
  19:  

  20: asm("
popn %r15);
  21: //end ,call interrupt return

  22: asm("reti");

  23: }


  • 中斷優先順序,中斷向量表對應 及設定錯誤位址


  • 記憶体初始化及其操作測試,要保證所有記憶体可正常R/W


    • 對於SDRAM時的參數,如size,speed.

    • 在測試時,需連同bit也需要check. 可以用(0x00,0xFF,0x55 and 0xAA)

    • 以check sum來檢查





          •    1: //for pc

               2: #include <stdio.h>

               3:  

               4: void main(void)

               5: {

               6: file *fp=fopen("image.bin","rb");

               7: unsigned long checksum=0;

               8: int i;

               9: int read_count;

              10:  

              11: while(1)

              12: {

              13: memset(buffer,0,256);

              14: read_count=fread(fp,1,256,buffer);

              15: for(i=0i;i<read_count;i++)

              16:  checksum+=buffer[i];

              17: if(read_count<256)

              18:     break;

              19: }

              20: fclose(fp);

              21: printf("checksum of image bin is %d",checksum);

              22: }

              23:  

              24: //for arm

              25: //function ,calculate ROM checksum(void)

              26: unsigned long calculate_ROM_checksum(void)

              27: {

              28: unsigned long checksum=0;

              29: //point the start address

              30: unsigned char* pointer=0x2000000;

              31: for(i=0;i<(8*1024*1024);i++)

              32:     checksum+=pointer[i];

              33: return checksum;

              34: }

              35:  






              • CPU初始化(boot loader)


                • 設定stack point

                • set status register,for disable interrupt

                • set interrupt vector point

                • 設定cpu的執行狀態(速度)

                • 設定記憶体控制器

                • 設定cpu的操作各記憶体的時序

                • 設定pin 功用(多功能下)




                • 將data載入RAM,對BSS段設定初值;保證其當主程式run時,程式中所有全域變數初始值正確.


                  • 將有設定初值的全域變數,從ROM搬到RAM中.(startup code)

                  • LMA(load memory address) 及 VMA(virtual memory address)


                image

                __START_data_LMA: data在ROM的位址

                __SIZE_DATA: data segement size.

                __START_data: data在RAM的位址


                   1: //link scriptor

                   2: .data__END_bss:AT(__END_rodata)

                   3:     {

                   4:     __START_data=.;

                   5:     *(.data);

                   6:     __END_data=.;

                   7:     }

                   8:  

                   9: //define 可在程式中使用的變數 

                  10: __START_data_LMA=LOADADDR(.data); //LMA

                  11: __SIZE_DATA=_END_data -__START_data;

                  12:  

                  13:  

                  14: //boot.c

                  15: extern unsigned long *__START_data;

                  16: extern unsigned long *__SIZE_data_LMA;

                  17: extern int __SIZE_DATA;

                  18:  

                  19: void copy_data_section(void)

                  20: {

                  21: int i;

                  22: unsigned long* dest=START_data;

                  23: unsigned long* src=START_data_LMA;

                  24: for(i=0;i<(__SIZE_DATA/4);i++)

                  25:  des[i]=src[i];

                  26: }

                設定bss 段(無初始值,全域變數)


                   1: //link scriptor

                   2: .bss 0x00000000:

                   3:     {

                   4:     __START_bss=.;

                   5:     *(.bss);

                   6:     __END_bss=.;

                   7:     }

                   8:  

                   9: //define 可在程式中使用的變數 

                  10: __SIZE_BSS=_END_bss -__START_bss;

                  11:  

                  12:  

                  13: //boot.c

                  14: extern unsigned long *__START_bss;

                  15: extern int __SIZE_bss;

                  16:  

                  17: void copy_bss_section(void)

                  18: {

                  19: int i;

                  20: unsigned long* dest=START_bss; //for vma

                  21: //unsigned long* src=START_data_LMA;

                  22: for(i=0;i<(__SIZE_BSS/4);i++)

                  23:  des[i]=s0;

                  24: }



                ps.NAND flash<硬碟,程式無法在此執行,需 透過command去讀寫.

                    NOR,ROM/Flash,可用指標,給位址來做存取.