Stressing memory, or how to use JetPac (ROM version) to diagnose low memory.
Valoración de usuario: / 0
PeorMejor 
Martes, 27 de Mayo de 2008 13:18

This is a issue 3B Spectrum, with no socketed chip except the ULA and one suspicious socket at IC12 (bit 6 of low memory). Does initial boot-up, but it hangs before showing the copyright message.

This sympthon uses to be a failure in low memory. So I plugged my JetPac ROM cartridge and turned on the system. The JetPac ROM version LDIR's a presentation screen from some location at the ROM cartridge, right to the screen memory area. This screen helps me find if there's any low memory bit position that does not work. This is what I saw:

There is a series of vertical lines equally distributed. Ovbiously, this indicates a failure on a specific bit. My initial suspect was IC12, which is on a socket. I put a working 4116, but the same pattern repeated.

So, IC12 is good, and there's another one which is failing. To help in the diagnose, I wrote this little program, intented to be flashed as a 16K ROM. This program is written so it does not use any memory at all, thanks, among other things, to register banks.

The program fills the screen with a 8-bit pattern, in which only one bit is on, and the other seven are off. Which bit is on, I indicate by using different colors in the border. Everytime the 0 key is pressed (or the trigger on a joystick plugged in at port II is pressed), the pattern changes to show the next bit. Here's its source code:

; Register usage:
; A = pattern to fill the screen with. Changes from 00000001 to 00000010, to 00000100, ...
; BC = length of memory block to fill, minus 1.
; HL, DE, BC = sed by LDIR to fill a memory block with a valur
; BC (when not used in LDIR): port 0effeh to read half-row 6,7,8,9,0.
; HL (when not used in LDIR): busy-wait loop index.
; BC' = value FEh, to be used with out (c),e
; E' = border color. From 0 to 7, then 0 again.

Retardo         macro
                local BucRetardo
                ld hl,0
BucRetardo      dec hl
                inc h
                dec h
                jr nz,BucRetardo
                endm

                org 0
                di
                ;Black ink, white paper, no flash, no bright
                ld a,00111000b
                ld hl,22528
                ld de,22529
                ld bc,767
                ld (hl),a
                ldir

                ld a,1      ;A = pattern value to fill the screen with.
                exx
                ld bc,00feh ;C' = port FEh to write border color into.
                ld e,0      ;E' = number of color to show on border.
                exx

BucPrincipal    ld hl,16384
                ld de,16385
                ld bc,6143
                ld (hl),a
                ldir        ;Fill the screen with pattern

                exx
                out (c),e   ;Indicate what bit is on by changing border color.
                inc e       ;Prepare next color.
                exx

                ld bc,0effeh
EsperarASoltar  in e,(c)
                bit 0,e
                jr z,EsperarASoltar   ;Wait until 0 is not pressed.

                Retardo               ;Software debounce loop

EsperarAPulsar  in e,(c)
                bit 0,e
                jr nz,EsperarAPulsar ;Wait until 0 is pressed.

                Retardo              ;Software debounce loop

                rlca                 ;Rotate A, so pattern shows next bit.
                jr nc,BucPrincipal   ;If we have completed a turn over A register...
                exx
                ld e,0               ;... Reset E' to 0
                exx
                jr BucPrincipal

                org 16383
                db 0FFh              ;To ensure binary code to be 16385 bytes.

I booted the Spectrum with this little ROM and press 0 a couple of times. Then this was shown:

The pattern shows that there are two bits with logic high for each byte. Moreover, the two bits are located so the resulting pattern is regular (each vertical line is at the same distance from the next one).

If I have pressed the 0 key twice, that means that bit 2 should be the only one at high level. There's only one other bit in the same byte that makes a regular pattern with this one: bit 6. (If you think of a screen scan, bytes on it are arranged this way: 01000100 01000100 01000100... so you can see that there is always three 0's between each 1. That's the reason why you see a equally spaced series of vertical stripes).

So, at then end, something bad is happending with IC12. But I tried with two different chips and the bit 6 stripe was always there. I tested for open circuits at IC12 and found that the data bit from/to IC12, was not reaching the corresponding pin at ULA. I guess whoever solded that socket, did some damage to the tracks in the PCB. A bit of wire-wrapping and IC12 was "present" again.

Trying to boot from the Sinclair ROM didn't work. The machine did almost the same than did from the first time: tries to boot, border white, paper black, and hangs. I tried with the 16K-only memory test modified ROM which worked for me with Inacete's machine, and the copyright message came to the screen.

Clearly, something is wrong with the upper 32K memory. Some tests with BASIC POKE's and PEEK's didn't give me any clue . I tried the Sinclair test cartridge, and surprisingly, the test concluded that I had 48K "in working order".

Back to the modified Sinclair ROM. I wrote a BASIC program to POKE a series of values into some upper RAM addresses, but that addresses seemed to work well.

Then I tried another approach: with CLEAR statement, you can locate the machine stack pointer wherever you like (within certain limits). More precisely, doing a CLEAR changes the value stored at ERR_SP. First, I had to make the Spectrum believe it had 48K of RAM memory. The initial memory test sets P_RAMT to 32767. I poked it to contain 65535. After this, I could perform a CLEAR with a value greater than 32767.

I tried with 32768, 32769, and 32770. No one of this values led to a crash. But when I did CLEAR 32771, the machine hung.

CLEAR 32771 puts ERR_SP at 32768. Lower values set ERR_SP pointing to the 16K low memory area. So, there is in fact, something wrong with the upper memory block, and that failure affects, at least, the first address: 32768.

Back to BASIC: no results. POKing and PEEKing any value, sends me the same value on return. I thought that I was not "stressing" memory too much. After all, a POKE, follow with a PEEK, takes cents of seconds to execute. As the BASIC program itself rest on low memory, the only times CPU is accessing high memory is to do my POKE's and PEEK's.

On the other hand, the memory area which the machine stack is located in, gets very busy, because its contents have to be written and read at a very high speed, because of the number of PUSH, POP's, CALL's, RET's, etc. that are happening all over the ROM program. I thought that if I write and read back values to high memory at the speed of machine code, the failure could be more evident.

So, I re-wrote my POKE/PEEK test to use machine code. The little program do a loop from address 32768 to 65535. For each address, it pokes every value from 0 to 255, and after each poke, it peeks the same location to look for mismatches. If there is a mismatch, the routine sets BC with the offending address and returns. If after trying all addresses, there's no failure, it returns 0 in BC and exists to BASIC.

The source code is this:

                org 30000
                di
                ld hl,32768    ;From address 32768
buc2            ld b,0         ;Cycle each address to hold valeus from 255 to 0.
buc1            ld (hl),b      ;POKE value
                ld a,(hl)      ;and PEEK back
                cp b           ;equal?
                jr nz,fallo    ;if different, goto "fallo" (failure)
                djnz buc1      ;next value to poke.
                inc hl         ;next address to try
                ld a,h
                cp 0
                jr nz,buc2    ;until we reach address 65535
                ld bc,0       ;0 means everythink OK
                ei
                ret
fallo           push hl       ;put offeding address into BC
                pop bc        ;to be our USR return value.
                ei
                ret

This program runs in the low memory area. I did a run and nothing (returned 0). So, I left the Spectrum all night executing this routine continously. After each USR 30000, I check the returned value against 0. If so, gave it another run. If not 0, I printed the result and exit.

After 23 passes, the routine stopped with the value: 56823. I poked a 0, and PEEK returned 16. I tried other locations with 0, and PEEK returned me always 16. The hidden offending bit was found: bit 4, at IC19.

It seemed that this routine had been stressed the 32K memory area so hard, that the failure became permanent, instead of happening only sometimes. Needless to say that after this, the machine managed to boot from the original Sinclair ROM, reporting 16K. The Sinclair test cartridge returned "16K inworking order", as expected. Changing IC19 with a working replacement did the rest.

 

Add your comment

Your name:
Your email:
Título:
Comment:
  The word for verification. Lowercase letters only with no spaces.
Word verification:
ZX Projects, Powered by Joomla! and designed by SiteGround web hosting