1. 程式人生 > >TMS320C6713燒寫Flash的通用方法

TMS320C6713燒寫Flash的通用方法

1 你必須知道的TMS320C6000啟動過程

這部分內容在我的另一篇部落格

有提到過,這裡重新摘錄一遍。

如上圖

  • 在Device Reset階段:裝置初始化為預設狀態,大部分三態輸出都配置為高阻態。
  • 在CPU Reset階段:從RS上升沿處開始(這個時候,HD[4:3]配置啟動模式,HD8配置大小端模式,CLKMODE配置輸入時鐘源,根據HPI_EN配置外設功能),處理器檢查啟動模式HD[4:3],啟動bootloader程式。

HD43

從上圖可以看出,CE1地址空間必需連線Flash晶片才能使用外部Flash引導模式,在電路設計時要注意。

若HD[4:3]=10(本文的操作環境基於此),EDMA自動將CE1起始位置的1KB程式碼拷貝到內部程式儲存器的0地址,這部分功能是由硬體完成的,稱一級引導Bootloader

因此,外部Flash啟動的最簡單的想法就是:把要執行的程式放到CE1的起始1KB地址空間。這樣只要設定HD[4:3]=10就能自啟動了。那這麼簡單,還有討論本文的必要嗎?

呃,如果你的思維還停留在小孩子過家家的程度,唉。。。1KB?1KB才能存多少程式碼?要是程式碼量超過1KB呢?這正是本文要探討的問題的初衷:程式程式碼>1KB,如何讓C6713的程式從外部Flash自啟動?

這就涉及另一個Bootloader了,我們稱之為二級引導Bootloader(說白了就是一段小程式)。二級Bootloader作用有:(1)在上電覆位後將使用者的應用程式從Flash拷貝到RAM中執行;(2)跳轉到應用程式的入口函式處。

二級Bootloader的執行要由一級Bootloader拷貝到RAM中執行,這就明白了,二級Bootloader必須放在外部Flash的起始的1KB位置處。

我們簡要的用個圖描述下所謂的二級Bootloader的自啟動過程及主要思路。

要完成這個過程,

  • 首先要編寫一段稱為2 Level Bootloader的啟動程式碼並燒寫到Flash的初始1KB地址處(DSP6713的CE1起始地址為0x90000000),1 Level Bootloader將該程式碼拷貝到RAM的起始0地址,開始執行。
  • 燒寫使用者程式到0x90000400開始的Flash地址處
  • 2 Level Bootloader將0x90000400開始的使用者程式碼拷貝到RAM的0x400地址處
  • 2 Level Bootloader呼叫_c_int00使用者入口程式,然後呼叫main函式開始執行使用者程式碼

關於_c_int00的介紹也請參考[DSP TMS320C6000基礎學習(7)—— Bootloader與VectorTable]本文所有操作的前提是您已經配置好了中斷向量表(這樣在呼叫_c_int00時才能正確的進入到使用者程式)。

2 編寫二級Bootloader

先巨集定義一下EMIF相關的暫存器,因為我們要讀Flash,所以在二級載入程式執行前要配置EMIF暫存器,

;
;  ======== c6713_emif.s62 ========
;
            .title  "Flash bootup utility"

; global EMIF symbols defined for the c671x family
            .include        boot_c671x.h62

;EMIF Register Addresses for c671x family  
EMIF_GCTL       .equ  0x01800000  ;EMIF global control
EMIF_CE1        .equ  0x01800004  ;address of EMIF CE1 control reg.
EMIF_CE0        .equ  0x01800008  ;EMIF CE0control
EMIF_CE2        .equ  0x01800010  ;EMIF CE2control
EMIF_CE3        .equ  0x01800014  ;EMIF CE3control
EMIF_SDRAMCTL   .equ  0x01800018  ;EMIF SDRAM control
EMIF_SDRAMTIM   .equ  0x0180001c  ;EMIF SDRAM timer
EMIF_SDRAMEXT   .equ  0x01800020  ;EMIF SDRAM extension

; EMIF Register Values specifically for 6713 DSK
EMIF_GCTL_V     .equ  0x00000078  ;
EMIF_CE0_V      .equ  0xffffff23  ;EMIF CE0 SDRAM
EMIF_CE1_V      .equ  0xffffff13  ;EMIF CE1 Flash 8-bit
EMIF_CE2_V      .equ  0xffffbf93 ;EMIF CE2 Daughtercard 32-bit async
EMIF_CE3_V      .equ  0xffffff13  ;EMIF CE3 Daughtercard 32-bit async
EMIF_SDRAMCTL_V .equ  0x53115000  ;EMIF SDRAM control
EMIF_SDRAMTIM_V .equ  0x00000578  ;SDRAM timing (refresh)
EMIF_SDRAMEXT_V .equ  0x000a8529  ;SDRAM extended control

巨集定義的EMIF暫存器宣告為全域性符號,.global與C語言中的extern效果一致,宣告為外部符號。

;
;  ======== boot_c671x.h62 ========
;

    .if ($isdefed("BOOT_C671X_") = 0)  ; prevent multiple includes of this file
BOOT_C671X_ .set    1

; EMIF Register Addresses for c671x family         
        .global EMIF_GCTL         ;EMIF global control
        .global EMIF_CE1          ;address of EMIF CE1 control reg.
        .global EMIF_CE0          ;EMIF CE0control
        .global EMIF_CE2          ;EMIF CE2control
        .global EMIF_CE3          ;EMIF CE3control
        .global EMIF_SDRAMCTL     ;EMIF SDRAM control
        .global EMIF_SDRAMTIM     ;EMIF SDRAM timer
        .global EMIF_SDRAMEXT     ;EMIF SDRAM extension

; EMIF Register Values for c671x family
        .global EMIF_GCTL_V       ;
        .global EMIF_CE0_V        ;EMIF CE0 SDRAM
        .global EMIF_CE1_V        ;EMIF CE1 Flash 8-bit
        .global EMIF_CE2_V        ;EMIF CE2 Daughtercard 32-bit async
        .global EMIF_CE3_V        ;EMIF CE3 Daughtercard 32-bit async
        .global EMIF_SDRAMCTL_V   ;EMIF SDRAM control
        .global EMIF_SDRAMTIM_V   ;SDRAM timing (refresh)
        .global EMIF_SDRAMEXT_V   ;SDRAM extended control

    .endif      ; if BOOT_C671X_ is not defined

下面的程式碼段名.boot_load,你將在之後的cmd檔案中看到它。

程式碼首先對EMIF進行初始化,然後在copy_section_top中讀取使用者程式的段資訊(段的Flash載入地址,段的RAM執行地址以及段的長度),在copy_loop中執行迴圈拷貝操作。

;A;
;  ======== File: boot_c671x.s62 ========
;
            .title  "Flash bootup utility"

; global EMIF symbols defined for the c671x family
            .include        boot_c671x.h62

; Address of the generated boot-table
user_size      .equ  0x00001798
user_ld_start  .equ  0x90000400
user_rn_start  .equ  0x00000400

            .sect ".boot_load"
            .global _boot

            .ref _c_int00

_boot:      
;************************************************************************
;* DEBUG LOOP -  COMMENT OUT B FOR NORMAL OPERATION
;************************************************************************

            zero B1
_myloop:  ; [!B1] B _myloop  
            nop  5
_myloopend: nop

;************************************************************************
;* CONFIGURE EMIF
;************************************************************************

        ;****************************************************************
        ; *EMIF_GCTL = EMIF_GCTL_V;
        ;****************************************************************

            mvkl  EMIF_GCTL,A4    
      ||    mvkl  EMIF_GCTL_V,B4

            mvkh  EMIF_GCTL,A4
      ||    mvkh  EMIF_GCTL_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_CE0 = EMIF_CE0_V
        ;****************************************************************

            mvkl  EMIF_CE0,A4       
      ||    mvkl  EMIF_CE0_V,B4     

            mvkh  EMIF_CE0,A4
      ||    mvkh  EMIF_CE0_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_CE1 = EMIF_CE1_V (setup for 8-bit async)
        ;****************************************************************

            mvkl  EMIF_CE1,A4       
      ||    mvkl  EMIF_CE1_V,B4

            mvkh  EMIF_CE1,A4
      ||    mvkh  EMIF_CE1_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_CE2 = EMIF_CE2_V (setup for 32-bit async)
        ;****************************************************************

            mvkl  EMIF_CE2,A4       
      ||    mvkl  EMIF_CE2_V,B4

            mvkh  EMIF_CE2,A4
      ||    mvkh  EMIF_CE2_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_CE3 = EMIF_CE3_V (setup for 32-bit async)
        ;****************************************************************

      ||    mvkl  EMIF_CE3,A4    
      ||    mvkl  EMIF_CE3_V,B4     ;

            mvkh  EMIF_CE3,A4
      ||    mvkh  EMIF_CE3_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_SDRAMCTL = EMIF_SDRAMCTL_V
        ;****************************************************************
      ||    mvkl  EMIF_SDRAMCTL,A4      
      ||    mvkl  EMIF_SDRAMCTL_V,B4    ;

            mvkh  EMIF_SDRAMCTL,A4
      ||    mvkh  EMIF_SDRAMCTL_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_SDRAMTIM = EMIF_SDRAMTIM_V
        ;****************************************************************
      ||    mvkl  EMIF_SDRAMTIM,A4      
      ||    mvkl  EMIF_SDRAMTIM_V,B4    ;

            mvkh  EMIF_SDRAMTIM,A4
      ||    mvkh  EMIF_SDRAMTIM_V,B4

            stw   B4,*A4

        ;****************************************************************
        ; *EMIF_SDRAMEXT = EMIF_SDRAMEXT_V
        ;****************************************************************
      ||    mvkl  EMIF_SDRAMEXT,A4      
      ||    mvkl  EMIF_SDRAMEXT_V,B4    ;

            mvkh  EMIF_SDRAMEXT,A4
      ||    mvkh  EMIF_SDRAMEXT_V,B4

            stw   B4,*A4

;****************************************************************************
; copy sections
;****************************************************************************
        mvkl  copyTable, a3 ; load table pointer
        mvkh  copyTable, a3

        ; ldw   *a3++, b1     ; Load entry point

copy_section_top:
        ldw   *a3++, b0     ; byte count 
        ldw   *a3++, b4     ; load flash start (load) address
        ldw   *a3++, a4     ; ram start address
        nop   2

 [!b0]  b copy_done         ; have we copied all sections?
        nop   5

copy_loop:
        ldb   *b4++,b5      ; fetch from flash
        sub   b0,1,b0       ; decrement counter
 [ b0]  b     copy_loop     ; setup branch if not done
 [!b0]  b     copy_section_top
        zero  a1
 [!b0]  and   3,a3,a1
        stb   b5,*a4++      ; store to ram
 [!b0]  and   -4,a3,a5
 [a1]   and   4, a5,a3

;****************************************************************************
; jump to entry point
;****************************************************************************
copy_done:
        mvkl .S2 _c_int00,b0
        mvkh .S2 _c_int00,b0
        b    .S2 b0
        nop   5

copyTable: 

            ; count
            ; flash start (load) address 
            ; ram start (run) address

            ;; .text
            .word user_size
            .word user_ld_start
            .word user_rn_start    

            ;; end of table
            .word 0
            .word 0
            .word 0

在使用時,我們要對上面程式中的

user_size      .equ  0x00001798