ZIF socket giving me headaches.
ZIF socket giving me headaches.
I fired up my SBC again and starting writing more code.
When I built my SBC, I made a mistake and put a DIP socket in the ROM. Later, I decided to put a ZIF socket in but I didn't want to pull out the DIP socket. I should have used the ZIF socket initially.
Not that it would have mattered too much...seems the ZIF socket is a piece of crap. I'm going to test it tonight but I think some of the pins are not making a connection.
Unfortunately, I don't have another ZIF socket. Good ones are surprisingly expensive.
So, I was wondering if there is another way. A way to quickly get new code over to my AT28C256.
Another foobar on my part is that I didn't create an easy way to program the EEPROM in circuit.
Now I'm wondering what my options are.
What would be cool would be a way to add an upload to my make/build process.
Worse case, I might make a small board that has wires going to my programmer and my SBC. I could just turn off the SBC when programming. Not sure what running the SBC will do to my programmer, however.
Something else I've considered is to use an Arduino or something similar in the loop. Either as direct ROM (albeit, slow) or as a programmer.
I have one of those fancy ESP32's as well. That thing is wireless and might be fast enough for general purpose ROM. And it has 32 GPIO, IIRC. Just need voltage translation.
What are you guys doing to quickly get code into your SBC?
PS
My long-term goal is to write a minimal monitor that will pull new code over serial. But, I need a faster way of getting that minimal monitor installed.
Thanks!
When I built my SBC, I made a mistake and put a DIP socket in the ROM. Later, I decided to put a ZIF socket in but I didn't want to pull out the DIP socket. I should have used the ZIF socket initially.
Not that it would have mattered too much...seems the ZIF socket is a piece of crap. I'm going to test it tonight but I think some of the pins are not making a connection.
Unfortunately, I don't have another ZIF socket. Good ones are surprisingly expensive.
So, I was wondering if there is another way. A way to quickly get new code over to my AT28C256.
Another foobar on my part is that I didn't create an easy way to program the EEPROM in circuit.
Now I'm wondering what my options are.
What would be cool would be a way to add an upload to my make/build process.
Worse case, I might make a small board that has wires going to my programmer and my SBC. I could just turn off the SBC when programming. Not sure what running the SBC will do to my programmer, however.
Something else I've considered is to use an Arduino or something similar in the loop. Either as direct ROM (albeit, slow) or as a programmer.
I have one of those fancy ESP32's as well. That thing is wireless and might be fast enough for general purpose ROM. And it has 32 GPIO, IIRC. Just need voltage translation.
What are you guys doing to quickly get code into your SBC?
PS
My long-term goal is to write a minimal monitor that will pull new code over serial. But, I need a faster way of getting that minimal monitor installed.
Thanks!
Cat; the other white meat.
Re: ZIF socket giving me headaches.
Do you have /WE wired up to your EEPROM? The AT28C256 is programmable over the standard CPU bus if so, and doesn't require a high programming voltage to be applied externally. You'll need to load the programming routine and the new contents of the EEPROM (in 64-byte pages) into RAM, over a serial line or something, since the chip will be unavailable for reading during the programming cycle, even if you don't overwrite certain parts of it. You may also need to disable interrupts so that the CPU doesn't try to read the vector table, if that is in the EEPROM.
Assuming you haven't enabled Software Data Protection on the chip, the writing algorithm is as follows:
Assuming you haven't enabled Software Data Protection on the chip, the writing algorithm is as follows:
Code: Select all
Load/copy flashing code into RAM.
Load first page (64 bytes) of new data into RAM.
Disable interrupts.
Repeat:
Write new data into EEPROM.
Load next page (64 bytes) of data, if any, into RAM
Read and compare last byte of current page, repeat until it matches (this signifies that the page-write cycle is complete).
When last page written, re-enable interrupts and return control.
- floobydust
- Posts: 1394
- Joined: 05 Mar 2013
Re: ZIF socket giving me headaches.
As noted, writing to the AT28C256 insitu is very easy. You can do byte write or page write mode. Note that you need to sample the toggle bit which is actively toggling when the chip is writing the contents internally. You do need the write line connected to the write signal generated from the system (treat it the same as RAM). My SBC uses a jumper to either connect the WR to +5V or the Write signal.
Based on the above, you need to have interrupts disabled, You also need to have the code doing the write and sensing the toggle bit running from RAM. Here's a short routine that accomplishes a Byte write to the EEPROM (which is copied from EEPROM and RAM and called as a JSR):
My current Monitor supports programming the EEPROM insitu and can write any length from RAM to ROM, but of course you need to be careful where you are writing to. Current Monitor also supports a single byte EEPROM edit for patching. Both Monitor routines use the code snippet above which is copied into Page Zero first. Once the source and target locations are set, just JSR to the routine and it does the rest.
My Monitor also supports Xmodem-CRC for upload and download, which is what I use to get code down to the board. The code also handles S19 records automagically, so I can easily write code on the PC, download it to the SBC and then write it to the EEPROM. Note: This assumes you're NOT trying to overwrite the actual Monitor itself! I recently wrote a simple Flash utility which does replace the Monitor code, albeit it does rely on the BIOS not being touched. However, if the Monitor code is replaced with bad code, the SBC will likely crash after the BIOS init completes and shows it's boot message.
Based on the above, you need to have interrupts disabled, You also need to have the code doing the write and sensing the toggle bit running from RAM. Here's a short routine that accomplishes a Byte write to the EEPROM (which is copied from EEPROM and RAM and called as a JSR):
Code: Select all
BYTE_WRS SEI ;Disable interrupts
LDA (SRCL) ;Get source byte
STA (TGTL) ;Write to target byte
LDA (TGTL) ;Read target byte (EEPROM)
AND #%01000000 ;Mask off bit 6 - toggle bit
BYTE_WLP STA TEMP3 ;Store in Temp location
LDA (TGTL) ;Read target byte again (EEPROM)
AND #%01000000 ;Mask off bit 6 - toggle bit
CMP TEMP3 ;Compare to last read (toggles if write mode)
BNE BYTE_WLP ;Branch back if not done
CLI ;Re-enable interrupts
BYTE_WRE RTS ;Return to callerMy Monitor also supports Xmodem-CRC for upload and download, which is what I use to get code down to the board. The code also handles S19 records automagically, so I can easily write code on the PC, download it to the SBC and then write it to the EEPROM. Note: This assumes you're NOT trying to overwrite the actual Monitor itself! I recently wrote a simple Flash utility which does replace the Monitor code, albeit it does rely on the BIOS not being touched. However, if the Monitor code is replaced with bad code, the SBC will likely crash after the BIOS init completes and shows it's boot message.
Regards, KM
https://github.com/floobydust
https://github.com/floobydust
Re: ZIF socket giving me headaches.
The "toggle bit" output is only one method of detecting write completion; the chip inverts the most-significant bit of the last-written byte, relative to its true value, until the write is complete. So it is sufficient (and uses less code) to compare the written location to the value written until they match:
Or, for a simpler way of detecting the toggle-bit without relying on knowing the last value written:
Code: Select all
BYTE_WRS SEI ;Disable interrupts
LDA (SRCL) ;Get source byte
STA (TGTL) ;Write to target byte
BYTE_WLP CMP (TGTL) ;Read target byte (EEPROM)
BNE BYTE_WLP ;Branch back if write not done
CLI ;Re-enable interrupts
BYTE_WRE RTS ;Return to caller
Code: Select all
BYTE_WRS SEI ;Disable interrupts
LDA (SRCL) ;Get source byte
STA (TGTL) ;Write to target byte
BYTE_WLP LDA (TGTL) ;Read target byte (EEPROM)
CMP (TGTL) ;Re-read target byte (EEPROM)
BNE BYTE_WLP ;Branch back if write not done
CLI ;Re-enable interrupts
BYTE_WRE RTS ;Return to caller
Last edited by Chromatix on Fri Feb 08, 2019 8:22 pm, edited 1 time in total.
Re: ZIF socket giving me headaches.
As far as a minimal monitor goes, how about something like this? http://pygmy.utoh.org/3ins4th.html Very quick to implement a version of for a 6502 or similar, and from there you can do a whole lot as long as you have some RAM.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: ZIF socket giving me headaches.
cbmeeks wrote:
Not that it would have mattered too much...seems the ZIF socket is a piece of crap. I'm going to test it tonight but I think some of the pins are not making a connection.
Unfortunately, I don't have another ZIF socket. Good ones are surprisingly expensive.
[ . . . ]
What are you guys doing to quickly get code into your SBC?
Unfortunately, I don't have another ZIF socket. Good ones are surprisingly expensive.
[ . . . ]
What are you guys doing to quickly get code into your SBC?
When I developed the software in around 1990 for the automated test equipment at work which used a 65c02 SBC on STD bus, the SBC did not have room for ZIF sockets. After I had the initial Forth kernel working, I could develop the rest in RAM, totally interactively, and every so often I would round up all my latest additions and run them through the metacompiler and re-program the EPROMs. Those EPROMs were in and out of the regular sockets many times, but definitely not every day as I continued developing.
Similarly, if you have a way to get your assembled or compiled code into RAM to test and debug, or better yet, assemble or compile it on the SBC itself, your EEPROM won't have to come out and make a trip to the programmer very often. You will probably need at least some kind of working monitor program in the EEPROM though.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: ZIF socket giving me headaches.
I think there's scope here for a 256-byte wonder which can be loaded over the serial port into RAM, followed by the data to be flashed and periodic CRCs, and which takes over the serial port for the duration. There would need to be a (very simple) corresponding program on the other end of the serial line, of course.
If, as in the algorithm I first showed, the serial transfer of the following block is overlapped with the EEPROM write cycle of the current block, a 57600 baud serial line will nearly keep pace with the EEPROM. A "raw" CRC algorithm (without tables) can be very compact and still fast enough to work at serial speeds. Conversely, if the speed of the serial line is as little as 9600 baud, the FIFO in many UARTs will be large enough to absorb the page write cycle without losing throughput (and this is still faster than a stock 1541).
If, as in the algorithm I first showed, the serial transfer of the following block is overlapped with the EEPROM write cycle of the current block, a 57600 baud serial line will nearly keep pace with the EEPROM. A "raw" CRC algorithm (without tables) can be very compact and still fast enough to work at serial speeds. Conversely, if the speed of the serial line is as little as 9600 baud, the FIFO in many UARTs will be large enough to absorb the page write cycle without losing throughput (and this is still faster than a stock 1541).
Re: ZIF socket giving me headaches.
nyef wrote:
As far as a minimal monitor goes, how about something like this? http://pygmy.utoh.org/3ins4th.html Very quick to implement a version of for a 6502 or similar, and from there you can do a whole lot as long as you have some RAM.
You could do something like this:
Code: Select all
HEX
0200 XHERE !
CROSS-CODE SUB1
0 # LDA
CLC
0A # ADC
RTS
END-CROSS-CODE
CROSS-CODE SUB2
SUB1 JSR
END-CROSS-CODE
Essentially, take a stock 65xx assembler, replace HERE with XHERE, C! with XC!, etc. and assemble code. Use the 0200 (in this case) as the origin to the routine (since it sets XHERE). You can have XHERE maintained automatically by the assembler. For example, XHERE is set to 0200 at the start, and updated properly by the CROSS-CODE assembler. Also, SUB1 is set to 0200, and SUB2 would be set to 0206, etc.
Reloading the code assembles it live on the slave. By the time the assembly is done, not only is it assembled, it's already on the board.
You can also make "XALLOT", "XC,", "X,". Mind, you don't need to have a Forth on the slave, you're just using Forth concepts and commands to populate the image. No need to have the inner interpreter, move over words headers, etc. Just Franks simple driver. It's just an interesting, simple, fast cross assembler/loader with an interactive Forth command line.
There's nothing stopping you from setting XHERE manually before each routine.
Code: Select all
HEX
0200 XHERE !
CROSS-CODE SUB1
0 # LDA
CLC
0A ADC
RTS
END-CROSS-CODE
0210 XHERE !
CROSS-CODE SUB2
SUB1 JSR
END-CROSS-CODE
Code: Select all
0 VARIABLE ORGVAL
: ORG DUP ORGVAL ! XHERE ! ;
: +ORG ORGVAL @ + ORG ;
Code: Select all
HEX
0200 ORG
CROSS-CODE SUB1
0 # LDA
CLC
0A ADC
RTS
END-CROSS-CODE
10 +ORG
CROSS-CODE SUB2
SUB1 JSR
END-CROSS-CODE
But even better, if you change the "10 +ORG" to "20 +ORG", then everything else shifts as well.
The point of the individual origins is that it lets you redefine single routines, allowing you to patch tweak them and patch them in place because you have a buffer between routines, so you don't have to reassemble the entire set every single time. Just update one routine, and reload it. Hmm, how does it know to use the same origin the second time? Yea, I don't know either -- guess it needs work, but I'm sure Something Could Be Done.
I know, you could have CROSS-CODE look up and see if SUB2 is already in the dictionary. If it is, just use its existing value and ignore ORG. If you want to reassemble everything, FORGET the start (SUB1 in this case), and reload.
Wow - that was simple. That's down right clever.
So, now you're developing in assembly, ON THE BOARD, in almost real time with effectively zero turn around time.
Pretty neat!
Re: ZIF socket giving me headaches.
nyef wrote:
As far as a minimal monitor goes, how about something like this? http://pygmy.utoh.org/3ins4th.html Very quick to implement a version of for a 6502 or similar, and from there you can do a whole lot as long as you have some RAM.
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: ZIF socket giving me headaches.
Or a classic minicomputer with its toggle-switch front panel…
Re: ZIF socket giving me headaches.
Chromatix wrote:
Or a classic minicomputer with its toggle-switch front panel…
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: ZIF socket giving me headaches.
Something like LDY #xx, STY/JMP $xxxx, BRA *-5. Wire your toggle switches to replace the x's, and another one to switch between STY ($8C) and JMP ($4C).
Re: ZIF socket giving me headaches.
Even better: This allows you to use another switch or button, wired to /IRQ, to actually execute the code. Enter the routine with interrupts masked (which they are on reset or NMI); then WAI continues on IRQ, instead of going through the vector. At this point we are at 8 bytes.
A further refinement: This gives you the ability to examine memory as well as poke and execute, for the cost of three extra bytes of code, adding $AC to the opcode switch (alongside $8C and $4C), and a bunch of LEDs for a readout.
Code: Select all
WAI
LDY #$xx
STY $xxxx ; switchable to JMP
BRA *-6
A further refinement:
Code: Select all
WAI
LDY #$xx
STY $xxxx ; switchable to JMP or LDY
STY LEDs
BRA *-9
Re: ZIF socket giving me headaches.
If the goal is to build a minimal bootstrap ROM right at the top of the address space, then we must incorporate the three vectors - and we can do this within 16 bytes, so we only need a $FFFx mask and a 4-to-16 decoder to drive out diode ROM. NMI is the first vector encountered in program order, so we can include it in a JMP to replace the BRA, and the WAI then falls exactly at $FFF0: That's exactly 16 bytes. Then, looking at the actual bytes involved: There's a lot of bit patterns that can probably find diodes reused through OR gates from the decoder. For example:
Code: Select all
.ORG $FFF0
WAI
LDY #$xx ; data toggle switches on $FFF2
STY/JMP/LDY $xxxx ; three-way opcode selection between $8C/$4C/$AC on $FFF3, address toggle switches on $FFF4-5
STY LEDs
JMP $FFF0 ; incorporates NMI vector
.WORD $FFF0 ; reset vector
.WORD $???? ; IRQ vector
Code: Select all
$CB
$A0
xx ; data toggles
$8C/4C/AC
xx ; address low toggles
xx ; address high toggles
$AC
xx ; LED low address
xx ; LED high address
$4C
$F0
$FF
$F0
$FF
xx ; IRQ low address
xx ; IRQ high address
Re: ZIF socket giving me headaches.
We had some previous discussions on small bootstraps and minimal hardware to boot an SBC:
and not quite so minimal