; -------------------------------------------------------------------------------- ; @Title: Simple OSPI flash loading demo on AM62X-SKEVM (FLASH) ; @Description: ; S28HS512T CYPRESS flash is on OSPI_CS0 ( Cortex-R5 MAIN0 ) ; Additionally, the flashes below are also supported ; MT35XU512, IS25LP128 ... ; ; SRAM: 0x70000000 ; OSPI(controller) Base: 0x0FC40000 ; OSPI memory mapped ADDRESS: 0x60000000 (FSS0_DAT_REG1) ; ; Prerequisites: ; * Connect Debug Cable to J17 via adapter LA-3780 ; ; @Keywords: ARM, Cortex-R5, OSPI, S28HS512 ; @Author: CMO ; @Board: AM62X-SKEVM ; @Chip: AM625X-CR5 ; @Copyright: (C) 1989-2024 Lauterbach GmbH, licensed for use with TRACE32(R) only ; -------------------------------------------------------------------------------- ; $Id: am62x-ospi.cmm 13463 2024-05-21 10:06:25Z 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) &PARAM_DUALPORT=STRing.SCANAndExtract("¶meters","DUALPORT=","1") LOCAL &OSPI_BASE &OSPI_MEMORY_BASE &SRAM_FLASH_ALGORITHM_BASE &OSPI_BASE=0x0FC40000 &OSPI_MEMORY_BASE=0x60000000 ; flash contents memory mapped address FSS0_DAT_REG1 &SRAM_FLASH_PROGRAM_BASE=0x70000000 ; SRAM base address to execute the flash program from ; -------------------------------------------------------------------------------- ; Set up helper variables LOCAL &PDD &AUX_SCRIPT_DIR &PRESENT_SCRIPT &PDD=OS.PDD() &AUX_SCRIPT_DIR="&PDD/hardware/am62xx/am62x-skevm/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/am62x-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)+0x64 %LE %Long 0yxxxxxxxxxxxxxx0000xxxxxxxxxxxxxx ; Disable WIR mode AM625X-CR5 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=AM625X-CR5" 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 AM625X-CR5" RESet SYStem.RESet System.CPU AM625X-CR5 SYStem.CONFIG CORE 8. 1. SYStem.Option EnReset OFF SYSTEM.JTAGCLOCK CTCK 10MHz IF COMBIPROBE()||UTRACE() ( IF (ID.WHISKER(0.)==0x12) SYStem.CONFIG.CONNECTOR MIPI20T ELSE SYStem.CONFIG.CONNECTOR MIPI34 ) ; 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 R5F Data.Set EZAXI:(0x45A20000+0x1C100) %Long 0x888 ; Enable CPUn_HALT for R5F upon PORz (WKUP_SEC_MMR) Data.Set EZAXI:(0x45A20000+0x1C120) %Long 0x1 ; Configure R5F bootvector Data.Set EZAXI:(0x45A20000+0x1C110) %Long 0x0 Data.Set EZAXI:(0x45A20000+0x1C114) %Long 0x0 ; Configure PLLs DO "&AUX_SCRIPT_DIR/configure_pll.cmm" MAIN ; 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" 0. 0. 28. 0x1 0x3 ; LPSC_FSS_OSPI ) ; -------------------------------------------------------------------------------- ; Configure Flash controller SYStem.Up SCREEN.OFF GOSUB PIN_MUX GOSUB CLK_INIT GOSUB OSPI_INIT GOSUB CACHE_MMU_INIT SCREEN.ON GOSUB READ_ID_TEST Break.RESet FLASH.RESet FLASH.Create 1. &OSPI_MEMORY_BASE++0x03FFFFFF 0x40000 TARGET Byte ; for MT35XU512 sector layout IF ("&PARAM_DUALPORT"!="1") ( FLASH.TARGET &SRAM_FLASH_PROGRAM_BASE &SRAM_FLASH_PROGRAM_BASE+0x2000 0x1000 ~~/demo/arm/flash/byte/snor_am644x.bin ) ELSE ( SYStem.MemAccess DAP FLASH.TARGET &SRAM_FLASH_PROGRAM_BASE E:&SRAM_FLASH_PROGRAM_BASE+0x2000 0x1000 ~~/demo/arm/flash/byte/snor_am644x.bin /DUALPORT ) ; Read FLASH Manufacturer and Device ID SILENT.FLASH.SPI.CMD 1. 0x9F /READ 0x4 vm:0x0 IF (Data.Long(vm:0)&0xFFFF)==0x5B34 //S28HS512 id code ( PRINT "found S28HS512" GOSUB SPI_4B_ADDRMODE_ENABLE SILENT.FLASH.SPI.CMD 1. 0x65 0x00 0x80 0x00 0x04 0x0 /READ 0x1 vm:0 ; Read Any Register to verify CFR3V IF (Data.Byte(vm:0)&0x08)==0x00 //00: hybrid ( PRINT "detect the flash is the hybrid mode" FLASH.Delete 1. FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00000000)++0x0001FFFF 0x01000 TARGET Byte ; 32 x 4K FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00020000)++0x0001FFFF 0x20000 TARGET Byte ; 1 x 128k FLASH.Create 1. (&OSPI_MEMORY_BASE+0x00040000)++(0x03FFFFFF-0x40000) 0x40000 TARGET Byte ; rest x 256k ) ELSE // uniform mode ( FLASH.Delete 1. FLASH.Create 1. &OSPI_MEMORY_BASE++0x03FFFFFF 0x40000 TARGET Byte ) ) ELSE IF (Data.Long(vm:0)&0xFFFF)==0x9D60 //IS25LP128 ( PRINT "found IS25LP128" //flash supports only the 3bytes address mode FLASH.RESet FLASH.Create 1. &OSPI_MEMORY_BASE++0x0FFFFFF 0x10000 TARGET Byte ; for IS25LP128 sector layout IF ("&PARAM_DUALPORT"!="1") ( FLASH.TARGET &SRAM_FLASH_PROGRAM_BASE &SRAM_FLASH_PROGRAM_BASE+0x2000 0x1000 ~~/demo/arm/flash/byte/snor3b_am644x.bin ) ELSE ( SYStem.MemAccess DAP FLASH.TARGET &SRAM_FLASH_PROGRAM_BASE E:&SRAM_FLASH_PROGRAM_BASE+0x2000 0x1000 ~~/demo/arm/flash/byte/snor3b_am644x.bin /DUALPORT ) ) ; Flash script ends here if called with parameter PREPAREONLY IF &PARAM_PREPAREONLY ENDDO PREPAREDONE ; -------------------------------------------------------------------------------- ; Flash programming example DIALOG.YESNO "Program flash memory?" LOCAL &progflash ENTRY &progflash IF &progflash ( FLASH.ReProgram.ALL Data.LOAD.auto * ;Data.LOAD.Binary * &OSPI_MEMORY_BASE ; Finalize flash programming FLASH.ReProgram.off ; Reset device PRINT "Please power-cycle the board after flash program is complete" ) ENDDO ; -------------------------------------------------------------------------------- ; Helper functions 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 for S28HS512 ; 0x34 ; 0x5B (or 0x5B) ; 0x1A ; 0x0F ; 0x3 ; 0x90 ; ... LOCAL &CTRLREG &RXDATA0 &RXDATA1 &cmd &rd &rd_num &cmd_exec &rdata &CTRLREG=&OSPI_BASE+0x090 &RXDATA0=&OSPI_BASE+0x0A0 &RXDATA1=&OSPI_BASE+0x0A4 &cmd=0x9f<<24. //cmd &rd=0x1<<23. //rd data enable &rd_num=0x7<<20. //7+1==8bytes &cmd_exec=0x1 //cmd execution Data.Set EZAXI:&CTRLREG %LE %Long (&cmd|&cmd_exec|&rd_num|&rd) ;write cmd + write data SCREEN.WAIT 100.ms &rdata=Data.Long(EZAXI:&RXDATA0) ;read lower , 8byte fifo PRinT "1st 0x" (&rdata)&0xFF " (Manufacturer)" ; //RXFIFO0 PRinT "2nd 0x" (&rdata>>8.)&0xFF " (Device ID)" PRinT "3rd 0x" (&rdata>>16.)&0xFF PRinT "4th 0x" (&rdata>>24.)&0xFF &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 ) PIN_MUX: ( ; PinMux Data.Set EZAXI:0x000F5008 %Long 0x68ef3490 ; PADMMR_LOCK5_KICK0 -> unlock I/O partition Data.Set EZAXI:0x000F500C %Long 0xd172bc5a ; PADMMR_LOCK5_KICK1 screen.wait 10.ms Data.Set EZAXI:0x000F4000 %Long 0x00000000 ; H24: PADCONFIG0 OSPI0_CLK Data.Set EZAXI:0x000F4004 %Long 0x00040000 ; G25: PADCONFIG1 OSPI0_LBCLKO Data.Set EZAXI:0x000F4008 %Long 0x00240000 ; J24: PADCONFIG2 OSPI0_DQS Data.Set EZAXI:0x000F400C %Long 0x00040000 ; E25: PADCONFIG3 OSPI0_D0 Data.Set EZAXI:0x000F4010 %Long 0x00040000 ; G24: PADCONFIG4 OSPI0_D1 Data.Set EZAXI:0x000F4014 %Long 0x00040000 ; F25: PADCONFIG5 OSPI0_D2 Data.Set EZAXI:0x000F4018 %Long 0x00040000 ; F24: PADCONFIG6 OSPI0_D3 Data.Set EZAXI:0x000F401C %Long 0x00040000 ; J23: PADCONFIG7 OSPI0_D4 Data.Set EZAXI:0x000F4020 %Long 0x00040000 ; J26: PADCONFIG8 OSPI0_D5 Data.Set EZAXI:0x000F4024 %Long 0x00040000 ; H25: PADCONFIG9 OSPI0_D6 Data.Set EZAXI:0x000F4028 %Long 0x00040000 ; J22: PADCONFIG10 OSPI0_D7 Data.Set EZAXI:0x000F402C %Long 0x00000000 ; F23: PADCONFIG11 OSPI0_CSn0 Data.Set EZAXI:0x000F4030 %Long 0x00000000 ; G21: PADCONFIG12 OSPI0_CSn1 Data.Set EZAXI:0x000F4034 %Long 0x00000002 ; H21: PADCONFIG13 OSPI0_CSn2 Data.Set EZAXI:0x000F4038 %Long 0x00000001 ; E24: PADCONFIG14 OSPI0_CSn3 Data.Set EZAXI:0x000F5008 %Long 0x43015008 ; PADMMR_LOCK5_KICK0 -> lock I/O partition Data.Set EZAXI:0x000F500C %Long 0x4301500C ; PADLMMR_LOCK5_KICK1 RETURN ) ; OSPI is from MAIN_PLL0_HSDIV1_CLOCKOUT (200MHz) or MAIN_PLL1_HSDIV5_CLOCKOUT CLK_INIT: ( Data.Set EZAXI:0x00109008 %Long 0x68EF3490 ; CTRLMMR_MCU_LOCK2_KICK0 Data.Set EZAXI:0x0010900C %Long 0xD172BC5A WAIT 1.ms ;freq: PLL1 (2.4G) -> HSDIV4 (/5+1) -> 400Mhz --> BAUD/x Data.Set EZAXI:0x00680084 %Long 0x8005 ;PLL0_HSDIV1_CTRL WAIT 1.ms Data.Set EZAXI:0x00108500 %Long 0x0 ;CTRLMMR_OSPI0_CLKSEL, 0h - MAIN_PLL0_HSDIV1_CLKOUT WAIT 1.ms RETURN ) CACHE_MMU_INIT: ( PRIVATE &i &tmpReg ; Enable MPU and disable I and D caches &tmpReg=Data.Long(C15:0x1) &tmpReg=&tmpReg|0x1 ; enable MPU &tmpReg=(&tmpReg&(~(0x1<<2.))) ; disable D cache &tmpReg=(&tmpReg&(~(0x1<<12.))) ; disable I cache Data.Set C15:0x1 %Long &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 &OSPI_MEMORY_BASE ; 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 &SRAM_FLASH_PROGRAM_BASE ; 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. ) RETURN ) OSPI_INIT: ( Data.Set EZAXI:&OSPI_BASE+0x0 %LE %Long 0x0 Data.Set EZAXI:&OSPI_BASE+0x4 %LE %Long 0x00000013 ; 4B Addr Read Data.Set EZAXI:&OSPI_BASE+0x8 %LE %Long 0x00000012 ; 4B Addr Write Data.Set EZAXI:&OSPI_BASE+0x0 %LE %Long 0x80800000 Data.Set EZAXI:&OSPI_BASE+0x14 %LE %Long 0x1003; 4B Address mode, 3B Addr: 0x1002 Data.Set EZAXI:&OSPI_BASE+0x10 %LE %Long 0x21 Data.Set EZAXI:&OSPI_BASE+0x1C %LE %Long 0xFFFFFFFF Data.Set EZAXI:&OSPI_BASE+0xC %LE %Long (0xFF<<16.)|(0xFF<<8.) ; !!!!! OSPI_DEV_DELAY_REG because of writing !!!!! Data.Set EZAXI:&OSPI_BASE+0x0 %LE %Long 0x00000081|(0x1<<19.)|(0xE<<10.) ; 0x1==baudrate_div4, enable usage of OSPI_CS0 Data.Set EZAXI:&OSPI_BASE+0x1C %LE %Long 0x04000000 ;ospi_setdirectcutoff, end of the flash address Data.Set EZAXI:&OSPI_BASE+0x0 %LE %Long 0x00000081|(0x5<<19.)|(0xE<<10.) ; pll1 divide, Enable using OSPI_CS0 RETURN ) SPI_4B_ADDRMODE_ENABLE: ( PRIVATE ®Data Data.Set VM:0x0--0xFF %Long 0x0 SILENT.FLASH.SPI.CMD 1. 0x65 0x80 0x00 0x03 0x0 /READ 0x1 vm:0x0 ;3Bytes Address mode ®Data=Data.Byte(vm:0x0) IF ®Data==0x08 ( // it means the current flash is 3Byte address mode, so it should switch to the 4Byte address mode for the 4b flash driver file. SILENT.FLASH.SPI.CMD 1. 0x65 0x80 0x00 0x03 0x00 /READ 0x1 vm:0x0 ;3Bytes Address mode 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 SCREEN.WAIT 10.ms ) SILENT.FLASH.SPI.CMD 1. 0x65 0x00 0x80 0x00 0x03 0x0 /READ 0x1 vm:0x0 ;4Bytes Address mode ®Data=Data.Byte(vm:0x0) IF ®Data==0x88 ( PRINT "4Bytes address mode enabled" ) ELSE ( PRINT "We expect 0x08 latency(dummy) cycles but we got the dummy cycle 0x" %Hex ®Data ENDDO ) RETURN )