;=======================================================================!
; 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
;========================================================================
|