;=======================================================================! ; LIBRAM.SCopyright (c) 2012 by Data Display UK Ltd.10-08-12! ;=======================================================================! ; vim: set ts=8 sw=8:; [tabs:8] .file"LibRam.s" .syntax unified .thumb .include "amacs.inc" .include "LibPid.inc" ;-----------------------------------------------------------------------! ; Publics! ;-----------------------------------------------------------------------! .globalInitRam, InitLPRAM, InitFPGA, InitSDRAM .globalMemTestData, MemTestAddr, MemTestDev, MemTestSDRAM .globalIsRamOk ;-----------------------------------------------------------------------! ; Constants and Equates! ;-----------------------------------------------------------------------! scsBase= 0x400FC000; APB1-31 System Control & Status scsSCS= 0x1A0; scsEClkSel= 0x100; scsEDelay= 0x1DC; scsECal= 0x1E0; ;------------------------------------------------------------------------ emcBase= 0x2009C000; External Memory Controller emcCtrl= 0x000; emcStatus= 0x004; emcConfig= 0x008; emcDCtrl= 0x020; emcDRefresh= 0x024; emcDRConfig= 0x028; emcDRPrchg= 0x030; emcDRas= 0x034; emcDSRex= 0x038; emcDApr= 0x03C; emcDDal= 0x040; emcDWr= 0x044; emcDRC= 0x048; emcDRfc= 0x04C; emcDXsr= 0x050; emcDRrd= 0x054; emcDMrd= 0x058; emcDConfig0= 0x100; SDRAM A000 0000 (32 MByte) emcDRasCas0= 0x104; ;emcDConfig1= 0x120; ;emcDRasCas1= 0x124; ;emcDConfig2= 0x140; ;emcDRasCas2= 0x144; ;emcDConfig3= 0x160; ;emcDRasCas3= 0x164; ; emcSExtWait= 0x080; emcSConfig0= 0x200; LPRAM 8000 0000 (512 KByte) emcSWaitWen0= 0x204; emcSWaitOen0= 0x208; emcSWaitRd0= 0x20C; emcSWaitPage0= 0x210; emcSWaitWr0= 0x214; emcSWaitTurn0= 0x218; emcSConfig1= 0x220; FPGA 9000 0000 (MMIO) emcSWaitWen1= 0x224; emcSWaitOen1= 0x228; emcSWaitRd1= 0x22C; emcSWaitPage1= 0x230; emcSWaitWr1= 0x234; emcSWaitTurn1= 0x238; ;emcSConfig2= 0x240; ;emcSWaitWen2= 0x244; ;emcSWaitOen2= 0x248; ;emcSWaitRd2= 0x24C; ;emcSWaitPage2= 0x250; ;emcSWaitWr2= 0x254; ;emcSWaitTurn2= 0x258; ;emcSConfig3= 0x260; ;emcSWaitWen3= 0x264; ;emcSWaitOen3= 0x268; ;emcSWaitRd3= 0x26C; ;emcSWaitPage3= 0x270; ;emcSWaitWr3= 0x274; ;emcSWaitTurn3= 0x278; ;-----------------------------------------------------------------------! ; CODE! ;-----------------------------------------------------------------------! .text .align 4,0 vTag:.asciz"@(#) LibRam.s v 1.00.0" .align 4,0 ;------------------------------------------------------------------------ emcPins:; Port Pin Count Func Flags .word(1<<28)+(25<<20)+( 1<<12)+(5<<8)+0x00; clock out for PLD .word(2<<28)+(16<<20)+( 3<<12)+(1<<8)+0x09; See .word(2<<28)+(20<<20)+( 1<<12)+(1<<8)+0x09; Matrix v6 .word(2<<28)+(24<<20)+( 1<<12)+(1<<8)+0x09; .word(2<<28)+(28<<20)+( 4<<12)+(1<<8)+0x09; .word(3<<28)+( 0<<20)+(32<<12)+(1<<8)+0x09; Data bus .word(4<<28)+( 0<<20)+(19<<12)+(1<<8)+0x09; Addr bus .word(4<<28)+(24<<20)+( 4<<12)+(1<<8)+0x09; .word(4<<28)+(30<<20)+( 2<<12)+(1<<8)+0x09,0; Terminate ; add pullup and fast slew ;-----------------------------------------------------------------------! ; Init All RAM! ;-----------------------------------------------------------------------! fn InitRam push{lr}; save regs ;---------------------------------------; movsr0, pEMC; enable peripheral clock blPowerOn; i.e PowerOn(pEMC) adrr0, emcPins; Assign all pins blPinSetup; ;---------------------------------------; ldrr3, =scsBase; emc global options ldrr0, [r3, scsSCS]; (i.e x = LPC_SYSTEM->scsSCS) LPC Open names are a guess bicsr0, 0x07; NB equiv to x = x & ~number orrsr0, 0x04; addr shift/full reset/!burst NB equiv to x = x | number strr0, [r3, scsSCS]; i.e LP_SYSTEM->scsSCS = x movr0, 1; EClk selection strr0, [r3, scsEClkSel]; by 2 to not exceed max (80MHz) movwr0, (16<<8)+(16<<0); FB = 4, CMD = 2 (x 250 psec) strr0, [r3, scsEDelay]; for SDRAMFIX ME !!! ;---------------------------------------; ldrr3, =emcBase; get EMC base addr movr0, (0<<2)+(0<<1)+(1<<0); !low power/!mirror/enable strr0, [r3, emcCtrl]; movsr0, (0<<1)+(0<<0); clk ratio 1:1/little endian strr0, [r3, emcConfig]; movsr0, 0; strr0, [r3, emcSExtWait]; not using 'extended wait' ;---------------------------------------; blInitLPRAM; want LPRAM 'call i.e InitLPRAM()' blInitFPGA; want FPGA blInitSDRAM; want SDRAM ;---------------------------------------; movr0, (0<<2)+(0<<1)+(1<<0); !low power/!mirror/enable strr0, [r3, emcCtrl]; now, (re)enable the EMC pop{pc}; return fe InitRam ;-----------------------------------------------------------------------! ; Init Dynamic RAM! ;-----------------------------------------------------------------------! eClk= (120/2); memory clock (CClk/2) = 60 MHz [i.e a #define] ; select one of Row-Bank-Column or Bank-Row-Column AMD= 0; addr mode: 0 = R-B-C, 1 = B-R-C MSF= ((9+2+2)-(AMD*2)); Mode data shift factor ; [9 cols, 4 banks, 32bit bus] CL= 3; CAS Latency (tClks) .macrons2clk sym ns; symbol name, duration in nsec*10 \sym= (((\ns*eClk)+9999)/10000); ns to memory clocks (round up) .endm ns2clktRP, 200; 20.0 ns see MT48LC16M.pdf ns2clktRAS, 440; 44.0 ns ns2clktXSR, 750; 75.0 ns ns2clktAPR, 200; 20.0 ns (using tRCD) tDAL = 5; 5 tClk ns2clktWR, 75; 7.5 ns [plus 1 tClk] ns2clktRC, 660; 66.0 ns ns2clktRFC, 660; 66.0 ns ns2clktRRD, 150; 15.0 ns tMRD = 2; 2 tClk ns2clktRCD, 200; 20 ns ns2ClkRFP, (640000000/4096); 4K refresh cycles per 64 mSec ModeWd= ((0<<9)+(0<<7)+(CL<<4)+(0<<3)+(2<<0)) ; Burst/Normal/CL/Seq/Burst=4 ;------------------------------------------------------------------------ fn InitSDRAM movr0, (0<<2)+(0<<1)+(1<<0); !low power/!mirror/enable strr0, [r3, emcCtrl]; EMC needs to be enabled for init movsr0, (0<<8)+(0<<0); clock = 1:1, Little Endian strr0, [r3, emcConfig]; movwr0, (1<<14)+(AMD<<12)+(2<<9)+(1<<7)+(0<<3) ; 1 = 32bit data bus ; 0 = Row-Bank-Column [AMD] ; 2 = 128 Kbit device ; 1 = 16bit device [times 2] ; 0 = SDRAM movtr0, (0<<4)+(0<<3); !WP/!buffer strr0, [r3, emcDConfig0]; set options as above movwr0, (CL<<8)+(tRAS<<0); set ras and cas strr0, [r3, emcDRasCas0]; movsr0, 1; read strategy: command delayed strr0, [r3, emcDRConfig]; movsr0, tRP-1; strr0, [r3, emcDRPrchg]; movsr0, tRAS-1; strr0, [r3, emcDRas]; movsr0, tXSR-1; strr0, [r3, emcDSRex]; movsr0, tAPR-1; strr0, [r3, emcDApr]; movsr0, tDAL; strr0, [r3, emcDDal]; movsr0, tWR-1+1; strr0, [r3, emcDWr]; movsr0, tRC-1; strr0, [r3, emcDRC]; movsr0, tRFC-1; strr0, [r3, emcDRfc]; movsr0, tXSR-1; strr0, [r3, emcDXsr]; movsr0, tRRD-1; strr0, [r3, emcDRrd]; movsr0, tMRD-1; strr0, [r3, emcDMrd]; movwr0, (3<<7)+(0<<5)+(0<<2)+(1<<1)+(1<<0) strr0, [r3, emcDCtrl]; NOP/Clk/!SRef/ClkAll/ClkE movwr0, (120*100)/3; delay 100 uSec 0:subsr0, 1; bne0b; movwr0, (2<<7)+(0<<5)+(0<<2)+(1<<1)+(1<<0) strr0, [r3, emcDCtrl]; PALL/Clk/!SRef/ClkAll/ClkE movsr0, 1; set fastest refresh strr0, [r3, emcDRefresh]; movwr0, (120*10)/3; delay 10 uSec [gt 128 tClk] 0:subsr0, 1; bne0b; movsr0, (RFP>>4); set 'normal' refresh rate movsr0, 25; DEBUG override strr0, [r3, emcDRefresh]; movwr0, (120*10)/3; delay 10 uSec [gt 128 tClk] 0:subsr0, 1; bne0b; movwr0, (1<<7)+(0<<5)+(0<<2)+(1<<1)+(1<<0) strr0, [r3, emcDCtrl]; MODE/Clk/!SRef/ClkAll/ClkE movwr0, ModeWd; load the mode register lslsr0, MSF; apply addr shift movsr1, 0xA0000000; SDRAM base address ldrr0, [r1, r0]; 'set' mode movwr0, (120*10)/3; delay 10 uSec [gt 128 tClk] 0:subsr0, 1; bne0b; movwr0, (0<<7)+(0<<5)+(0<<2)+(0<<1)+(0<<0) strr0, [r3, emcDCtrl]; normal running movwr0, (1<<14)+(AMD<<12)+(3<<9)+(1<<7)+(0<<3) ; 32bit data bus ; 1 = Bank-Row-Column ; 256 Kbit device ; 16bit device [times 2] ; SDRAM movtr0, (0<<4)+(1<<3); !WP/buffer [Enable Buffer] strr0, [r3, emcDConfig0]; set options as above bxlr; fe InitSDRAM ;-----------------------------------------------------------------------! ; MemTestSDRAM! ;-----------------------------------------------------------------------! MemSz= 32*1024*1024; nbr bytes (32 MB) fn MemTestSDRAM ;---------------------------------------; ; populate ram with deterministic data; movsr3, 0xA0000000; SDRAM movsr2, MemSz; nbr bytes (64 MB) movsr1, 11; start value 0:strr1, [r3], 4; *p++ = v++ ldrr0, [r3, -4]; read back addsr1, 1; subsr2, 4; while (--nWords) bgt0b; ;---------------------------------------; ; validate and invert; movsr3, 0xA0000000; SDRAM movsr2, MemSz; nbr bytes (32 MB) movsr1, 11; start value 0:ldrr0, [r3]; v = *p subsr0, r0, r1; validate bne9f; OOPS mvnsr0, r1; inverse strr0, [r3], 4; *p++ = ~(v++) addsr1, 1; subsr2, 4; while (--nWords) bgt0b; ;---------------------------------------; ; validate and clear; movsr3, 0xA0000000; SDRAM movsr2, MemSz; nbr bytes (32 MB) movsr1, 11; start value 0:ldrr0, [r3]; v = ~*p mvnsr0, r0; subsr0, r0, r1; validate bne9f; OOPS movsr0, 0; clear strr0, [r3], 4; *p++ = 0 addsr1, 1; v++ subsr2, 4; while (--nWords) bgt0b; 9:bxlr; return (0 = ok) fe MemTestSDRAM ;-----------------------------------------------------------------------! ; IsRamOk! ;-----------------------------------------------------------------------! ; r0 = start addr, r1 = size bytes fn IsRamOk push{r4,lr}; save regs addsr1, 3; round up movsr1, r1, lsr 2; cvt to dwords 0:ldrr4, [r0]; save current movsr2, 0xAAAAAAAA; probe strr2, [r0]; ldrr3, [r0]; strr4, [r0]; replace current subsr2, r3; check cbnzr2, 9f; OOPS! movsr2, 0x55555555; probe strr2, [r0]; ldrr3, [r0]; strr4, [r0], 4; replace current -- bump addr subsr2, r3; check cbnzr2, 9f; OOPS! subsr1, 1; loop bne0b; 9:movsr0, r2; zero = OK pop{r4,pc}; return fe IsRamOk ;-----------------------------------------------------------------------! ; LDR pool! ;-----------------------------------------------------------------------! .align 2,0xFF Pool: .pool; LDR pool ;------------------------------------------------------------------------ .align4,0xFF ;======================================================================== |