TMS320C6713燒寫Flash的通用方法
1 你必須知道的TMS320C6000啟動過程
這部分內容在我的另一篇部落格
有提到過,這裡重新摘錄一遍。
如上圖
- 在Device Reset階段:裝置初始化為預設狀態,大部分三態輸出都配置為高阻態。
- 在CPU Reset階段:從RS上升沿處開始(這個時候,HD[4:3]配置啟動模式,HD8配置大小端模式,CLKMODE配置輸入時鐘源,根據HPI_EN配置外設功能),處理器檢查啟動模式HD[4:3],啟動bootloader程式。
從上圖可以看出,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