⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cstartup.asm

📁 ECOG bootloader, used to initialized ecog microcontroller
💻 ASM
字号:
;==============================================================================
; Cyan Technology Ltd
;
; FILE
;  cstartup.asm - Assembler startup for C programs.
;
; DESCRIPTION
;  Defines C segments. Contains initial code called before C is started.
;    This is an updated version used for the bootloader example. 
;    The additional code includes an intialiser at the beginning of memory
;    and a conditional branch to 0x0200 if dip sw 1 is closed.
;    The code segment locations are also re-organised for correct operation.
;==============================================================================

                MODULE   cstartup
                .ALL

;
; C reserves DATA address 0 for the NULL pointer. The value H'DEAD is put in
; here so that it is easier to spot the effect of a NULL pointer during
; debugging. User memory for constants grows upwards from H'0001. The first
; address is given the equate symbol $??LO_ADDR.
;
                .SEG     C_RESERVED1
                ORG      0
                dc       H'DEAD
$??LO_ADDR      EQU      $

;
; DATA addresses H'EFE0-H'EFFF are used for scratchpad RAM in interrupt mode.
; DATA addresses H'EFC0-H'EFDF are used for scratchpad RAM in user mode.
; DATA addresses H'EFB8-H'EFBF are used for register storage in interrupt mode.
; Then follows the interrupt stack, user stack and user heap.
; User memory for variables grows downwards from the end of the user stack.
; This version of cstartup only contains one area of scratchpad RAM
; which constrains users not to write re-entrant re-interruptable code.
; The interrupt stack must start at IY-38 to be compatible with the C compiler.
;
                .SEG     C_RESERVED2
                ORG      H'EFB8

$??HI_ADDR      DEQU     $
                ds       8           ; Interrupt register storage

                ds       32          ; User Scratchpad
IY_SCRATCH      DEQU     $

$?irq_scratchpad? DEQU     $
                ds       32          ; Interrupt Scratchpad

;
; The registers that control the functional blocks of the eCOG1 are located
; at addresses H'FEA0 to H'FFCF. The C header file <ecog1.h> declares an
; external structure that descibes the registers. This variable is defined
; below.
;
                .SEG     REGISTERS
                ORG      H'FEA0
$fd:
$rg             ds       304

;
; C requires the following segments:
;     CONST  - Constants in ROM. For example:
;                 const char c = 'c' ;
;                 printf( "Hello World!" ) ;
;     VAR    - Variables in RAM. These are set to zero by the cstartup code.
;              For example:
;                 int i ;              (in file scope)
;                 static int i ;       (in function scope)
;     INIT   - Initialisd variables in RAM. For example:
;                 int i = 9 ;          (in file scope)
;                 static int i = 9 ;   (in function scope)
;     INITC  - Initialisation data for the INIT segment
;     HEAP   - The heap. Required if malloc() etc. are used.
;     STACK  - The stack. Always required.
;
; The memory allocated to each segment is defined by the value of
; $??<segment_name>_SIZE as set below. These sizes can be set manually or, if
; the appropriate line is tagged with !PACK and the -pack option is specified
; to ECOGCL, ECOGCL will write in the size actually required for the segment.
; The sizes of the STACK and HEAP segments must be set by the user.
; *** Notes for bootloader ***
; ISTACK has been removed as interrupts are not used in this code.  Both the
; HEAP and STACK have been reduced in size to accommodate the large amount of
; code that needs to run from ram.
;
$??ISTACK_SIZE  =        H'0000
$??STACK_SIZE   =        H'0080
$??HEAP_SIZE    =        H'0000
; ROM segments
$??INITC_SIZE   =        h'0007  ; !PACK
$??CONST_SIZE   =        h'0089  ; !PACK

; RAM segments
$??INIT_SIZE    =        h'0007  ; !PACK
$??VAR_SIZE     =        h'0035  ; !PACK


; -- Locate DATA segments in memory --
;
; Segments are allocated sequentially by the ??ALLOCATE macro. They may be
; set at fixed addresses by setting ADDR prior to calling ??ALLOCATE.
;
??ALLOCATE      MACRO    seg
                .SEG     &seg
                ORG      ADDR
$??&seg!_LO     = ADDR
ADDR            = ADDR + $??&seg!_SIZE
$??&seg!_HI     = ADDR-1
                ENDMAC

; Allocate DATA ROM
ADDR            = $??LO_ADDR
                ??ALLOCATE INITC
                ??ALLOCATE CONST

; Allocate DATA RAM
ADDR            = $??HI_ADDR - $??VAR_SIZE - $??INIT_SIZE
ADDR            = ADDR - $??ISTACK_SIZE - $??STACK_SIZE - $??HEAP_SIZE
                 
                ??ALLOCATE INIT
                ??ALLOCATE VAR
                ??ALLOCATE HEAP
                ??ALLOCATE STACK                                    
                ??ALLOCATE ISTACK

; -- Memory initialisation macros --
;
; Segments may be initialised by filling with a constant value using the
; ??SEGFILL macro.  Two symbols are passed, the segment name and the value to
; fill with.  A third symbol (the size) is assumed.
;
??SEGFILL       MACRO    seg, value
                LOCAL    fill_loop
                IF       $??&seg!_SIZE
                ld       x, #$??&seg
                ld       al, #$??&seg!_SIZE
                ld       ah, &value
&fill_loop:     st       ah, @(0,x)
                add      x, #1
                sub      al, #1
                bne      &fill_loop
                ENDIF
                ENDMAC

;
; Segments may be initialised by copying an initialisation segment with
; the ??SEGCOPY macro. Two symbols are passed, the source and destination
; segment names.
;
??SEGCOPY       MACRO    src, dest
                IF       $??&src!_SIZE NE $??&dest!_SIZE
                .ERR     "Copy segments different sizes"
                ENDIF
                IF       $??&src!_SIZE
                ld       x, #$??&src
                ld       y, #$??&dest
                ld       al, #$??&src!_SIZE
                bc
                ENDIF
                ENDMAC

;
; Fills a block of memory with a value. Three values are passed, the start
; address for the block, the number of addresses to write to and the value
; to be written.
;
??MEMFILL       MACRO    start, length, value
                LOCAL    fill_loop
                ld       x, &start
                ld       al, &length
                ld       ah, &value
&fill_loop:     st       ah, @(0,x)
                add      x, #1
                sub      al, #1
                bne      &fill_loop
                ENDMAC


;
; Input argument for main().
;
                .SEG     CONST
argv            dc       0,0         ; NULL as two-word byte address 


; Code addresses defined here
$?bootstart_code CEQU    0x0040    ; Bootloader startup code
$?userstart_code CEQU    0x0200    ; User application code start address
$?bootload_code  CEQU    0x7000    ; Bootloader main code
$?bootload_flash CEQU    0x7600    ; Bootloader routine (in flash for debugging)
$?bootload_ram   CEQU    0x8000    ; Bootloader routine (copied to ram and executed at this address)

;
; Start of Code.
;
                .CODE   
                ORG      $?bootstart_code
                
; Get address of mmu registers
                ld x, #h'ff43        ; &mmu.translate_en

; Disable all unwanted mmu translations initially
; (flash code and sram data areas are always enabled)
                ld al, #0
                st al, @(0,x)        ; mmu.translate_en

; Map CodeFlash Physical 0 - 7fff to Logical Code 0 - 7fff
                ld al, #h'0
                st al, @(1,x)        ; mmu.xxx_log h'ff44
                st al, @(2,x)        ; mmu.xxx_phys h'ff45
                ld al, #h'7f        
                st al, @(3,x)        ; mmu.xxx_size h'ff46
;
; Flash is now mapped in, we can continue with the user code if
; we so wish, resulting in limited overhead and disruption.
; Check dip sw1, jump to application code at 0x0200 if open (off)
                ld    al,@$rg+0x0115
                asr   #8
                and   al,#1
                cmp   al,#1
                beq   $?userstart_code  ; SW1 open, jump to application code
                bra   $?bootload_code   ; Else continue into bootloader

;
;-----------------------------------------------------------------------
;
                ORG     $?userstart_code
; Start address for user application code (downloaded to 0x0200)
                  
;
;-----------------------------------------------------------------------
;
                ORG        $?bootload_code
; Start address for bootloader main code
                bra $ecog1ConfigMMU    ; configure MMU and Cache Banks                  

$ecog1ConfigContinue:
;
; Initialise segments. The
; The INIT segment is set from the ROM initialisers in the INITC segment.
; The non initialised RAM segment VAR is set to zero (compiler puts 0
; initialised variables in these segments as well as uninitialised ones).
;
                ??SEGCOPY INITC, INIT
                ??SEGFILL VAR, #h'0

; Set interrupt stack pointer.
                ld y, #IY_SCRATCH

; Set user mode flag to allow interupts.
                st flags, @(-1,y)
                ld al, @(-1,y)
                or al, #h'10
                st al, @(-1,y)
                ld flags, @(-1,y)

; Set usermode stack pointer
                ld y, #$??STACK_HI

; Call ecog1Config to setup eCOG1 peripherals
; Defined in module produced by configuration compiler
                bsr $ecog1Config
                
; Call main, with argc and argv[0] set to 0.
; Copies bootloader routine to ram then returns
                ld ah, #argv
                ld al, #0
                bsr $main
                  
; We now need to check the status of the return variable and branch
; depending on user code or bootloader
                cmp al, #1
                beq $run_user_code
                  
; When Main returns we are ready with the bootloader code in memory
; Now call bootloader in ram
                bsr $?bootload_ram     ; Execute bootloader from RAM
;                bsr $?bootload_flash   ; Execute bootloader from flash (to allow debugging)

; Run the downloaded user program - test to see results
$run_user_code:
                bsr $?userstart_code

;
; Bootloader has finished new code download - stop here
; Exit code is in AL.
$exit:
                brk                ; Alert the user if in debug mode
                bra $run_user_code ; Restart user application
                
;
; This is the minimal interrupt routine.
;
$minimal_handler:
                st flags,@(-33,y) ; Store Flags
                st al, @(-34,y)   ; Store AL

                ld al, @(-33,y)   ; Put Flags into AL
                or al, #h'0010    ; Set usermode
                st al, @(-33,y)   ; Store the value to be restored to Flags

                brk               ; Alert the user if in debug mode

                ld al, @(-34,y)   ; Restore AL
                rti @(-33,y)      ; Restore PC and Flags

;
; The address exception can happen often during development. A handler
; is put here to catch the exception.
;
$address_error:
                st flags,@(-33,y) ; Store Flags
                st al, @(-34,y)   ; Store AL

                ld al, @(-33,y)   ; Put Flags into AL
                or al, #h'0010    ; Set usermode
                st al, @(-33,y)   ; Store the value to be restored to Flags

                brk               ; Alert the user if in debug mode

                ld al, #h'a
                st al, @h'ff69    ; Clear status in mmu.address_exception

                ld al, #h'200
                st al, @h'ff7a    ; Clear status in emi.ctrl_sts

                ld al, @(-34,y)   ; Restore AL
                rti @(-33,y)      ; Restore PC and Flags

; Start address for configuration code which follows here
$??CSTARTUP_END EQU     $

;
;-----------------------------------------------------------------------
;
; Assign bootloader routine to a fixed logical address in flash
; to allow easy copying to ram
                .CSEG   BOOTLOADER   
                ORG     $?bootload_flash

                ENDMOD


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -