📄 sb_eeprogram.asm
字号:
;**************************************************************************
;***
;*** Copyright 2007, Freescale, Inc. All rights reserved.
;***
;**************************************************************************
;***
;*** I2C EEPROM programing routines for making SoundBite self boot
;***
;*** This code writes the I2C EEPROM attached to the 56371 in the format
;*** required for self-booting in mode 9
;***
;**************************************************************************
section soundbite_eeprogram
nolist
include "..\dsp56371.equ" ; generic 56371 equates
include "..\soundbite.equ" ; SoundBite specific equates
include "..\soundbite_macros.equ" ; macros for sb_leds.asm and sb_switches.asm
list
;**************************************************************************
; reference external symbols for LED control
;**************************************************************************
xref SETUP_LEDS,SET_LEDS
;**************************************************************************
; define default start addresses and lengths of uploads for EEPROM...
;**************************************************************************
PSTART_CODE equ 0 ; this is always 0 for non-SA self-boot
XSTART equ 0 ; this is typically always 0
YSTART equ 0 ; this is typically always 0
PLENGTH equ $450 ; length of P code
XLENGTH equ $40 ; length of X data
YLENGTH equ $40 ; length of Y data
PSTART_EXEC equ $0 ; begin execution here after download done
EEPROM_STRT equ $0 ; default start address in EEPROM
;**************************************************************************
;**************************************************************************
; define symbols used for progress indication via LEDs
;**************************************************************************
TOTAL_BYTES equ 3*(12+PLENGTH+XLENGTH+YLENGTH) ; total bytes to upload to EEPROM
PROGRESS equ @CVI($FE0000/TOTAL_BYTES) ; increment to show 8 bits of
; progress in LEDs when complete
org p:
;*************************************************************************
; entry point to EEPROM programming routine to make SoundBite self boot
;*************************************************************************
e2prog:
ori #$03,mr ; guarantee that interrupts are masked
movep #$0,X:M_HCSR ; turn off/reset SHI
;*** Set DSP core clock rate ***
movep #$04401d,x:$FFFFFD ; assumes 24.576 MHz DSP core clock
; programming routine won't work otherwise
rep #$FFF ; wait for PLL to settle
nop
;*** Set SHI clock Rate ***
movep #$000040,X:M_HCKR ; /64 for crystal value (i.e. 25MHz/(8*8) = 390625 Hz
;*** Setup SHI: Master Mode, 8 bit data, I2C protocol ***
movep #$008242,X:M_HCSR ; write register leaving SHI disabled...
bset #0,x:M_HCSR ; enable the SHI after register programmed...
;*** set M registers for pointers to guarantee linear addressing
move #$FFFFFF,m0 ; set linear addressing mode for r0,r1,r2
move m0,m1
move m1,m2
;*** setup progress indication (binary counter)
move #0,r7 ; counter used for indicating 8 bits of progress (LEDs)
move #PROGRESS,n7 ; increment and show progress by displaying uppermost byte
bsr SETUP_LEDS ; setup LEDs for use
;*** load y0 and y1 with I2C device select write/read bytes
;*** this allows changing device select on the fly, if desired
move #$A00000,y0 ; I2C EEPROM device select, write bit clear
move #$A10000,y1 ; I2C EEPROM device select, read bit set
;*** load core registers with all upload parameters, allowing for easy change with debugger
move #EEPROM_STRT,r1 ; r1 = EEPROM internal start address
move #>PSTART_CODE,r4 ; r4 = P code start address
move #>XSTART,r5 ; r5 = X data start address
move #>YSTART,r6 ; r6 = Y data start address
move #>PLENGTH,m4 ; m4 = P code length
move #>XLENGTH,m5 ; m5 = X data length
move #>YLENGTH,m6 ; m6 = Y data length
move #>PSTART_EXEC,n0 ; n0 = P addr at which to start executing
;*********************************************************************
;*** stop here and wait to enable user to change upload paramters
;*** comment this out for production SoundBite programming...
;*********************************************************************
; DEBUG ; change upload paramters now, if desired/required
;*********************************************************************
nop
nop
nop
; write table of start addresses and lengths to EEPROM; 18 bytes total
move r4,b1 ; write start address for P code data to EEPROM
bsr WRITE_word
move r5,b1 ; write start address for X data to EEPROM
bsr WRITE_word
move r6,b1 ; write start address for Y data to EEPROM
bsr WRITE_word
move m4,b1 ; write length of P code to EEPROM
bsr WRITE_word
move m5,b1 ; write length of X data to EEPROM
bsr WRITE_word
move m6,b1 ; write length of Y data to EEPROM
bsr WRITE_word
; write P code data to EEPROM
move r1,n4 ; store EEPROM addres for beginning of P data
move r4,r2 ; r2 points to P start address
move m4,r3 ; r3 contains length of data to upload
do r3,Pdataloop
move p:(r2)+,b1 ; read word from P memory
bsr WRITE_word ; write it to EEPROM
nop
Pdataloop:
nop
; write X data to EEPROM
move r1,n5 ; store EEPROM addres for beginning of X data
move r5,r2 ; r2 points to X start address
move m5,r3 ; r3 contains length of data to upload
do r3,Xdataloop
move x:(r2)+,b1 ; read word from X memory
bsr WRITE_word ; write it to EEPROM
nop
Xdataloop:
nop
; write Y data to EEPROM
move r1,n6 ; store EEPROM addres for beginning of Y data
move r6,r2 ; r2 points to Y start address
move m6,r3 ; r3 contains length of data to upload
do r3,Ydataloop
move y:(r2)+,b1 ; read word from Y memory
bsr WRITE_word ; write it to EEPROM
nop
Ydataloop:
nop
; write address to start execution when download completes
move r1,n7 ; store EEPROM addres for start of execution
move n0,b1 ; P address at which to start execution
bsr WRITE_word
nop
move #>$FF,a1 ; turn on all LEDs to indicate completion
bsr SET_LEDS ; while turning off GPLED9
;*********************************************************************
;*** EEPROM programming is now complete... Data in EEPROM may be inspected, if desired
;*********************************************************************
DEBUG ; stop here. EEPROM should now be programmed...
; Nx registers n4,n5,n6,n7 contain the EEPROM addresses
; of the respective P, X, Y data and P exec. start addresses.
; These may be inspected using the READ_TEST routine below.
jmp READ_TEST ; resume here to check EEPROM (for checking by hand only)
jmp * ; stop here
;*********************************************************************
;*** EEPROM programming/reading subroutines
;*********************************************************************
;*********************************************************************
;*** Write 3 bytes of a 24-bit word to EEPROM, LSB first
;***
;*** b1: contains word to write
;*** r1: contains address to write to in EEPROM
;*** r7: contains the visual progress counter (displays $FF when complete)
;*** clobbers a and x0
;***
;*** calls WRITE_byte subroutine
;*********************************************************************
WRITE_word:
do #3,wordloop ; loop over 3 bytes of 24-bit word
asr #8,b,b ; shift LSB of B1 to MSB of b0
move b0,x0 ; move b0 to x0, argument for WRITE_byte
bsr WRITE_byte ; write this to EEPROM
nop
move r7,a1 ; put progress counter into A
lsr #16,a ; shift A right by 16 bits
bsr SET_LEDS ; display status in lower 8 LEDs
nop
wordloop:
nop
rts
;*********************************************************************
;*** Write a single byte to EEPROM
;***
;*** x0: contains byte to write in upper 8-bits (MSB)
;*** r1: contains address to write to in EEPROM,
;*** where r1 is incremented by 1 following the write
;*** y0: contains I2C device select specifying write
;***
;*** clobbers r0,a
;*********************************************************************
WRITE_byte:
move y0,r0 ; EEPROM slave address with write bit clr
bsr SHI_tx ; write to SHI (I2C device select)
move r1,a0
asl #8,a,a ; Get MSB of address into TX position
move a0,r0 ; TX MSByte address
bsr SHI_tx ; write to SHI
asl #8,a,a ; Now get LSB address into position
move a0,r0 ; TX LSByte address
bsr SHI_tx ; write to SHI
move x0,r0 ; write desired byte to EEPROM
bsr SHI_tx ; write to SHI
bset #M_HIDLE,x:M_HCSR ; generate I2C stop event to complete write
; write a device select here, wait for EEPROM to ack to indicate write complete
poll_till_done:
move y0,r0 ; EEPROM slave address with write bit clear
movep r0,x:M_HTX ; write data to SHI TX register
brclr #19,a0,_no_led ; only turn on LED9 when bit 3 of LSB of address is set
; (remembering that LSB is in uppermost 8 bits of a0...)
GPLED8_on ; turn LED on
_no_led:
rep #$c00 ; wait long enough for lack of ACK to cause M_HBER error
nop ;
GPLED8_off ; turn LED off
brclr #M_HBER,x:M_HCSR,poll_jump_out ; exit when EEPROM gives an ACK (writing done)
movep #0,x:M_HCSR ; reset SHI to clear I2C bus error
rep #3
nop ; nops for status bit update latency...
movep #$008242,X:M_HCSR ; write register but leave SHI disabled...
bset #0,x:M_HCSR ; enable the SHI after register programmed...
bra poll_till_done ; loop back to write control word again...
poll_jump_out: ; at this point, byte written to I2C EEPROM
bset #M_HIDLE,x:M_HCSR ; generate I2C stop event
move (r1)+ ; increment EEPROM address pointer
move (r7)+n7 ; increment for progress indication
rts ; return from whence called
;*********************************************************************
;*** SHI TX routine
;***
;*** r0: contains data to write
;*********************************************************************
SHI_tx:
movep r0,x:M_HTX ; write data to SHI TX register
rep #3
nop ; nops for latency in status bits updating
brclr #M_HTDE,X:M_HCSR,* ; Wait for M_HTX register to empty
rts ; and then return
;*********************************************************************
;*** Read a random byte from EEPROM
;***
;*** EEPROM requires an incomplete I2C write cycle to update the internal
;*** address pointer followed by a read. Inefficient but it works...
;***
;*** x0: returns byte read from EEPROM in upper 8-bits
;*** r1: contains address to write to in EEPROM
;*** y0: contains I2C device select specifying write
;*** y1: contains I2C device select specifying read
;***
;*** clobbers r0,a
;*********************************************************************
READ_rand_byte:
move y0,r0 ; EEPROM slave address with write bit clr
bsr SHI_tx ; write to SHI
move r1,a0 ; move address of interest to a0
asl #8,a,a ; Shift MSB of address into TX position
move a0,r0 ; TX MSByte address
bsr SHI_tx ; write to SHI
asl #8,a,a ; Now get LSB address into position
move a0,r0 ; TX LSByte address
bsr SHI_tx ; write to SHI
bset #M_HIDLE,x:M_HCSR ; generate I2C stop event - incomplete write cycle
rep #20 ; wait a bit...
nop
move y1,r0 ; write eeprom slave address, w/read bit set
movep r0,x:M_HTX ; write data to SHI TX register
bset #M_HIDLE,x:M_HCSR ; don't ack rcv'd byte so EEPROM only sends one byte
nop ; nops for latency in status bits getting updated
nop
nop
brclr #M_HTDE,X:M_HCSR,* ; Wait for M_HTX register to empty
brclr #M_HRNE,x:M_HCSR,* ; wait for EEPROM to write byte back
move x:M_HRX,x0 ; read return value from EEPROM
rts
;*********************************************************************
;*** This is a short read routine used to inspect by hand the contents of
;*** the EEPROM after writing. Change PC to READ_TEST and then watch x0,x1
;*** as stepping through the loop at the bottom. Change addresses by
;*** changing r1 with debugger. This should probably be turned into a full
;*** byte by byte verification automatically run after the data is written
;*** to the EEPROM... An exercise for the reader?
;*********************************************************************
READ_TEST:
movep #$0,X:M_HCSR ; turn off/reset SHI
;*** Set PLL clock Rate ***
movep #$04401d,x:$FFFFFD ; turn off pll / revert to 25 MHz
;*** Set SHI clock Rate ***
movep #$000040,X:M_HCKR ; /64 for crystal value (i.e. 25MHz/(8*8) = 390625
;*** Set M_HIDLE bit / Master Mode / 8 bit data / I2C ***
movep #$008242,X:M_HCSR ; write register with disabled...
bset #0,x:M_HCSR ; then enable the SHI after register programmed...
move #0,r1 ; load default EEPROM starting address (0)
randread:
bsr READ_rand_byte ; read EEPROM contents (and put in X0)
move r1,x1 ; put current EEPROM address in X1
move (r1)+ ; increment EEPROM address pointer
jmp randread ; jump for next, break here to change EEPROM address
;*********************************************************************
;*** This routine blanks entire EEPROM to the original $FFFFFF contents
;*** (this is usually run by hand in debugger...)
;*********************************************************************
EE_BLANK:
move #$FF,x0 ; blank EEPROM value
move #0,r1 ; r1 points to EEPROM start address
move #$200000,r3 ; r3 = 32k bytes in EEPROM
do r3,blankloop
bsr WRITE_byte ; write it to EEPROM
nop
blankloop:
nop
debug ; stop here
endsec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -