• Please review our updated Terms and Rules here

Interesting DRAM Defects in Dynamic PET

Hugo Holden

Veteran Member
Joined
Dec 23, 2015
Messages
4,780
Location
Australia
I thought I should report some interesting findings in my PET which involve defective DRAM. Because, it is somewhat unusual.

In my quest to check DRAM, I wrote an assembly language program to write to the DRAM from page 04 up to page 7F.

Nothing fancy as the program is still in evolution and I am only just learning to code 6502 assembly language.

So initially I got it working (it required self modifying code to avoid using page 0)

The program I wrote resides in page 03 where the cassette buffers are.

In any case, so far it does something really simple. All it does at the moment is fill the user memory with byte 00 from addresses $0400 to $7FF0. Once it does that it returns to BASIC. ( I can do this in BASIC of course, but it takes ages to do it, but only a second or two with the assembly language program).

Once I had filled the memory with byte 00, then I have been inspecting it with BASIC, to PEEK the locations.

I found that my DRAM had four defective locations in the upper part of page 06 that did not retain the 0 written there.

But, the plot seriously thickens:

One of the four defective locations at address decimal value 1667 is behaving very strangely. Not only does it not "remember' the 0 that was written to it, it has another strange peculiarity. When "Peek'd" it will return a different value depending on how it is done. For example, if the bytes around it are Peek'd with a FOR-NEXT loop the location 1667 returns a value of 96 (when it should have been zero). But, if the location is individually Peek'd it returns a value of 244. Yet the other three defective locations in this region at least return the same value, regardless if they are Peek'd as a one off , or Peek'd by a loop.

This might go to show some of the unusual time or pattern sensitive faults, that can crop up in this 4116 DRAM, making the notion of an accurate DRAM memory check program much more difficult than it looks on face value.

I have attached two screen images showing these issues.
 

Attachments

  • DRAM1.jpg
    DRAM1.jpg
    110.1 KB · Views: 16
  • DRam2.jpg
    DRam2.jpg
    155.3 KB · Views: 16
PS:....ignore the typos that says 244, the value the memory location 1667 sometimes returns is 224, as can be seen from the screen photo, corrected image attached.
 

Attachments

  • DRam2.jpg
    DRam2.jpg
    155.3 KB · Views: 11
Last edited:
FWIW, are you disabling interrupts with your memory test? I mean, it's probably unlikely it'd have anything to do with the particular memory addresses you're reporting issues with (I don't know why necessarily it would be touching addresses in "Page 6"), but there is a vertical refresh interrupt in the PET involved with screen updates that could potentially be keeping track of "something".
 
As a “thought experiment” what happens if we do assume that there is some sort of memory issue with the low bank of 16K DRAM?

This means the fault is just as likely to affect pages 0 and 1 in some way, shape or form.

As you are running BASIC, and BASIC uses page 0 quite extensively, and we know that 16-bit pointers are formed in page 0, is it possible that a small memory fault materialising in page 0 could manifest itself as a fault elsewhere if the pointer(s) go screwy?

Can I suggest extending your 6502 programming skills to code up the full test in assembler to see whether the fault can be traced to real memory or the interaction between the memory and BASIC.

I would write a program that lived in the lower 16K RAM to test out the upper 16K RAM and vice-versa.

Also, don’t forget that a memory error could also affect your test program...

Dave
 
For what it is worth, even running that code in an emulator causes various values to appear in 0x683 and 0x682. Looks like it might be something to do with BASIC, maybe the "x" variable or stack. I don't think that's your memory problem...
 
Honestly I'd say that any test that involves using BASIC to "peek" things is suspect unless you've extensively sussed out how BASIC uses memory and are absolutely sure you're not poking around in scratch space used by in-memory BASIC code representation, garbage collection, variable space, or interrupt activity. To quote the bard ("Aliens"): "Nuke it from orbit: it's the only way to be sure." And by "it" I mean everything else that might otherwise run at the same time as your testing loop. Turn off interrupts, blow away the stack and zero page, and write your own display code that will poke the verdicts into screen memory. And then reboot to exit the program.
 
Yes, of course, it is obvious now...

BASIC 'knows' where the end of the source program is, and uses memory from there upwards as variable storage etc. It may also use the space for other things.

Likewise, it could use the memory space from 'top of memory' downwards as (for example) a stack. The 6502 hardware stack is limited to 256 bytes (page 1). That limitation can be overcome by BASIC creating its own stack using a 16-bit pointer (stored in page 0) and treating main memory as a stack by synthesising the PUSH and PULL instructions as subroutines.

The only way you can get your memory test to work is going to be purely in assembler, unless you do quite a bit of research into the subroutines you use to make sure they have no unintended side effects.

Dave
 
Yes, of course, it is obvious now...

BASIC 'knows' where the end of the source program is, and uses memory from there upwards as variable storage etc. It may also use the space for other things.

Likewise, it could use the memory space from 'top of memory' downwards as (for example) a stack. The 6502 hardware stack is limited to 256 bytes (page 1). That limitation can be overcome by BASIC creating its own stack using a 16-bit pointer (stored in page 0) and treating main memory as a stack by synthesising the PUSH and PULL instructions as subroutines.

The only way you can get your memory test to work is going to be purely in assembler, unless you do quite a bit of research into the subroutines you use to make sure they have no unintended side effects.

Dave
I did find that BASIC appeared tp use the top 15 bytes of page 7F, the "170" values there were overwritten with other values, so my program avoids that (but now I am wondering if that might be due to some interaction in the DRAM that should not be there, because I saw a memory check program that tested memory right up to $7FFF, so presumably they had no problem there, but I have a problem there).

I also found if I only fill memory from $0500 to $7FF0 the problem at the top of page $06 remains.

It seems odd that BASIC would do anything to that area in page $06 deliberately or it would corrupt many user programs. After all address $06 is in the user area and they expect to put programs in memory there without them getting corrupted. It could be that activity from BASIC in the pages $00 and $01 is interfering with page $06 due to some sort of cross coupling effect inside the DRAM. This could explain how it is returning different values depending on how BASIC peek's it.

The FOR-NEXT loop was in immediate mode, not a line numbered program, I had read that this was not supposed to use the user memory. But I had discovered that it does sometimes, at least with this DRAM, affect memory just above page $04 in the program area, where the occasional byte gets altered after using immediate mode, I made another post about that, but that could in fact be due to underling defects in this group of particular DRAM IC's and interactions that should not be there between low and high addresses.

But, I also have a tool I made which replaces DRAM below $0400 with SRAM, by disabling the DRAM over that address range and switching in the SRAM, so I can try that and see if that makes any difference, but it might not because it only disables the DRAM reads, not writes. to have it disable the writes too, it requires cutting a track and adding a resistor, I didn't want to do that.

The other thing I will do is finish the assembly program so it checks the bytes itself, and I don't have to use BASIC peeks to check the values.

Also I will drop in a fresh array of DRAM IC's and see what happens. And test the removed DRAM IC's in the 4116 DRAM tester I bought on ebay and see if that can detect a problem in any.

I will report what happens.
 
Last edited:
It seems odd that BASIC would do anything to that area in page $06 deliberately or it would corrupt many user programs.

Have you actually observed "corruption" in software you've run on this machine, or are you just noticing the value of these memory locations is changing as you run PEEK commands from the BASIC prompt?

The FOR-NEXT loop was in immediate mode, not a line numbered program, I had read that this was not supposed to use the user memory.

That doesn't add up to me. If you're assigning variables even in immediate mode BASIC is going to assign memory to handle them and *where* it does so is controlled by some pointers that point to potentially random (to you) locations in "unused" memory. Why *shouldn't* BASIC use some particular location around half a K above the end of the "system" space for housekeeping when you have no BASIC program resident?

Unfortunately Commodore BASIC doesn't have the VARPTR command so it's not exactly straightforward to figure out where a variable resides in memory (there are some USR routines out there to do it), but there is a simple test you can try: enter a BASIC program, doesn't have to be a big one but it'd be most definitive if it was at least big enough to occupy up to these locations in page 06 (I assume you're counting from zero so this will mean a BASIC program of about .7K) and then fish around to see if these locations that change value when you run immediate mode commands move up accordingly. (Or, likewise, see if the BASIC program is actually getting corrupted.)
 
Have you actually observed "corruption" in software you've run on this machine, or are you just noticing the value of these memory locations is changing as you run PEEK commands from the BASIC prompt?


That doesn't add up to me. If you're assigning variables even in immediate mode BASIC is going to assign memory to handle them and *where* it does so is controlled by some pointers that point to potentially random (to you) locations in "unused" memory. Why *shouldn't* BASIC use some particular location around half a K above the end of the "system" space for housekeeping when you have no BASIC program resident?
I have had some very odd things happen running programs. I have been running an Editor and an Assembler and a loader in BASIC to make my assembly language programs. The loader program, occasionally for no obvious reason crashes and I have to reset the computer. I'm suspicious that it extends into the defective area in page $06, but I do not know for sure if that is the cause.

The remark about the user memory not being used in immediate mode was in Adam Osborne's book about the PET. I will copy and post it.

It made me wonder where the BASIC immediate mode statements would/could be stored, the only other place I could see they could exist in the system then, if not anywhere in the DRAM from $0400 upward, then more likely, they are held somewhere below page $04 in the DRAM. But if that is true I don't know where that is. Some data is definitely in the video RAM area and there is spare RAM there.

It is interesting in that I found this remark about the immediate mode operations not affecting user memory ($0400 to $7FFF in the 32k PET) to be "almost true" at least for this particular DRAM I'm testing in that if I write a simple immediate For-Next mode program to write bytes into $0400 and above to $7FFF, it works, so if BASIC was using that area for the process, as it does for a line numbered and executed programs, the immediate mode program would destroy itself and it doesn't.

......here is the post I made about the issue a while ago on June 10th. For this I poked the value and peek'd it immediately after in immediate mode loop, and just the one byte returned the wrong value, but it was also affected by how it was peek'd. It seems looking back that this is a similar issue to the way that one of the 4 defective bytes in high page $06 is behaving:


Maybe as you have suggested the immediate mode is using the top 15 bytes at $7FFF for the "housekeeping". I will do an experiment and see if executing immediate mode programs alters those bytes. If that is true then the remark about immediate mode programs not using user memory must have been incorrect. But, the fact I could use an immediate mode program to write up to $7FFF, makes it look unlikely, or the program would have wiped itself out.
 
Last edited:
I would write a program that lived in the lower 16K RAM to test out the upper 16K RAM and vice-versa.

Dave
This is a very good idea. I could assemble two versions of the final program, one to reside in high memory, the other in low.
 
I have attached the remarks about usage of memory in BASIC's immediate mode, from the book.

There are no DRAM defects in the computer, it just looked like there might be. I have confirmed this with new & tested DRAM too.

It took a while to figure out what was going on, because of the effect the LOADER program was having on memory somehow. The loader was altering the bytes in the top of page 7F (it was not BASIC doing it), and causing another effect where the group of abnormal looking bytes were shifted up to high page 06, when without the loader having been used, these same bytes appear at low page 04.

Instead I dropped using the loader for a while, I entered my program manually in the M/L monitor. My program is good and fills the entire memory with a selected byte (00 for the experiment) from $0400 to $7FFF, And everything is normal and all the bytes are good and 00 examined by the M/L monitor.

However, interesting things happen using BASIC to examine the memory contents;

If a line numbered program is used to peek & print the bytes, where the program resides immediately above $0400, the bytes are changed as expected, and all locations above the program are 00.

In immediate mode, with single peek statements, all the bytes are normal and 00 and there is no change to the memory values from $0400 upwards, all returning the correct value 00 and the single peek statement not altering any bytes to any other value.

However, if an immediate mode FOR-NEXT loop is made to examine and print the bytes from $0400 upwards, always on low page 04 a sequence of 5 bytes gets altered away from the 00 that was there previously, though the second byte in the sequence generally is not and remains at 00. Typically a byte sequence like 58,00,8C,00,10 or similar, with slightly different values depending on the range of memory looked at, appears on examination with the M/L monitor (or in decimal form as the Print-peek loop prints them to the screen).

One interesting thing is the exact place this byte array starts varies a little depending on the range of the FOR -NEXT loop too as well as the exact byte values that appear. For example sometimes they might start at address $0436, other times in places nearby like $0443. 8C might be 8B or the second to last byte an 07.

These bytes always appear in a similar area of low page 04 when the immediate mode FOR-NEXT loop is used. But if the Loader program had been used first, oddly they appear in high page 06.

In any case this is definite evidence that an immediate mode FOR-NEXT loop program , will alter the memory bytes, even if it is just a few of them. So the statement in the book that the immediate mode program is not "stored" in computer memory could be correct, but it can still alter memory.
 

Attachments

  • OB1.jpg
    OB1.jpg
    800.7 KB · Views: 4
Let's try a thought experiment...

You enter an immediate FOR/NEXT loop on the screen...

Does BASIC 'execute' the line of text from the screen?

My understanding is that the line would be tokenised/crunched to be executed (i.e. the text FOR, TO, NEXT, PEEK etc. would be parsed and tokenised before execution).

If the line of text remains on the screen in its original form, this can't be done on the screen - so would require the line of text entered to be stored somewhere. That somewhere has to be in main memory.

Equally, a variable (X) is created with an initial value. Internally, other state information will also be created to support the execution of the FOR/NEXT loop. This will also require memory.

I think that memory IS being used internally by executing an immediate mode program - you just don't necessarily know what BASIC is up to!

Even though the line of BASIC text is not 'stored' (it doesn't have a line number), this doesn't necessarily mean it isn't stored by BASIC somewhere transiently in memory.

Out of interest, if you change the variable 'X' to something else (e.g. 'HUGO'), does this affect your observed memory 'corruption'?

I used to know all this. Unfortunately, those brain cells have died off in the intervening years :)!

Dave
 
Any variables you create in immediate mode (including ones used in for-next loops) stick around after the fact. For instance, run this:

for x=1 to 200: print x; : next x

and then separately:

print x

The output of that second command is “201”.

It’s awkward on Commodore BASIC to find out exactly where this “x” variable lives in RAM because there’s no VARPTR command like in TRS-80 or GW-BASIC, but if you peek around while setting random variables you do see the contents of RAM which would be right after the “start” of the BASIC programs space changing, and if, for laughs, you add a line number and some BASIC code you’ll see the whole party move up accordingly.

As to why touching page 7F might do “weird things”, the general rule with Microsoft-descended BASICs is they store numeric variables immediately after the program code, while arrays and strings are built down from the top of memory. Again, to compare with TRS-80 BASIC, this is why those machines prompt you with “memory size?” on boot; to give one user-friendly opportunity to reserve memory for machine language code to live in. (Otherwise you have to reserve memory like in Commodore BASIC, which is poke over some pointer values... or play games to disguise M/L routines as BASIC code, which is a really common Commodore strategy. The PET in particular doesn’t include an auto-relocating loader for BASIC programs, so the way it works by loading BASIC program data as essentially a linked list starting at a fixed base, makes that easily possible. I don’t know what this ‘LOADER” program mentioned is, but if it’s something masquerading as a BASIC program for purposes of kicking off an M/L payload then it’s very likely it “invisibly“ messes with the locations of where BASIC would generate variables in immediate mode.)
 
I am doing better with the 6502 assembly language now.

My program so far can write the byte 00 to all locations from $0400 to $7FFF. Then after it has done that it overwrites locations $0400 $0402 $0404 etc or every second byte, right up to $7FFE. The theory behind it being that writing into alternate byte locations should not only give the correct value back, but it should not alter the value of any of the other previously programmed bytes (It is quite different than just writing alternate FF's and 00's to memory, even though the pattern in memory is the same afterwards). The next move is to reverse the order of the bytes as a double check.

The M/L monitor actually works at a good speed to examine the bytes as they scroll by and it makes it very easy to stop and see the address of any defective ones.

I'm currently running some interesting pink ceramic 4116's that I bought from Bosnia and Herzegovina. And they are all working perfectly. Fairly exotic looking IC's as far as they go. The price was $14 USD for 16 pieces, very reasonable at less than $1 each.

I also learned an interesting feature of self modifying code, which is obvious I think for those who have used it before, but this is the first time I have done it, so I got caught out.

The code itself should be regarded as damaged and must be repaired before leaving the program, in this case the byte I modify throughout the program must be set back to its un-altered state before exiting the program. Otherwise, if not done, the second time the program is used it malfunctions. Also my program saves and restores the X & Y resisters and pushes & pulls the A and program status register around the program, so it returns to BASIC without upsetting any apple carts.

Currently the program is running in the cassette buffer area in high page 03. But, probably I will want to put this program into ROM elsewhere. What would be the easiest way to get the program byte array to a modern computer from the PET ? Will the M/L monitor S (save function) save an array of my program bytes from memory to the SD2PET in a format where they can be used in a modern computer, say opened in Notepad or similar, bringing the SD card across to the modern computer ?

(In my SOL-20 I simply sent the data across the serial link and I'm not sure the better way to do it with the PET)
 

Attachments

  • MEMprint.jpg
    MEMprint.jpg
    249.1 KB · Views: 6
  • dram3.jpg
    dram3.jpg
    224.3 KB · Views: 6
Last edited:
Also my program saves and restores the X & Y resisters and pushes & pulls the A and program status register around the program, so it returns to BASIC without upsetting any apple carts.


I presume you are calling your machine code with SYS or USR? BASIC should do all of that housekeeping for you.
 
I presume you are calling your machine code with SYS or USR? BASIC should do all of that housekeeping for you.
I wasn't sure for certain that SYS would do that 100%, as it is the first time I have used it for my own code, so I doubled up on the process just in case, but it is probably unnecessary.
 
Will the M/L monitor S (save function) save an array of my program bytes from memory to the SD2PET in a format where they can be used in a modern computer, say opened in Notepad or similar, bringing the SD card across to the modern computer ?
The M/L Monitor will save the file as a binary .prg program. Use a program like HxD (hexadecimal editor) to look at the file on the PC. You will see that the first two hex digits are the starting load location (I think in low byte, high byte) and then the machine code itself.

When in the M/L monitor and saving to your SD2PET, use the following format with no spaces between between the commas:
.S "test file",08,03D0,03FF
where 08 is the IEEE unit number, 03D0 is the starting address, and 03FF is the ending address +1.
When you get the "." prompt again, the SAVE is complete. Use .X to return to BASIC.

If ever saving to a real dual IEEE drive, make sure you use the drive number with the file name, i.e, "0:test file" or your block allocation map on your floppy may be corrupted.
 
Last edited:
The M/L Monitor will save the file as a binary .prg program. Use a program like HxD (hexadecimal editor) to look at the file on the PC. You will see that the first two hex digits are the starting load location (I think in low byte, high byte) and then the machine code itself.

When in the M/L monitor and saving to your SD2PET, use the following format with no spaces between between the commas:
.S "test file",08,03D0,03FF
where 08 is the IEEE unit number, 03D0 is the starting address, and 03FF is the ending address +1.
When you get the "." prompt again, the SAVE is complete. Use .X to return to BASIC.

If ever saving to a real dual IEEE drive, make sure you use the drive number with the file name, i.e, "0:test file" or your block allocation map on your floppy may be corrupted.
Thanks !
 
Of course the statement I made about putting my memory check program into ROM was very silly.

There are three things I have learnt so far about self modifying code:

1) Try to avoid it, if at all possible.
2) If you do it, make sure to repair the code before you exit your program or re-entry into the program will foul it up.
3) Self modifying code can only live (reside) in RAM, not ROM or it cannot self modify.

So if I put my code into a ROM, in this case, I will have to write a block move program to shift it into RAM, below address $0400 in the cassette data areas in the PET.

I learnt to write block move programs in 8080 assembly when I was playing around with my SOL-20, so I think I can do it for the 6502, or at least give it a go.

Everything "code" is difficult for me , but I am ok with hardware.
 
Back
Top