284 lines
8.3 KiB
Plaintext
284 lines
8.3 KiB
Plaintext
; --------------------------------------------------------------------------------
|
|
; @Title: Xilinx ZYNQ-7000 generic QSPI Flash Programming Template
|
|
; @Description:
|
|
; This is a generic template scripts that tries to setup flash programming
|
|
; on a ZYNQ-7000 series SoC from Xilinx. The script tries to use an as failsave
|
|
; configuration as possible.
|
|
; Flash info: all flashes with 16MB adressing mode, not valid if 4byte address
|
|
; was set beforehand
|
|
;
|
|
; internal RAM: 0x00001000
|
|
; SPI Tx Register : 0xE000D080
|
|
; SPI Rx Register : 0xE000D020
|
|
; SPI CS Register : 0xE000D000
|
|
; Prerequisites:
|
|
; * ZYNQ BOOTMODE: CASCADED, JTAG BOOT, PLL ON
|
|
;
|
|
; @Keywords: Zynq Zynq7000 flash spi
|
|
; @Author: amerkle
|
|
; @Board: ZC702 Zedboard ZC706
|
|
; @Chip: Zynq-7000
|
|
; @Props: Template
|
|
; @Copyright: (C) 1989-2022 Lauterbach GmbH, licensed for use with TRACE32(R) only
|
|
; --------------------------------------------------------------------------------
|
|
; $Id: zynq7000-spi64-template.cmm 10516 2022-02-02 11:39:30Z bschroefel $
|
|
|
|
LOCAL &arg1
|
|
ENTRY &arg1
|
|
&arg1=STRing.UPpeR("&arg1") // for example "PREPAREONLY"
|
|
|
|
|
|
LOCAL &ctrl_reg
|
|
LOCAL &tx_reg
|
|
LOCAL &rx_reg
|
|
|
|
&ctrl_reg=0xE000D000
|
|
&tx_reg=0xE000D080 ;Register TXD1 for the 1-byte instruction
|
|
&rx_reg=0xE000D020
|
|
|
|
WinCLEAR
|
|
|
|
RESet
|
|
SYStem.RESet
|
|
SYStem.CPU ZYNQ-7000
|
|
SYStem.MemAccess DAP
|
|
; This selects the DAP for accessing the ARM cores
|
|
; (accessing the TAP of the FPGA logic requires different settings)
|
|
SYStem.CONFIG DAPIRPRE 6.
|
|
SYStem.CONFIG DAPIRPOST 0.
|
|
SYStem.CONFIG DAPDRPRE 1.
|
|
SYStem.CONFIG DAPDRPOST 0.
|
|
|
|
TrOnchip.Set.RESET OFF
|
|
TrOnchip.Set.UNDEF OFF
|
|
TrOnchip.Set.DABORT OFF
|
|
TrOnchip.Set.PABORT OFF
|
|
|
|
SYStem.JtagClock CTCK 10.0MHz
|
|
CORE.ASSIGN 1.
|
|
SYStem.Mode.Attach
|
|
|
|
IF STATE.RUN()
|
|
Break
|
|
|
|
DO ~~/demo/arm/hardware/zynq-7000/scripts/zynq7000_reset
|
|
|
|
; SLCR - UNLOCK WRITE
|
|
Data.Set ASD:0XF8000008 %Long 0x0000DF0D
|
|
; Assert Reset of Second core -> we are save to remap memories
|
|
Data.Set ASD:0xF8000244 %LONG 0x2
|
|
; MMU disable, Exception Vectors HIGH
|
|
Data.Set C15:0x1 %Long 0x18C52478
|
|
; OCM_CFG - OCM[0..2]=0x0--0x2ffff OCM[3]=0xffff0000
|
|
Data.Set AZSD:0xF8000910 %Long 0x18
|
|
|
|
; exception Vectors
|
|
Data.Assemble R:0xffff0000 b $+0
|
|
Data.Assemble , b $+0
|
|
Data.Assemble , b $+0
|
|
Data.Assemble , b $+0
|
|
Data.Assemble , b $+0
|
|
Data.Assemble , b $+0
|
|
Data.Assemble , b $+0
|
|
|
|
; set PC to a endless loop in OCM - prevent issues with XIP mode
|
|
Register.Set PC 0xffff0020
|
|
Data.Assemble R:0xffff0020 b $+0
|
|
|
|
GOSUB zynq7000_io_init ; qspi pin configuration
|
|
|
|
GOSUB zynq7000_clk_init ; cpu & qspi clock configuration
|
|
|
|
(
|
|
; SLCR - UNLOCK WRITE
|
|
Data.Set AD:0XF8000008 %Long 0x0000DF0D
|
|
|
|
; LQSPI_CLK_CTRL - Divisor=0, use ARM-PLL, enable
|
|
Data.Set AD:0xF800014C %Long 0x21
|
|
; APER_CLK_CTRL set LQSPI_CPU
|
|
Data.Set AD:0xF800012C %LE %Long Data.Long(AD:0xF800012C)|0x800000 ; Enable Clock of QSPI
|
|
|
|
; toggle reset of QSPI controller
|
|
Data.Set AD:0xF8000230 %LE %Long 0x3 ; assert RESET
|
|
WAIT 100.ms
|
|
Data.Set AD:0xF8000230 %LE %Long 0x0 ; deassert RESET
|
|
WAIT 100.ms
|
|
|
|
; initialize QSPI controller
|
|
Data.Set AD:0xE000D014 %Long 0x0 ; Disable QSPI
|
|
Data.Set AD:0xE000D000 %Long 0x80020021 ; Configuration SPI, CS0, 8bits, Master Mode
|
|
Data.Set AD:0xE000D000 %Long Data.Long(AZSD:0xE000D000)|(0x1<<14.) ; manual CS mode
|
|
Data.Set AD:0xE000D008 %Long 0xFF ; Disable SPI Interupt
|
|
Data.Set AD:0xE000D0A0 %Long 0x00000003 ; disable LQ_MODE, enable TWO_MEM & SEP_BUS for dual spi devices
|
|
Data.Set AD:0xE000D028 %Long 0x1
|
|
Data.Set AD:0xE000D02C %Long 0x1
|
|
Data.Set AD:0xE000D038 %Long 0x33
|
|
Data.Set AD:0xE000D014 %Long 0x1 ; Enable QSPI
|
|
)
|
|
|
|
//FLASH READ ID TEST
|
|
AREA.view
|
|
GOSUB READ_ID_TEST
|
|
DIALOG.YESNO "Is the flash ID correctly shown in the AREA window?"
|
|
LOCAL &result
|
|
ENTRY &result
|
|
IF !&result
|
|
(
|
|
PRINT "Please check your register configuration to enable your flash controller"
|
|
ENDDO
|
|
)
|
|
|
|
//RAM TEST for algorithm file
|
|
Data.Test 0x00001000++0x7FFF /Prime
|
|
IF FOUND()
|
|
(
|
|
PRINT "RAM is NOT initialized around 0x" ADDRESS.OFFSET(TRACK.ADDRESS())
|
|
ENDDO
|
|
)
|
|
|
|
FLASHFILE.RESet
|
|
FLASHFILE.CONFIG 0xE000D080 0xE000D020 0xE000D000
|
|
FLASHFILE.TARGET 0x00001000++0x3FFF 0x00005000++0x21FF ~~/demo/arm/flash/byte/spi64_zynq7xxx.bin /KEEP ; internal RAM
|
|
FLASHFILE.GETID
|
|
|
|
//End of the test prepareonly
|
|
IF "&arg1"=="PREPAREONLY"
|
|
ENDDO
|
|
|
|
|
|
//Dump window for Serial FLASH
|
|
FLASHFILE.DUMP 0x0 ; Also can read the spi flash data at 0xFC00_0000 after LQSPI_CFG.LQ_MODE is enabled
|
|
|
|
//Unlock Serial FLASH
|
|
;FLASHFILE.UNLOCK 0x00--0xFFFFF
|
|
|
|
//Write Serial FLASH
|
|
;FLASHFILE.ERASE 0x00--0xFFFFF
|
|
|
|
//Write Serial FLASH
|
|
;FLASHFILE.LOAD * 0x00
|
|
;FLASHFILE.LOAD * 0x00 /ComPare
|
|
|
|
ENDDO
|
|
|
|
zynq7000_io_init:
|
|
(
|
|
; SLCR - UNLOCK WRITE
|
|
Data.Set AD:0XF8000008 %Long 0x0000DF0D
|
|
|
|
; MIO_PIN_[0..31] - TriState
|
|
Data.Set AD:0xF8000700++0x7f %Long 0x1201
|
|
|
|
PRIVATE &LVCMOS
|
|
; select either LVCMOS18=1/LVCMOS25=2/LVCMOS33=3
|
|
&LVCMOS=1.
|
|
; MIO1 - QSPI0 CS0
|
|
Data.Set AD:0xF8000704 %Long 0x0002|(&LVCMOS<<9.)
|
|
; MIO2 - QSPI0 IO0
|
|
Data.Set AD:0xF8000708 %Long 0x1002|(&LVCMOS<<9.)
|
|
; MIO3 - QSPI0 IO1
|
|
Data.Set AD:0xF800070c %Long 0x0002|(&LVCMOS<<9.)
|
|
; MIO5 - GPIO5
|
|
Data.Set AD:0xF8000714 %Long 0x0000|(&LVCMOS<<9.)
|
|
; MIO6 - QSPI0 CLK
|
|
Data.Set AD:0xF8000718 %Long 0x0002|(&LVCMOS<<9.)
|
|
|
|
; GPIO_RST_CTRL - Toggle Reset of GPIO
|
|
Data.Set AD:0xF800022C %Long 0x1
|
|
WAIT 1.ms
|
|
Data.Set AD:0xF800022C %Long 0x0
|
|
|
|
; ZC702 speciality
|
|
; use MIO5 as GPIO drive it high as MIO5(=DQ3) has RESET/HOLD as secondary function
|
|
; BANK0.BYPM clear MIO5
|
|
Data.Set AD:0xE000A200 %Long Data.Long(AD:0xE000A200)&~(1.<<5.)
|
|
; BANK0.DIRM set MIO5
|
|
Data.Set AD:0xE000A204 %Long Data.Long(AD:0xE000A204)|(1.<<5.)
|
|
; BANK0.OEN set MIO5
|
|
Data.Set AD:0xE000A208 %Long Data.Long(AD:0xE000A208)|(1.<<5.)
|
|
; set MIO5 high
|
|
Data.Set AD:0xE000A040 %Long Data.Long(AD:0xE000A040)|(1.<<5.)
|
|
|
|
RETURN
|
|
)
|
|
|
|
zynq7000_clk_init:
|
|
(
|
|
; SLCR - UNLOCK WRITE
|
|
Data.Set AD:0XF8000008 %Long 0x0000DF0D
|
|
|
|
; clock setup
|
|
; BYPASS all PLLs - we are running on Oscillator now
|
|
Data.Set AD:0xF8000100 %Long 0x10
|
|
Data.Set AD:0xF8000104 %Long 0x10
|
|
Data.Set AD:0xF8000108 %Long 0x10
|
|
; ARM_CLK_CTRL - DIVISOR 0
|
|
Data.Set AD:0xF8000120 %Long 0x1F000000
|
|
IF FALSE()
|
|
(
|
|
; optional - start the PLL again - e.g. slow as possible
|
|
; ARM_PLL_CTRL - set F_DIV=13.
|
|
Data.Set AD:0xF8000100 %Long Data.Long(AD:0xF8000100)|(13.<<12.)
|
|
; ARM_PLL_CFG for Divisor 0xd - PLL_CP=2 PLL_RES=6 LOCK_CNT=750
|
|
Data.Set AD:0xF8000110 %Long (750.<<12.)|(2.<<8.)|(6.<<4.)
|
|
; ARM_PLL_CTRL - toggle reset
|
|
Data.Set AD:0xF8000100 %Long Data.Long(AD:0xF8000100)|0x1
|
|
WAIT 10.ms
|
|
Data.Set AD:0xF8000100 %Long Data.Long(AD:0xF8000100)&~0x1
|
|
; PLL_STATUS wait for ARM_PLL_STABLE
|
|
WAIT (Data.Long(AD:0xF800010C)&0x4)!=0
|
|
; ARM_PLL_CTRL - clear bypass
|
|
Data.Set AD:0xF8000100 %Long Data.Long(AD:0xF8000100)&~0x10
|
|
)
|
|
RETURN
|
|
)
|
|
|
|
READ_ID_TEST:
|
|
(
|
|
LOCAL &data
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
PRINT "ctrl_reg : &data "
|
|
|
|
Data.Set AD:&ctrl_reg %Long (&data&(~(0x1<<10.))) ; cs low
|
|
|
|
Data.Set &tx_reg %Byte 0x9F
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT " 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
Data.Set &tx_reg %Byte 0x00
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT "1st : 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
Data.Set &tx_reg %Byte 0x00
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT "2nd : 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
Data.Set &tx_reg %Byte 0x00
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT "3rd : 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
Data.Set &tx_reg %Byte 0x00
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT "4th : 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
|
|
Data.Set &tx_reg %Byte 0x00
|
|
&data=Data.Long(AD:&ctrl_reg)
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<16.)) ; start cmd
|
|
WAIT 1.ms
|
|
PRINT "5th : 0x" FORMAT.HEX(2,(Data.Long(AD:&rx_reg)>>24.)&0xFF)
|
|
|
|
Data.Set AD:&ctrl_reg %Long (&data|(0x1<<10.)) ; cs high
|
|
|
|
RETURN
|
|
) |