; > TestSrc.Mem1IOMD TTL RISC OS 2+ POST memory linetest ; ; This test code is used to perform basic integrity tests on DRAM. ; It doesn't test all locations - just walks patterns through data ; and address lines. ; ;------------------------------------------------------------------------ ; History ; ; Date Name Comment ; ---- ---- ------- ; 1-Jun-93 ArtG Derived from Mem1 for use on Medusa ; 18-Nov-94 RCM Morris changes ; 24-Jun-96 BAR Change the IOMD ID code checking code, ; instead of checking for ARM7500 and skipping ; ARM7500 specifi code if not equal, not ; checks for original (RriscPC) IOM ID code ; and skip if equal, thus ARM7500 and ; ARM7500FE parts still do correct test. ; 08-Jul-96 BAR Ensure r0 is cleared before checking IOMD vsn no. ; ;------------------------------------------------------------------------ ; ; Test the data and address and byte strobe lines for uniqueness. ; LTORG ROUT 1 = "VRAM :",0 2 = "VRAM-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 3 = "DRAM ",&ff,":",0 4 = "Data :",0 5 = &88,&ff,&ff," MByte",0 ALIGN ts_LineTest [ MorrisSupport MOV r12, #IOMD_Base MOV r0,#0 ; Clear out r0 LDRB r1,[r12,#IOMD_ID1] ; load r1 with IOMD ID high byte ORR r0,r0,r1, LSL #8 ; Or r0 and r1 - shifted left 8, put in r0 LDRB r1,[r12,#IOMD_ID0] ; load r1 with IOMD ID low byte ORR r0,r0,r1 ; Or r0 and r1, put in r0 LDR r1,=ts_IOMD_ID1 ; get Ref IOMD ID code #1 (Original) CMPS r0,r1 ; check for IOMD ID Code #1 BEQ ts_LineTestIOMD ; Original IOMD, not 7500 or 7500FE, assume RiscPC hardware ; ; Here bceause its an ARM7500 or ARM7500 'FE' variant : Morris H/W ; MOV r11, #IOMD_DRAMWID_DRAM_32bit * &0F ;set all 4 banks to be 32bit initially LDR r1, =ts_IOMD_ID3 TEQ r0, r1 ; are we on FE part? ORREQ r11, r11, #IOMD_DRAMWID_EDO_Enable :OR: IOMD_DRAMWID_RASCAS_3 :OR: IOMD_DRAMWID_RASPre_4 ; if so, then enable EDO and slower RASCAS and RASPre times ; ts_LineTest for Morris ; MOV r14, #IOMD_Base STRB r11, [r14, #IOMD_DRAMWID] ; enable 32-bit addressing of data, also forces 26 bit mode, if ARM 6/7 (since P bit zero) MOV r0,#MMUC_D SetCop r0,CR_Control MOV r0,#0 MOV_fiq r9,r0 ; r9-fiq records low DRAM address for use elsewhere MOV r10, #0 ;indicate no RAM found yet MOV r9, #IOMD_DRAMWID_DRAM_16bit ;bit to OR into DRAMWID to set 16bit MOV r12, #DRAM0PhysRam ; ; r12 DRAM address ; r9 IOMD_DRAMWID_DRAM_16bit for current DRAM bank ; r11 current IOMD_DRAMWID register contents ; ;ExamineDRAMBank ;examine first/next DRAM bank 2005 ; MOV r8,r12,LSL #2 ; indicate bank under test AND r8,r8,#(3 :SHL: 28) ADR r4,%BT3 BL ts_SendText ; MOV r8,#0 ; r8 indicates RAM found in this bank LDMIA r12, {r1, r2} ;Preserve the two locations that we widdle on ADRL r3, funnypatterns ;We write different values to two locations LDMIA r3, {r3, r4} ; incase bus capacitance holds our value STMIA r12, {r3, r4} LDMIA r12, {r5, r6} ;Reread test locations EORS r5, r5, r3 ;Both locations should read correctly EOR r6, r6, r4 ; if memory is 32bits wide ;TEQ r5, #0 TEQEQ r6, #0 BEQ %FT2010 ;32bit wide memory TST r5, #&00FF ;If the bottom 16bits of each location TSTEQ r5, #&FF00 ; are correct, the memory is 16bits wide TSTEQ r6, #&00FF TSTEQ r6, #&FF00 BNE %FT2050 ;No memory in this bank ORR r11, r11, r9 ;Bank is 16bits wide 2010 STMIA r12, {r1, r2} ;Restore the two locations we widdled on ;Must do BEFORE poking the DRAMWID register MOV r14, #IOMD_Base ; STRB r11, [r14, #IOMD_DRAMWID] ; ; ; minimum ram test ; MOV r0, r12 ADD r1, r12, #A18 BL DistinctAddresses BNE %FT2050 ;Less than 512KBytes, so ignore this bank MOV_fiq r2,r9 ; if this is the first bank of DRAM or VRAM, TEQS r2,#0 ; put it's address in r9_fiq BNE %FT2012 MOV_fiq r9,r0 2012 MOV r6, #0 ;Fragment address MOV r7, #0 ;Fragment address MOV r8, #A19 ; now go through address lines A19-A25 2015 MOV r0, r12 ADD r1, r12, r8 ; see if this address line is unique BL DistinctAddresses BNE %FT2020 ; if we've failed then r8 is true size, so exit MOV r8, r8, LSL #1 ; else shift up to next TEQ r8, #A26 ; only test up to A25 BNE %BT2015 BEQ %FT2035 ;Bank fully occupied, DON'T test for higher fragments 2020 ; ; Found some DRAM, at address r0, size r8. ; There may be one or two higher address lines connected, so scan upto A25 looking for ; extra DRAM chunks. ; MOV r1, r8 2025 TEQ r1, #A25 BEQ %FT2035 ;No higher active address lines found ie one lump of DRAM ADD r1, r0, r1,LSL #1 BL DistinctAddresses SUB r1, r1, r0 ;Recover bit value BNE %BT2025 ; ; Got a 2nd fragment, at address r1 (also of size r8) ; MOV r6, r1 2030 TEQ r1, #A25 BEQ %FT2035 ;No higher active address lines found ie two lumps of DRAM ADD r1, r0, r1,LSL #1 BL DistinctAddresses SUB r1, r1, r0 ;Recover bit value BNE %BT2030 ; ; Got another active address line (ie total four fragments) ; MOV r7, r1 ; 2035 ; ; Found 1, 2 or 4 lumps of DRAM ; ;NoRamInBank 2050 MOV r13, r8 TEQ r6, #0 MOVNE r13, r13, LSL #1 TEQNE r7, #0 MOVNE r13, r13, LSL #1 ; remember size of this bank in bytes MOV r8,r13,LSL #(24 - 20) ; and display it in 2 digits, in MBytes. ADR r4,%BT5 BL ts_MoreText ADRL r4,%FT73 ; announce data line test BL ts_SendText MOV r1,r12 ; do walking bit test BL ts_Dataline BEQ %FT2055 ; looks OK, carry on to next bank ADRL r4,%FT74 ; bit test failed, so report it MOV r8,r0 BL ts_SendText ; and bit fault mask CMPS r13,#0 ; was any RAM thought to be here ? BEQ %FT2055 FAULT #R_LINFAILBIT ; if so, it's faulty. MOV r13,#0 ; so ignore it 2055 2055 ; ; If there was some RAM found here, and it passed the dataline test, ; do the address and bytestrobe tests on it too. ; CMPS r13,#0 BEQ %FT2060 ADRL r4,%FT75 ; announce start of address line test BL ts_SendText MOV r1,r12 ; test address lines in this block MOV r0,r13, LSR #2 ; bank may be in 4 fragments BL ts_Addrline BEQ %FT2056 ADRL r4,%FT76 ; failed - report error mask MOV r8,r0 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 2056 ADR r4,%FT77 ; announce start of byte test BL ts_SendText MOV r1,r12 BL ts_Byteword BEQ %FT2060 ADR r4,%FT78 ; failed - report error mask MOV r8,r0,LSL #16 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 2060 ; If the RAM found still seems OK, add it's size into the r10 accumulator ; Working or not, carry on to check the next bank. ADD r10,r10,r13 ; accumulate DRAM if any found ADD r12, r12, #DRAM1PhysRam-DRAM0PhysRam ; move onto next bank MOV r9, r9, LSL #1 ; shunt up position in DRAMWID CMP r9, #&0010 ; if more banks to do BLT %BT2005 ; then loop ADR r4,%FT70 BL ts_SendText ; None found .. print message MOVS r8,r10,LSL #(24 - 20) ; all finished .. ADREQL r4,%FT71 ; did we find any DRAM? ADRNEL r4,%FT72 BNE %FT2065 FAULT #R_LINFAILBIT ; fault if we didn't 2065 BL ts_MoreText B ts_endline ] ts_LineTestIOMD ADR r4,%BT1 BL ts_SendText ; Start data line tests on VRAM MOV r0,#0 MOV_fiq r9,r0 ; r9-fiq records VRAM or low DRAM address MOV r12, #IOMD_Base MOV r2, #IOMD_VREFCR_VRAM_256Kx64 :OR: IOMD_VREFCR_REF_16 ; assume 2 banks of VRAM by default STRB r2, [r12, #IOMD_VREFCR] ; Find the size, using MemSize's method MOV r0, #VideoPhysRam ; point at VRAM ADD r1, r0, #A2 ; test A2 BL DistinctAddresses MOVEQ r9, #2 ; we've got 2M of VRAM BEQ %FT21 MOV r2, #IOMD_VREFCR_VRAM_256Kx32 :OR: IOMD_VREFCR_REF_16 STRB r2, [r12, #IOMD_VREFCR] ADD r1, r0, #A2 ; check for any VRAM at all BL DistinctAddresses MOVEQ r9, #1 ; we've got 1M of VRAM MOVNE r9, #0 ; no VRAM 21 BNE %FT22 MOV_fiq r9,r0 ; record VRAM address FAULT #R_VRAM ; indicate VRAM present ; Report size .. if this is non-zero and the data line test fails, ; RISC OS will have problems. 22 ADR r4,%BT5 ; Add size (in hex Mbyte) MOV r8,r9, LSL #24 ; to "VRam : " message BL ts_MoreText ; Worked out what size VRAM is, and set up IOMD register. ; Do a data line test on the resulting array, repeated at oddword address to ; ensure both banks get tested with walking 0 and walking 1 ADR r4,%BT4 BL ts_SendText MOV r1, #VideoPhysRam BL ts_Dataline ADDEQ r1,r1,#4 BLEQ ts_Dataline BEQ %FT25 ; looks OK - carry on with VRAM test ; ; Data line test failed. Report the bitmap that failed, then carry on. ; ADR r4,%BT2 MOV r8,r0 ; report data fault mask BL ts_SendText B %FT30 ; ; If there was some VRAM found here, and it passed the dataline test, ; do the address and bytestrobe tests on it too. ; 25 ADRL r4,%FT75 ; announce start of address line test BL ts_SendText MOV r1,#VideoPhysRam MOV r0,r9,LSL #20 ; size in MB determined before dataline test BL ts_Addrline BEQ %FT26 ADRL r4,%FT76 ; failed - report error mask MOV r8,r0 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure B %FT30 26 ADRL r4,%FT77 ; announce start of byte test BL ts_SendText MOV r1,#VideoPhysRam BL ts_Byteword ADDEQ r1,r1,#4 ; retest at an oddword boundary BLEQ ts_Byteword BEQ %FT27 ADRL r4,%FT78 ; failed - report error mask MOV r8,r0,LSL #16 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure 27 ; Similarly, test each DRAM bank in turn, reporting failures or sizes for each 30 MOV r11, #IOMD_DRAMCR_DRAM_Large * &55 ; set all banks to be large initially MOV r14, #IOMD_Base STRB r11, [r14, #IOMD_DRAMCR] ; enable 32-bit addressing of data, also forces 26 bit mode, if ARM 6/7 (since P bit zero) MOV r0,#MMUC_D SetCop r0,CR_Control MOV r10, #0 ; indicate no RAM found yet MOV r9, #IOMD_DRAMCR_DRAM_Small ; bit to OR into DRAMCR MOV r12, #DRAM0PhysRam 35 MOV r8,r12,LSL #2 ; indicate bank under test AND r8,r8,#(3 :SHL: 28) ADRL r4,%BT3 BL ts_SendText MOV r8,#0 ; r8 indicates RAM found in this bank MOV r0, r12 ADD r1, r12, #A10 ; this should be OK for both configurations BL DistinctAddresses BNE %FT50 ; [no RAM in this bank at all] MOV_fiq r2,r9 ; if this is the first bank of DRAM or VRAM, TEQS r2,#0 ; put it's address in r9_fiq BNE %FT36 MOV_fiq r9,r0 36 ADD r1, r12, #A11 ; test for 256K DRAM BL DistinctAddresses ORRNE r11, r11, r9 ; it is, so select small multiplexing MOVNE r14, #IOMD_Base STRNEB r11, [r14, #IOMD_DRAMCR] ; store new value of DRAMCR, so we can use memory immediately MOVNE r8, #1024*1024 ; must be 1Mbyte at this address BNE %FT50 ; it's bigger than 256K words, so test address lines A21-A25 in sequence ; we assume that the size of each bank is a power of 2 MOV r8, #A21 ; now go through address lines A21-A25 40 ADD r1, r12, r8 ; see if this address line is unique BL DistinctAddresses BNE %FT50 ; if we've failed then r8 is true size, so exit MOV r8, r8, LSL #1 ; else shift up to next TEQ r8, #A26 ; only test up to A25 BNE %BT40 50 MOV r13,r8 ; remember size of this bank in bytes MOV r8,r13,LSL #(24 - 20) ; and display it in 2 digits, in MBytes. ADRL r4,%BT5 BL ts_MoreText ADRL r4,%FT73 ; announce data line test BL ts_SendText MOV r1,r12 ; do walking bit test BL ts_Dataline BEQ %FT55 ; looks OK, carry on to next bank ADRL r4,%FT74 ; bit test failed, so report it MOV r8,r0 BL ts_SendText ; and bit fault mask CMPS r13,#0 ; was any RAM thought to be here ? BEQ %FT55 FAULT #R_LINFAILBIT ; if so, it's faulty. MOV r13,#0 ; so ignore it 55 ; ; If there was some RAM found here, and it passed the dataline test, ; do the address and bytestrobe tests on it too. ; CMPS r13,#0 BEQ %FT60 ADR r4,%FT75 ; announce start of address line test BL ts_SendText MOV r1,r12 ; test address lines in this block MOV r0,r13 BL ts_Addrline BEQ %FT56 ADR r4,%FT76 ; failed - report error mask MOV r8,r0 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 56 ADR r4,%FT77 ; announce start of byte test BL ts_SendText MOV r1,r12 BL ts_Byteword BEQ %FT60 ADR r4,%FT78 ; failed - report error mask MOV r8,r0,LSL #16 BL ts_SendText FAULT #R_LINFAILBIT ; and record failure MOV r13,#0 ; then forget this memory block 60 ; If the RAM found still seems OK, add it's size into the r10 accumulator ; Working or not, carry on to check the next bank. ADD r10,r10,r13 ; accumulate DRAM if any found ADD r12, r12, #DRAM1PhysRam-DRAM0PhysRam ; move onto next bank MOV r9, r9, LSL #2 ; shunt up position in DRAMCR CMP r9, #&100 ; if more banks to do BCC %BT35 ; then loop ADR r4,%FT70 BL ts_SendText ; None found .. print message MOVS r8,r10,LSL #(24 - 20) ; all finished .. ADREQ r4,%FT71 ; did we find any DRAM? ADRNE r4,%FT72 BNE %FT65 FAULT #R_LINFAILBIT ; fault if we didn't 65 BL ts_MoreText B ts_endline 70 = "DRAM",0 71 = &88,"Failed",0 72 = &88,&ff,&ff," MByte",0 73 = "Data :",0 74 = "Data-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 75 = "Addrs :",0 76 = "Addrs-F",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 77 = "Byte :",0 78 = "Byte-F",&88,&ff,&ff,&ff,&ff,0 ; ; Data line test. ; ; In : r1 - start address for test ; ; Out : r0 - failing data pattern ; r1 - address of failure ; ; ; This exercises data lines in attempt to find shorts/opens. ; It goes something like : ; ; for (ptr = address, pattern = 1; pattern != 0; pattern <<= 1) ; *ptr++ = pattern; ; *ptr++ = ~pattern; ; for (ptr = address, pattern = 1; pattern != 0; pattern <<= 1) ; result |= pattern ^ *ptr++; ; result |= ~pattern ^ *ptr++; ; return result and address ; ts_Dataline ROUT ; ; Write all walking-zero, walking-one patterns ; 10 MOV r6,r1 ; set pointer for a write loop MOV r5,#1 ; set initial test pattern MVN r4,r5 ; and it's inverse 11 STMIA r6!,{r4-r5} ; write the patterns ADDS r5,r5,r5 ; shift the pattern (into Carry) MVN r4,r5 BCC %BT11 ; repeat until all bits done ; ; Read back and accumulate in r0 any incorrect bits ; MOV r6,r1 ; set pointer for a read loop MOV r5,#1 ; set initial test pattern MVN r4,r5 ; and it's inverse MOV r0,#0 ; accumulate result 21 LDMIA r6!,{r2-r3} ; read the patterns EOR r2,r2,r4 ORR r0,r0,r2 ; OR any failed bits into r0 EOR r3,r3,r5 ORR r0,r0,r2 ADDS r5,r5,r5 ; shift the pattern (into Carry) MVN r4,r5 BCC %BT21 ; repeat until all bits done ; ; After all checks at this address group, report back errors ; MOVS r0,r0 ; check for any result bits set MOV pc,r14 ; return r0 with error map (or 0) ; ; Address line test ; ; In : r0 - size of memory block ; r1 - start address of memory block ; ; Out : r0 - failing address bit mask ; ; This exercises address lines in an attempt to find any which don't ; work (i.e., don't select unique addresses). ; ; It works something like : ; ; MaxRam = PhysRam | (Memory size - 4); ; for (pattern = 4; pattern < memsize; pattern <<= 1 ) ; *(PhysRam ^ pattern) = pattern; ; *(MaxRam ^ pattern) = ~pattern; ; for (pattern = 4; pattern < memsize; pattern <<= 1 ) ; if (*PhysRam == *(PhysRam ^ pattern)) ; result |= pattern; ; if (*MaxRam == *(MaxRam + pattern)) ; result |= pattern; ; return result ; ts_Addrline ROUT MOVS r7,r0 ; Save memory size SUB r6,r0,#4 ; Calculate MaxRam ADD r6,r6,r1 ; (all-bits-set memory address) ; ; Mark (walking one, walking 0) addresses with unique patterns ; LDR r5,=&5A5AA5A5 ; initialize end markers STR r5,[r6] MVN r4,r5 MOV r3,r1 STR r4,[r3] MOV r5,#4 ; initialize pattern 02 MVN r4,r5 EOR r3,r5,r1 ; point to (start ^ pattern) STR r4,[r3] EOR r3,r5,r6 ; point to (end ^ pattern) STR r5,[r3] MOV r5,r5,LSL #1 ; shift test pattern up CMPS r5,r7 ; test bit still inside memory ? BCC %02 ; reached top bit - end this loop ; ; Check (walking one, walking 0) addresses for effectivity ; MOV r5,#4 ; initialize pattern MOV r3,r1 MOV r0,#0 04 MVN r4,r5 EOR r2,r5,r3 ; point to (start ^ pattern) LDR r2,[r2] LDR r1,[r3] CMPS r1,r2 ; do contents differ ? ORREQ r0,r0,r5 ; no - record ineffective bit EOR r2,r5,r6 ; point to (end ^ pattern) LDR r2,[r2] LDR r1,[r6] CMPS r1,r2 ; do contents differ ? ORREQ r0,r0,r5 ; no - record ineffective bit MOV r5,r5,LSL #1 ; shift test pattern up CMPS r5,r7 ; test bit still inside memory ? BCC %04 ; reached top bit - end this loop MOVS r0,r0 ; any result bits set - return error MOV pc,r14 ; ; Byte / word test ; ; In : r1 - memory start ; ; Out : r0 - Failure indication ; ; This test ensures that individual bytes may be written to each part of a word ; without affecting the other bytes in the word. ; ; for (byte = 0; byte < 4; byte ++) ; address[0] = word_signature ; address[1] = ~word_signature ; address + byte = byte_signature ; if (address[0] != ; (word_signature & (~ff << byte * 8)) ; | (byte_signature << byte * 8) ) ; result |= (1 << byte) ; if (result != 0 ; result |= address; /* fail at address, byte(s) */ ; return result; /* pass */ ; ts_Byteword ROUT LDR r3,=&AABBCCDD ; word signature MOV r0,#0 MOV r2,r0 ; ; byte test loop ( for bytes 0 to 4 ...) ; 02 MVN r4,r3 STMIA r1,{r3,r4} ; write word signature STRB r2,[r1,r2] ; write byte (0, 1, 2 or 3) MOV r4,r2,LSL #3 ; calculate expected result MOV r5,#&ff MVN r5,r5,LSL r4 AND r5,r5,r3 ; word signature, byte removed ORR r5,r5,r2,LSL r4 ; byte signature inserted LDR r4,[r1,#4] ; read (probable) inverse data to precharge bus LDR r4,[r1] ; read modified word CMPS r4,r5 MOV r5,#1 MOV r4,r2,LSL #2 ORRNE r0,r0,r5,LSL r4 ; fault : set bit in result mask ; ; Loop for next byte ; ADD r2,r2,#1 ; Bump byte counter CMPS r2,#4 ; ... until 4 byte strobes tested BLO %BT02 ; ; byte strobes all tested : check for errors ; CMPS r0,#0 MOV pc,r14 ; Result : return address and fault mask. ; ; End of RAM line tests ; ts_endline END