;> MEM2C ; ; RISC OS 2+ BOOT TEST SOFTWARE ; MEMORY TEST 2 VERSION A. ; BRIAN RICE 30-10-89 ; 06-Apr-90 ArtG 0.1 Test variable memory size ; ; This file will perform a simple test on all DRAM. ; The test code for this test was taken from thhe A680 Quick memory ; test software. The software was copied straight but the number of times ; the test looped arround was cut down to two loops, because of time ; constraints when testing the memory. Test_wks_msize * &40 ; Space for test block size Test_wks_return1 * &44 ; Space for return addresses Test_wks_return2 * &48 Test_code_off * &4C ; Where testing starts test_size * 13 * 4 ; Size of test group test_mem_rsvd * Test_code_off+test_mem_template_end-test_mem_template ; ; Quick test the RAM (pre boot style) ; ts_RamTest ROUT MOV r13,r0 STR r14,[r13,#Test_wks_return1] STR r1,[r13,#Test_wks_msize] LDR r0, test_quick_pattern BL test_mem_code ORRS r0,r0,r0 BNE test_mem_quit ; LDR r0, test_quick_pattern MVN r0, r0 ; inverse pattern BL test_mem_code ORRS r0,r0,r0 test_mem_quit ADR r12,%22 BEQ %10 ; If fault detected, exit with zero flag clear, r0 pointing to failing ; location, r1 containing faulty data and r2 pointing a suitable error ; message indicating whether all-0 or all-1 data was expected. LDR r2,[r14] ; fetch failing instructiom ANDS r2,r2,#1 ; calculate expected data ADREQ r12,%20 ; and load suitable message ADRNE r12,%21 MOVS r0,r0 ; with zero flag set for PASS. 10 LDR pc,[r13,#Test_wks_return1] ; Fail messages indicate incorrect data read after WRote 0 or Wrote 1 ; to all bits at that location. 20 = "WR-0 RD",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 21 = "WR-1 RD",&88,&ff,&ff,&ff,&ff,&ff,&ff,&ff,&ff,0 22 = "??",0 ALIGN test_quick_pattern & &0f76 ; Large Memory test. Generates the write + test routines in memory ; then calls them. The routine tests patterns as defined by the bottom ; 13 bits of r0. ; ; N.B. The test start address must be calculated to ensure that ; the loops finish exactly with r0 equal to End_memory ; ; The routine returns with eq true if the memory is OK. test_mem_code ROUT STR r14, [r13, #Test_wks_return2] ; ; Copy the ram test code into low ram, modifying MOV instructions ; to MVN in accordance with the test pattern. ; ADR r1, test_mem_template ADD r2, r13, #Test_code_off LDMIA r1!, {r3-r4} ; copy initial 2 instrucions STMIA r2!, {r3-r4} MOV r4, #1 0 MOVS r0, r0, ROR #1 LDR r3, [r1], #4 ORRCS r3, r3, #&00400000 ; Convert MOV => MVN STR r3, [r2], #4 ADD r4, r4, #1 CMP r4, #13 BLE %B0 ; ; Copy the load loop control and verify start instructions ; LDMIA r1!, {r5-r9} STMIA r2!, {r5-r9} ; ; Copy and modify the CMP instructions ; MOV r0, r0, ROR #32-13 MOV r4, #1 1 MOVS r0, r0, ROR #1 LDR r3, [r1], #4 ORRCS r3, r3, #&00200000 ; Convert CMP => cmn ORRCS r3, r3, #&00000001 ; Convert #0 => #1 STR r3, [r2], #4 ADD r4, r4, #1 CMP r4, #13 BLE %B1 ; ; Copy the verify loop control and finishing-up instructions ; LDMIA r1!, {r5-r12} STMIA r2!, {r5-r12} LDMIA r1!, {r5-r12} STMIA r2!, {r5-r12} LDMIA r1!, {r5-r12} STMIA r2!, {r5-r12} ; check we've copied enough ASSERT ((test_mem_stadd - test_mem_chk) = (24 * 4)) ; ; Calculate the test start and end addresses ; LDR r0, [r13, #Test_wks_msize] ; size of test area ADD r14, r13, r0 ; end of test area SUB r1, r0, #test_mem_rsvd ; testable size MOV r2, #test_size ; adjust r1 to (r1 / 13*4) * (13*4) DivRem r3, r1, r2, r4 MUL r1, r3, r2 SUB r0, r14, r1 ; rounded test start address ; Do it. MOV r1, #Test_code_off ADD r1, r1, r13 ; pointer to copied code MOV pc, r1 ; ; The following code is copied (and modified) into RAM for execution ; test_mem_template ROUT STR r0, test_mem_stadd ; save initial RAM address STR r13, test_mem_base ; save test area base address MOV r1, #0 ; Converted to MVN if bit = 1 MOV r2, #0 ; Converted to MVN if bit = 1 MOV r3, #0 ; Converted to MVN if bit = 1 MOV r4, #0 ; Converted to MVN if bit = 1 MOV r5, #0 ; Converted to MVN if bit = 1 MOV r6, #0 ; Converted to MVN if bit = 1 MOV r7, #0 ; Converted to MVN if bit = 1 MOV r8, #0 ; Converted to MVN if bit = 1 MOV r9, #0 ; Converted to MVN if bit = 1 MOV r10, #0 ; Converted to MVN if bit = 1 MOV r11, #0 ; Converted to MVN if bit = 1 MOV r12, #0 ; Converted to MVN if bit = 1 MOV r13, #0 ; Converted to MVN if bit = 1 0 STMIA r0!, {r1-r13} CMP r0, r14 BLO %B0 LDR r0, test_mem_stadd 1 LDMIA r0!, {r1-r13} 2 CMP r1, #0 ; Converted to cmn if bit = 1 CMPEQ r2, #0 ; Converted to cmneq if bit = 1 CMPEQ r3, #0 ; Converted to cmneq if bit = 1 CMPEQ r4, #0 ; Converted to cmneq if bit = 1 CMPEQ r5, #0 ; Converted to cmneq if bit = 1 CMPEQ r6, #0 ; Converted to cmneq if bit = 1 CMPEQ r7, #0 ; Converted to cmneq if bit = 1 CMPEQ r8, #0 ; Converted to cmneq if bit = 1 CMPEQ r9, #0 ; Converted to cmneq if bit = 1 CMPEQ r10, #0 ; Converted to cmneq if bit = 1 CMPEQ r11, #0 ; Converted to cmneq if bit = 1 CMPEQ r12, #0 ; Converted to cmneq if bit = 1 CMPEQ r13, #0 ; Converted to cmneq if bit = 1 test_mem_chk BNE %F5 ; go report fault data CMP r0, r14 BLO %B1 ; else loop for next batch MOVS r0, #0 ; All OK : return with NULL r0 4 LDR r13,test_mem_base LDR pc, [r13, #Test_wks_return2] ; Failed : repeat the last batch of tests one at a time, to determine ; the first failing address and data. ; Note that the test instructions are copied to %8 to permit individual ; execution, and %7 is overwritten with an instruction used to copy ; the failing data into r1. Change this code very carefully ! 5 LDR r14,%2 ; Obtain first test in the set STR r14,%8 ; and re-execute it SUB r0,r0,#(13*4) ; adjust pointer to bad data ADR r14,%2 ; point to first test. 7 B %8 ; make sure %8 is refetched 8 & 0 ; redo the test here : BNE %4 ; if it failed, exit with ; r0 = ptr to memory ; r1 = wrongly read data ; r14 => failing instruction LDR r1,[r14,#4]! ;fetch next instruction AND r1,r1,#&f0000 ;make an instruction MOV r1,r1,LSR #16 ;to copy the next register ORR r1,r1,#&E1000000 ;down to r1 ORR r1,r1,#&00A00000 ;e.g. CMPEQ r10,#0 ORR r1,r1,#&00001000 STR r1,%7 ;and put it at %7 LDR r1,[r14] ;then copy the next test STR r1,%8 ;to %8 ADD r0,r0,#4 ;bump the fault pointer B %7 ;and execute %7 and %8. test_mem_stadd ; address of first test location & 0 test_mem_base & 0 ; address of test block test_mem_template_end ; ; Copy the L2 page table from r1 to r0, then remap the translation table's ; base address in the MMU to point to an L1 page table within it. ; ROUT ts_remap_ttab [ StrongARM_POST ;make sure ARM810 cache or StrongARM data cache is cleaned/flushed, because we are going to remap ARM_read_ID r3 AND r3,r3,#&F000 CMP r3,#&8000 BNE %FT22 ;ARM810 ;;; ARM8_cleanflush_IDC r3 ;not implemented yet B %FT24 22 CMP r3,#&A000 BNE %FT24 ;StrongARM ;tricky...we'll read 16k of data in current ROM space, to act as clean and flush of current data MOV r3,pc BIC r3,r3,#31 ;32 byte aligned ARMA_clean_DC r3,r4,r5 24 ] ;StrongARM_POST MOV r2,#FixedAreasL2Size ADD r0,r0,r2 ; point to locations in PhysSpace ADD r0,r0,#PhysSpace ADD r1,r1,r2 ADD r1,r1,#PhysSpace 10 ASSERT ((FixedAreasL2Size :AND: ((8*4)-1)) = 0) LDMDB r1!,{r3-r10} ; copy the page & section tables STMDB r0!,{r3-r10} SUBS r2,r2,#(8*4) BNE %BT10 SUB r9,r1,r0 ; r9 = offset from original to copy ADD r0, r0, #DRAMOffset_L1PT-DRAMOffset_L2PT ; r0 -> copy of L1Phys SUB r10, r0, #PhysSpace ; keep real address of L1PT for MMU ADD r2,r0,#((1 :SHL: (32-20))*4) ; size of L1PT - 1 word per meg of memory 11 LDR r3,[r0],#4 ; check each L1 table entry ANDS r4,r3,#3 CMPS r4,#L1_Page ; if it's page mapped .. SUBEQ r3,r3,r9 ; adjust the page table base address STREQ r3,[r0,#-4] CMPS r0,r2 ; repeat for all the level 1 table BNE %BT11 SetCop r10, CR_TTabBase ; set up MMU pointer to L1 [ StrongARM_POST ;flush cache if ARM 6/7 (ARM 8,StrongARM already sorted, above) ;flush TLB(s) ARM_read_ID r4 AND r4,r4,#&F000 CMP r4,#&8000 ;ARM 8? CMPNE r4,#&A000 ;or StrongARM? MCRNE ARM_config_cp,0,R0,ARM67_cacheflush_reg,C0,0 ;flush 6/7 cache MCRNE ARM_config_cp,0,R0,ARM67_TLBflush_reg,C0,0 ;flush 6/7 TLB MCREQ ARM_config_cp,0,R0,ARM8A_TLB_reg,C7,0 ;flush 8/StrongARM TLB(s) | SetCop r0, CR_IDCFlush ; flush cache + TLB just in case SetCop r0, CR_TLBFlush ; (data written is irrelevant) ] MOV pc,r14 END