; -------------------------------------------------------------------------------- ; @Title: Simple QSPI flash loading demo on SK-AM62A-LP (FLASH) ; @Description: ; Simple, generic example on how to rewrite the QSPI flash of the SK-AM62A-LP. ; ; Prerequisites: ; * Connect Debug Cable to J19 via adapter LA-3780 ; ; @Keywords: ARM, Cortex-R5, FLASH, QSPI ; @Author: CMO ; @Board: SK-AM62A-LP ; @Chip: AM62AX ; @Copyright: (C) 1989-2022 Lauterbach GmbH, licensed for use with TRACE32(R) only ; -------------------------------------------------------------------------------- ; $Id: am62ax_spinand.cmm 13322 2024-04-12 13:24:57Z cmorgenstern $ ; -------------------------------------------------------------------------------- ; Set up flash helper variables LOCAL &ARGS ENTRY %LINE &ARGS LOCAL ¶meters &PARAM_PREPAREONLY &PARAM_DUALPORT ¶meters=STRing.UPpeR("&ARGS") &PARAM_PREPAREONLY=(STRing.SCAN("¶meters","PREPAREONLY",0)!=-1) LOCAL &CONFIG_FLASHTYPE &CONFIG_FLASHTYPE=STRing.SCANAndExtract(STRing.UPpeR("&PARAMETERS"),"FLASHTYPE=","") IF ("&CONFIG_FLASHTYPE"=="") ( &CONFIG_FLASHTYPE="W35" ; default to W35N01JWxxxG ) ; -------------------------------------------------------------------------------- ; Set flash type specific configuration LOCAL &CONFIG_ERASEBLOCKSIZE &CONFIG_DRIVER IF "&CONFIG_FLASHTYPE"=="W25" ( &CONFIG_ERASEBLOCKSIZE=0x20000 ; W25N01JWxxxG=128KB uniform blocks &CONFIG_DRIVER="spinand2k6p_tiospi.bin" ) ELSE IF "&CONFIG_FLASHTYPE"=="W35" ( &CONFIG_ERASEBLOCKSIZE=0x40000 ; W35N01JWxxxG=256KB uniform blocks &CONFIG_DRIVER="spinand4k7_tiospi.bin" ) ELSE ( PRINT %ERROR "&PPF: Unsupported flash type chosen '&CONFIG_FLASHTYPE'. Exiting... " ENDDO ) LOCAL &CONFIG_DUALPORT &CONFIG_DUALPORT=TRUE() ; default to dualport flash programming ; Use PLL2 as flash controller clock source (in doubt leave as TRUE()) LOCAL &CONFIG_USE_PLL2 &CONFIG_USE_PLL2=TRUE() ; Flash controller and memory defines LOCAL &CONFIG_OSPI_BASE &CONFIG_OSPI_MEMORY_BASE &CONFIG_OSPI_BASE=0x0FC40000 &CONFIG_OSPI_MEMORY_BASE=0x60000000 ; flash contents memory mapped address FSS0_DAT_REG1 ; -------------------------------------------------------------------------------- ; Set up helper variables LOCAL &PDD &AUX_SCRIPT_DIR &PRESENT_SCRIPT &PDD=OS.PDD() &AUX_SCRIPT_DIR="&PDD/hardware/am62ax/sk-am62a-lp/scripts" &PRESENT_SCRIPT=OS.PPF() ; -------------------------------------------------------------------------------- ; Setup target specific callback functions and variables for device setup and HS unlock ; Global variable for Secure-AP base address LOCAL &TI_SETUP_GLOBALVAR_SECAPBASE IF VERSION.BUILD()<153938. &TI_SETUP_GLOBALVAR_SECAPBASE=EDBG:(0x40000000+0x100*6.) ELSE &TI_SETUP_GLOBALVAR_SECAPBASE=DP:(0x100*6.) ; Global variable for Power-AP base address LOCAL &TI_SETUP_GLOBALVAR_PWRAPBASE IF VERSION.BUILD()<153938. &TI_SETUP_GLOBALVAR_PWRAPBASE=EDBG:(0x40000000+0x100*3.) ELSE &TI_SETUP_GLOBALVAR_PWRAPBASE=EDP:(0x100*3.) ; Callback function for handling DSMC (TIFS) core LOCAL &TI_SETUP_CALLBACKFUNC_DSMC_HANDLING &TI_SETUP_CALLBACKFUNC_DSMC_HANDLING="TI_SETUP_CALLBACKFUNC_DSMC_HANDLING" SUBROUTINE TI_SETUP_CALLBACKFUNC_DSMC_HANDLING ( IF !SIMULATOR() DO "&AUX_SCRIPT_DIR/am62ax-cm4-sms0-tifs_connect.cmm" RETURN ) ; Callback function to disable WIR after an early HS device unlock via 'SETUPMODE=JTAG' LOCAL &TI_SETUP_CALLBACKFUNC_EARLYUNLOCK_WIRRELEASE &TI_SETUP_CALLBACKFUNC_EARLYUNLOCK_WIRRELEASE="TI_SETUP_CALLBACKFUNC_EARLYUNLOCK_WIRRELEASE" SUBROUTINE TI_SETUP_CALLBACKFUNC_EARLYUNLOCK_WIRRELEASE ( Data.Set (&TI_SETUP_GLOBALVAR_PWRAPBASE)+0x60 %LE %Long 0yxxxxxxxxxxxxxx0000xxxxxxxxxxxxxx ; Disable WIR mode AM62AX-CR5-MCU RETURN ) ; -------------------------------------------------------------------------------- ; Extract script arguments and set default values LOCAL &ARGS &GUIMODE &DEVICETYPE &SETUPMODE &SYSFWFILE &SCICLIENTFILE &CERTIFICATEFILE ENTRY %LINE &ARGS DO "&AUX_SCRIPT_DIR/ti_setup_parser.cmm" &ARGS "CALLSCRIPT=&PRESENT_SCRIPT" "CPU=AM62AX-CR5-MCU" RETURNVALUES &GUIMODE &DEVICETYPE &SETUPMODE &SYSFWFILE &SCICLIENTFILE &CERTIFICATEFILE ; Exit here if the setup dialog was executed &GUIMODE=&GUIMODE IF (&GUIMODE!=0.) ENDDO ; File global variables LOCAL &TI_SETUP_GLOBALVAR_SYSFWFILE &TI_SETUP_GLOBALVAR_SYSFWFILE="&SYSFWFILE" LOCAL &TI_SETUP_GLOBALVAR_SCICLIENTFILE &TI_SETUP_GLOBALVAR_SCICLIENTFILE="&SCICLIENTFILE" LOCAL &TI_SETUP_GLOBALVAR_CERTIFICATEFILE &TI_SETUP_GLOBALVAR_CERTIFICATEFILE="&CERTIFICATEFILE" ; Setup global variables LOCAL &TI_SETUP_GLOBALVAR_DEVICETYPE &TI_SETUP_GLOBALVAR_DEVICETYPE="&DEVICETYPE" LOCAL &TI_SETUP_GLOBALVAR_SETUPMODE &TI_SETUP_GLOBALVAR_SETUPMODE="&SETUPMODE" ; -------------------------------------------------------------------------------- ; Set up helper variables PRIVATE &BARE_METAL_SETUP &RET &BARE_METAL_SETUP=FALSE() WinCLEAR RESet SYStem.RESet IF ((!SIMULATOR())&&(SYStem.INSTANCE()!=1.)) ( PRINT %ERROR "This script must be called from MASTER GUI!" ENDDO ) ; -------------------------------------------------------------------------------- ; Target device initialization setup based on '&DEVICETYPE' and '&SETUPMODE' ; Cross check device type ( PRIVATE &isHS Do "&AUX_SCRIPT_DIR/ti_setup_generic.cmm" DETECT_HS_DEVICE RETURNVALUES &isHS IF ((!STRing.ComPare("&TI_SETUP_GLOBALVAR_DEVICETYPE","HS*"))&&(&isHS)) ( ; Essentially: GP was selected, HS detected. PRINT %WARNING "Specified device type was '&TI_SETUP_GLOBALVAR_DEVICETYPE' but detected device type is 'HS'. Continuing as '&TI_SETUP_GLOBALVAR_DEVICETYPE' device." ) ) ; Perform initialization Do "&AUX_SCRIPT_DIR/ti_setup_generic.cmm" DEVICE_INIT RETURNVALUES &RET &BARE_METAL_SETUP IF (&RET!=0.) ( PRINT %ERROR "Device initialization failed. Exiting ..." AREA ENDDO ) ; -------------------------------------------------------------------------------- ; Basic debugger setup TITLE "TRACE32 for ARM - AM62AX-CR5-MCU" ; set GUI title RESet SYStem.CPU AM62AX-CR5-MCU SYStem.CONFIG CORE 6. 1. SYStem.Option EnReset OFF ; Disable system reset IF COMBIPROBE()||UTRACE() ( SYStem.CONFIG.CONNECTOR MIPI34 ; because of converter LA-3782 ) ; Disable trace to avoid access of temporary unresponsive components Trace.METHOD NONE ; -------------------------------------------------------------------------------- ; Basic target setup SYStem.Mode Prepare IF ((STRing.ComPare("&TI_SETUP_GLOBALVAR_DEVICETYPE","HS*"))&&("&SETUPMODE"=="JTAG")) ( ; Unlock and stop secure watchdog Data.Set EZAXI:0x44135120 %LE %Long 0x4658FC21 Data.Set EZAXI:0x44135124 %LE %Long 0x3AC4F102 SCREEN.WAIT 10.uS Data.Set EZAXI:0x44135150 %LE %Long 0xA ) IF (&BARE_METAL_SETUP) ( ; Basic board setup (via AXI system bus accesses) ; Enable ATCM for Cortex-R5 Data.Set EZAXI:(0x45A20000+0x20100) %Long 0x888 ; Enable CPUn_HALT for Cortex-R5 upon PORz (WKUP_SEC_MMR) Data.Set EZAXI:(0x45A20000+0x20120) %Long 0x1 ; Configure Cortex-R5 bootvector Data.Set EZAXI:(0x45A20000+0x20110) %Long 0x0 Data.Set EZAXI:(0x45A20000+0x20114) %Long 0x0 ; Configure PLLs DO "&AUX_SCRIPT_DIR/configure_pll.cmm" MAIN DO "&AUX_SCRIPT_DIR/configure_pll.cmm" MCU ; Enable Power DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 0. 0. 1. 0x1 0x3 ; LPSC_MAIN_DM DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 0. 0. 4. 0x1 0x3 ; LPSC_DM2MAIN_ISO DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 1. 1. 9. 0x1 0x3 ; LPSC_MCU_COMMON DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 1. 1. 6. 0x1 0x3 ; LPSC_MCU_R5 DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 1. 1. 7. 0x1 0x3 ; LPSC_MCU_MCANSS_0 DO "&AUX_SCRIPT_DIR/configure_psc.cmm" 1. 1. 8. 0x1 0x3 ; LPSC_MCU_MCANSS_1 ) ; -------------------------------------------------------------------------------- ; Connect to the MCU-CR5 to program flash SYStem.Up SCREEN.OFF ; Flash Controller Power & Clock Enable ; GOSUB CLK_INIT ; Usually not requried ; Flash Pin Mux Configuration GOSUB PIN_MUX ; Flash Controller Init GOSUB OSPI_INIT GOSUB CACHE_MMU_INIT ; Flash Read ID Test GOSUB READ_ID_TEST ; -------------------------------------------------------------------------------- ; Flash declaration Break.RESet FLASHFILE.RESet FLASHFILE.Create 0x0--0x7FFFFFF &CONFIG_ERASEBLOCKSIZE ; FLASFILE.CONFIG FLASHFILE.CONFIG &CONFIG_OSPI_BASE LOCAL &DUALPORT_OPTION &DUALPORT_OPTION="" IF (&CONFIG_DUALPORT) ( ; Configure and enable run time memory access DO "&AUX_SCRIPT_DIR/am62ax-cr5_runtime_memory_access.cmm" SYStem.MemAccess DAP &DUALPORT_OPTION="/DualPort" ) FLASHFILE.TARGET 0x79100000++0x1FFF E:0x79102000++0x23FF "~~/demo/arm/flash/byte/&CONFIG_DRIVER" /KEEP &DUALPORT_OPTION ; Read FLASH Manufacturer and Device ID FLASHFILE.GETID ;GOSUB FLASHFILE_ONFI_TEST ; Read out the onfi registers in spinand flash ; SPINAND specific function to read memory GOSUB FLASHFILE_CHECK_SPINAND_READMODE ; Check BUF flag in the SR-2[3], it changes the spinand read method ; Unlock SPI NAND FLASH FLASHFILE.UNLOCK 0x0--0x7FFFFFF ; End of the test prepare only IF (&PARAM_PREPAREONLY) ( SCREEN.ON ENDDO ) ; ------------------------------------------------------------------------------ ; Flash programming example ; Open flash sector overview FLASHFILE.List ; Dump window for Serial FLASH FLASHFILE.DUMP 0x0 ;FLASHFILE.DUMP 0x0 /SPARE /Track ; Write Serial FLASH ;FLASHFILE.ERASE 0x0--0xFFFFF ; Write Serial FLASH ;FLASHFILE.LOAD * 0x0 ;FLASHFILE.LOAD * 0x0 /ComPare ; Reset device PRINT "Please power-cycle the board after flash program is complete" SCREEN.ON ENDDO READ_ID_TEST: ( ; In case of errors you can try to read the ID via: ; GOSUB READ_ID_TEST ; ; Check the output of the AREA window. ; Expected output ID: ; 0xFF (Dummy) ; 0xEF (Manufacture) ; 0xBC ; 0x21 LOCAL &rdata &CTRLREG &RXDATA0 &RXDATA1 &CTRLREG=&CONFIG_OSPI_BASE+0x090 &RXDATA0=&CONFIG_OSPI_BASE+0x0A0 &RXDATA1=&CONFIG_OSPI_BASE+0x0A4 &cmd=0x9f<<24. ; cmd &rd=0x1<<23. ; rd data enable &rd_num=0x7<<20. ; 7+1==8bytes, max &cmd_exec=0x1 ; cmd execution Data.Set EZAXI:&CTRLREG %LE %Long (&cmd|&cmd_exec|&rd_num|&rd) ;write cmd + write data WAIT 100.ms &rdata=Data.Long(EZAXI:&RXDATA0) ;read lower , 8byte fifo PRINT "1st 0x" (&rdata)&0xFF " (Dummy)" ; ; RXFIFO0 PRINT "2nd 0x" (&rdata>>8.)&0xFF " (Manufacture)" PRINT "3rd 0x" (&rdata>>16.)&0xFF " (Device ID)[15:8]" PRINT "4th 0x" (&rdata>>24.)&0xFF " (Device ID)[7:0]" &rdata=Data.Long(EZAXI:&RXDATA1) ;read upper , 8byte fifo ;PRINT "5th 0x" (&rdata)&0xFF ;PRINT "6th 0x" (&rdata>>8.)&0xFF ;PRINT "7th 0x" (&rdata>>16.)&0xFF ;PRINT "8th 0x" (&rdata>>24.)&0xFF RETURN ) FLASHFILE_ONFI_TEST: ( FLASHFILE.GETONFI /VM PRINT "A page size: " %Decimal Data.Long(VM:0x50) "./" Data.Long(VM:0x54) ".Bytes (main/spare)" PRINT "A block size: 0x" Data.Long(VM:0x50)*Data.Long(VM:0x5C) " (" %Decimal Data.Long(VM:0x5C) ".Pages)" PRINT "A device size: 0x" Data.Long(VM:0x50)*Data.Long(VM:0x5C)*Data.Long(VM:0x60) " Bytes" RETURN ) FLASHFILE_CHECK_SPINAND_READMODE: ( ; The Buffer Read Mode (BUF=1) requires a Column Address to start outputting the existing data inside ; the Data Buffer, and once it reaches the end of the data buffer (Byte 2,111), DO (IO1) pin will become ; high-Z state. ; The Continuous Read Mode (BUF=0) doesn��t require the starting Column Address. The device will ; always start output the data from the first column (Byte 0) of the Data buffer, and once the end of the ; data buffer (Byte 2,048) is reached, the data output will continue through the next memory page. ; 2048+64, Buffer Read Mode (BUF=1), bcz the OSPI RX buffer is not large enough (Not A nand page size) FLASHFILE.SPI.CMD 0x0F 0xB0 /READ 0x4 VM:0 IF Data.Byte(VM:0x0)!=0x18 ( FLASHFILE.SPI.CMD 0x1F 0xB0 0x18 ;Set ECC[4]=1, BUF[3]=1 in Status Register-2 ) RETURN ) OSPI_INIT: ( Data.Set EZAXI:&CONFIG_OSPI_BASE+0x0 %LE %Long 0x0 Data.Set EZAXI:&CONFIG_OSPI_BASE+0x4 %LE %Long 0x00000013 ; 4B Addr Read Data.Set EZAXI:&CONFIG_OSPI_BASE+0x8 %LE %Long 0x00000012 ; 4B Addr Write Data.Set EZAXI:&CONFIG_OSPI_BASE+0x0 %LE %Long 0x80800000 Data.Set EZAXI:&CONFIG_OSPI_BASE+0x14 %LE %Long 0x1003; 4B Address mode, 3B Addr: 0x1002 Data.Set EZAXI:&CONFIG_OSPI_BASE+0x10 %LE %Long 0x21 Data.Set EZAXI:&CONFIG_OSPI_BASE+0x1C %LE %Long 0xFFFFFFFF ; Data.Set EZAXI:&CONFIG_OSPI_BASE+0xC %LE %Long (0xFF<<16.)|(0xFF<<8.) ; !!!!! OSPI_DEV_DELAY_REG because of writing !!!!! Data.Set EZAXI:&CONFIG_OSPI_BASE+0x0 %LE %Long 0x00000081|(0x1<<19.)|(0xE<<10.) ; 0x1==baudrate_div4, enable usage of OSPI_CS0 Data.Set EZAXI:&CONFIG_OSPI_BASE+0x1C %LE %Long 0x04000000 ;ospi_setdirectcutoff, end of the flash address RETURN ) PIN_MUX: ( ;MMR_unlock Data.Set EZAXI:0x000F5008 %Long 0x68EF3490 ; Data.Set EZAXI:0x000F500C %Long 0xD172BC5A Data.Set EZAXI:0x000F4000 %Long 0x00040000 ; L22 : CTRLMMR_WKUP_PADCONFIG0 MCU_OSPI0_CLK Data.Set EZAXI:0x000F4004 %Long 0x00040000 ; : MCU_OSPI0_LBCLKO Data.Set EZAXI:0x000F4008 %Long 0x00040000 ; : MCU_OSPI0_DQS Data.Set EZAXI:0x000F400C %Long 0x00040000 ; : MCU_OSPI0_D0 Data.Set EZAXI:0x000F4010 %Long 0x00040000 ; : MCU_OSPI0_D1 Data.Set EZAXI:0x000F4014 %Long 0x00040000 ; : MCU_OSPI0_D2 Data.Set EZAXI:0x000F4018 %Long 0x00040000 ; : MCU_OSPI0_D3 Data.Set EZAXI:0x000F401C %Long 0x00040000 ; : MCU_OSPI0_D4 Data.Set EZAXI:0x000F4020 %Long 0x00040000 ; : MCU_OSPI0_D5 Data.Set EZAXI:0x000F4024 %Long 0x00040000 ; : MCU_OSPI0_D6 Data.Set EZAXI:0x000F4028 %Long 0x00040000 ; : MCU_OSPI0_D7 Data.Set EZAXI:0x000F402C %Long 0x00040000 ; : MCU_OSPI0_CSn0 Data.Set EZAXI:0x000F4030 %Long 0x00040000 ; : MCU_OSPI0_CSn1 Data.Set EZAXI:0x000F4034 %Long 0x00040001 ; : MCU_OSPI0_CSn2 Data.Set EZAXI:0x000F4038 %Long 0x00040001 ; : MCU_OSPI0_CSn3 RETURN ) CLK_INIT: ( Data.Set EZAXI:0x40F09008 %Long 0x68EF3490 ; CTRLMMR_MCU_LOCK2_KICK0 Data.Set EZAXI:0x40F0900C %Long 0xD172BC5A Data.Set EZAXI:0x40d01010 %Long 0x68EF3490 ;MCU_PLL1_KICK0 Data.Set EZAXI:0x40d01014 %Long 0xD172BC5A ;MCU_PLL1_KICK1 wait 1.ms IF (&CONFIG_USE_PLL2) ( Data.Set EZAXI:0x40D02090 %Long 0x0000800b ; MCU_PLL2_HSDIV_CTRL4 --> 166MHz wait 1.ms Data.Set EZAXI:0x40F08030 %Long 0x1 ;CTRLMMR_MCU_OSPI0_CLKSEL, 2h - MCU_PLL2_HSDIV4_CLKOUT ) ELSE ( ;freq: PLL1 (2.4G) -> HSDIV4 (/5+1) -> 400Mhz --> BAUD/x Data.Set EZAXI:0x40D01090 %Long 0x8005 ;MCU_PLL1_HSDIV_CTRL4 wait 1.ms Data.Set EZAXI:0x40F08030 %Long 0x0 ;CTRLMMR_MCU_OSPI0_CLKSEL, 0h - MCU_PLL1_HSDIV4_CLKOUT ) wait 1.ms RETURN ) CACHE_MMU_INIT: ( PRIVATE &i &tmpReg ; Configure small region setup for flash programming PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x016 %Long 0x00000000 ; set default PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x216 %Long 0x0000003F PER.Set.SaveIndex C15:0x026 %Long 0x0 C15:0x416 %Long 0x00001310 PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x016 %Long 0x60000000 ; setup flash window PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x216 %Long 0x00000035 PER.Set.SaveIndex C15:0x026 %Long 0x1 C15:0x416 %Long 0x00001301 PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x016 %Long 0x79100000 ; setup buffer space PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x216 %Long 0x00000027 PER.Set.SaveIndex C15:0x026 %Long 0x2 C15:0x416 %Long 0x0000030C ; Reset all other MPU regions &i=3. WHILE &i<16. ( PER.Set.SaveIndex C15:0x026 %Long &i C15:0x016 %Long 0x0 PER.Set.SaveIndex C15:0x026 %Long &i C15:0x216 %Long 0x0 PER.Set.SaveIndex C15:0x026 %Long &i C15:0x416 %Long 0x0 &i=&i+1 ) ; Enable MPU and I and D caches &tmpReg=Data.Long(C15:0x1) &tmpReg=&tmpReg|0x1 ; enable MPU &tmpReg=(&tmpReg|((0x1<<2.))) ; enable D cache &tmpReg=(&tmpReg|((0x1<<12.))) ; enable I cache Data.Set C15:0x1 %Long &tmpReg RETURN ) ; detect the flash address mode by the internal flash register (0x0080_0003) ; CR2V : should come 0x08(3B) or 0x88(4B) SPI_4B_ADDRMODE_ENABLE: ( PRIVATE ®Data SILENT.FLASH.SPI.CMD 1. 0x06 SILENT.FLASH.SPI.CMD 1. 0x71 0x80 0x00 0x03 0x88 ; write 0x88 to CR2V , switch 3B->4B address mode Data.Set VM:0x0--0xFF %Long 0x0 SILENT.FLASH.SPI.CMD 1. 0x65 0x00 0x80 0x00 0x03 0x0 /READ 0x4 vm:0x0 ;4Bytes Address mode ®Data=Data.Byte(vm:0x0) IF ®Data!=0x88 ( PRINT "We expect 0x08 latency(dummy) cycles but we got the dummy cycle 0x" %Hex ®Data ENDDO ) RETURN )