Thank you, I like your version of savebyte. It is certainly more efficient and I can build a bigger program in RAM. Use zero page is a good idea for later. Right now I like to leave as many intermediate data intact in memory as possible so I can figured out what happened.
The reason I mentioned 256-byte for master boot record is because CF native mode is 16-bit, so its 512-byte sector is arranged as 256x16 after reset. I use the lower byte and discard the upper byte. 256 bytes are all I can get out of MBR at this stage of bootstrapping.
Your idea about treating the remaining data in the FIFO as a program is a good one. So instead of forming a small program in RAM then padded with bunch of illegal instructions until the jmp $800; I can jump to $800 immediately after the small program in RAM is created, then treat the remaining data in FIFO as a new program. On the other hand, 256 bytes are all I have to work with so the original idea was replacing the serial loader with a small CF loader that initializes the CF to another sector, say sector 1, and loads its contents (256 bytes) into memory and runs it. This CF loader is also a small-ish program that can be created with the initial 256-byte blind boot opcodes.
At this stage of development, flexibility is important so I like the multi-stage bootstrap and managed it with TeraTerm macro script. Eventually I do want everything to be self-contained in a CF disk then save the CF disk image as the distribution media for new computers.
Bill
CRC65, A frugal 6502 SBC
Re: CRC65, A frugal 6502 SBC
I've had good bit of fun writing software for CF bootstrapping. George's version of savebyte is very helpful because it allows decent size program to be created in zero page with 256 bytes of opcodes streaming from CF's master boot record. I tried several methods. George has suggested first creating a tiny program in RAM that reads the remaining data from CF's master boot record as the second level bootstrap program. That was quite convoluted, but worked quite well once I've figured out the multiple levels of bootstraps. Below is the program that worked reliably.
The first half (above the two lines of ****) is the tiny program created in RAM at $800-$80b. The tiny program executes and copies remaining data (2nd level bootstrap) in CF to $900 and then jumps into $900. The 2nd level bootstrap copies the monitor program previously stored in multiple sectors of CF disk to RAM and then jumps into the monitor. Whew!
Frankly that was too convoluted for me. I can barely keep it straight in my head right now, never mind a few months from now. So I decided to reduced one level of bootstrapping by putting the 2nd level bootstrap in the 1st level. This is possible because the 2nd level bootstrap is 46 bytes, so it can be created with 256 bytes of opcode stream with spare. This simpler bootstrap also worked well and hopefully I can still explain it a few months later.
The end result for both methods are the same; the hardware signed on with monitor prompt a fraction of second after power on.
That was fun. Now I'll go back to work on the hardware as either TTL implementation or GAL22V10 design.
The first half (above the two lines of ****) is the tiny program created in RAM at $800-$80b. The tiny program executes and copies remaining data (2nd level bootstrap) in CF to $900 and then jumps into $900. The 2nd level bootstrap copies the monitor program previously stored in multiple sectors of CF disk to RAM and then jumps into the monitor. Whew!
Code: Select all
.macro savebyte val,addr
LDA #val
STA addr
.endmacro
.ORG $b300
;This is the opcode stream for master boot record
; it will be executed as stream of opcode for 65c02
NOP ;reset vector plus extra padding
NOP
NOP
NOP
NOP
.byte 3 ;illegal instruction executed in 1 cycle
;for synchronization purpose
savebyte $ad,$800 ;xx: LDA $e000
savebyte $00,$801
savebyte $e0,$802
savebyte $9d,$803 ;STA $900,x
savebyte $00,$804
savebyte $09,$805
savebyte $e8,$806 ;INX
savebyte $d0,$807 ;BNE xx
savebyte $f7,$808
savebyte $4c,$809 ;JMP $900
savebyte $00,$80a
savebyte $09,$80b
LDX #0 ;initialize regX here to save program space
JMP $800
;program above is executed as it streams out of CF data port
; .org $800
;this is the first stage loader, loading 256 bytes of following data into 0x900
; then jump into 0x900
; xx:
; AD 00 80 LDA $e000 ;read from CF
; 9D 00 09 STA $900,x
; E8 INX
; D0 F7 BNE xx
; 4C 00 09 JMP $900
;xx:
; LDA $e000 ;read from CF
; STA $900,x
; INX
; BNE xx
; JMP $900
;*********************** program below is loaded into $900 by program above *************
;************************ then start the program at $900 *********************
;The hardware is now in normal mode where serial is $8000-$83FF, CF is $8400-$87FF
;zero page locations 0xc0 and 0xc1 are indirect index of address to be loaded
STZ $c0 ;put zero in $c0 (LSB)
LDA #$b4 ;put $b4 in $c1 (MSB)
STA $c1
LDX #2 ;CHS mode, read sectors $2-$d, start from sector 0x2
moresectx:
LDA #1 ;sector count of 1
STA CFsectcnt
STX CF07 ;X contains the sector to be read
LDA #$20 ;read CF command
STA CFstat
readdrqx:
LDA CFstat ;check data request bit set before read CF data
BMI readdrqx
AND #8
BEQ readdrqx
blk1stx:
LDA CFdata
STA ($c0) ;save, starting from 0xB400
INC $c0
BNE blk1stx
INC $c1 ;next 256 bytes
INX ;next CF sector
CPX #$d
BNE moresectx
JMP $b400 ;start location of CRCMon
.align 256,3
The end result for both methods are the same; the hardware signed on with monitor prompt a fraction of second after power on.
That was fun. Now I'll go back to work on the hardware as either TTL implementation or GAL22V10 design.
Code: Select all
.macro savebyte val,addr
LDA #val
STA addr
.endmacro
.ORG $b300
;This is the opcode stream save to master boot record
; it will be executed as stream of opcode for 65c02
NOP ;reset vector plus extra padding
NOP
NOP
NOP
NOP
.byte 3 ;illegal instruction executed in 1 cycle
;for synchronization purpose
;delayx:
savebyte $AD,$00 ;LDA CFstat
savebyte $07,$01
savebyte $84,$02
savebyte $E8,$03 ;INX
savebyte $D0,$04 ;BNE delayx
savebyte $FA,$05
savebyte $A2,$06 ;LDX #2
savebyte $02,$07
savebyte $8C,$08 ;moresectx: STY CFsectcnt
savebyte $02,$09
savebyte $84,$0A
savebyte $8E,$0B ;STX CF07
savebyte $03,$0C
savebyte $84,$0D
savebyte $A9,$0E ;LDA #$20
savebyte $20,$0F
savebyte $8D,$10 ;STA CFstat
savebyte $07,$11
savebyte $84,$12
savebyte $AD,$13 ;readdrqx: LDA CFstat
savebyte $07,$14
savebyte $84,$15
savebyte $30,$16 ;BMI readdrqx
savebyte $FB,$17
savebyte $29,$18 ;AND #8
savebyte $08,$19
savebyte $F0,$1A ;BEQ readdrqx
savebyte $F7,$1B
savebyte $AD,$1C ;blkx: LDA CFdata
savebyte $00,$1D
savebyte $84,$1E
savebyte $92,$1F ;STA ($c0)
savebyte $C0,$20
savebyte $E6,$21 ;INC $c0
savebyte $C0,$22
savebyte $D0,$23 ;BNE blkx
savebyte $F7,$24
savebyte $E6,$25 ;INC $c1
savebyte $C1,$26
savebyte $E8,$27 ;INX
savebyte $E0,$28 ;CPX #$e
savebyte $0E,$29
savebyte $D0,$2A ;BNE moresectx
savebyte $DC,$2B
savebyte $4C,$2C
savebyte $00,$2D
savebyte $B4,$2E
;to save program space, initialization of zero page as well as registers can be done
; as instruction streams out
STZ $c0 ;set up ZP as pointer from CF to memory
LDA #$b4 ;$b400 is starting of monitor
STA $c1
LDX #0
LDY #1 ;regY is always 1 to write to CF sector count reg
.align 253,03
JMP $0
;*********************** program below is created in zero page by program above *************
; CF is still in CHS mode. Sector 2 to sector $D correspond to monitor from $b400-$bfff
;
;000000r 1 .org $0
;000000 1 ; CF is still in CHS mode. Sector 2 to sector $D correspond to monitor from $b400-$bfff
;000000 1 delayx: ;value of $c0 is zero here
;000000 1 ;delay is needed for nDASP to negate and switch to normal mode
;000000 1 AD 07 84 LDA CFstat ;read clear the CF FIFO
;000003 1 E8 INX
;000004 1 D0 FA BNE delayx
;000006 1 A2 02 LDX #2 ;start from sector 2
;000008 1 ; ZP $c0,$c1 are already initialized, regY is 1
;000008 1 moresectx:
;000008 1 ; zero page locations 0xc0 and 0xc1 are indirect index of address to be loaded
;000008 1 8C 02 84 STY CFsectcnt ;sector count of 1
;00000B 1 8E 03 84 STX CF07
;00000E 1 A9 20 LDA #$20 ;read CF command
;000010 1 8D 07 84 STA CFstat
;000013 1 readdrqx:
;000013 1 AD 07 84 LDA CFstat ;check data request bit set before read CF data
;000016 1 30 FB BMI readdrqx ;spin on BSY set
;000018 1 29 08 AND #8 ;spin on DRQ
;00001A 1 F0 F7 BEQ readdrqx
;00001C 1 blkx:
;00001C 1 AD 00 84 LDA CFdata
;00001F 1 92 C0 STA ($c0) ;save, starting from 0xB400
;000021 1 E6 C0 INC $c0
;000023 1 D0 F7 BNE blkx
;000025 1 E6 C1 INC $c1 ;next 256 bytes
;000027 1 E8 INX ;next CF sector
;000028 1 E0 0E CPX #$e
;00002A 1 D0 DC BNE moresectx
;00002C 1 4C 00 B4 JMP $b400 ;start location of CRCMon
Re: CRC65, A frugal 6502 SBC
I ordered a batch of GAL22V10 from eBay, but they turned out to be fakes--they are writable but not verifiable. I returned it and ordered another batch from different vendor. In the meantime I have an unknown old batch of GAL20V8 that programed and verified OK, so I'll try it while learning about WinCUPL.
The CF bootstrap circuit should fit a GAL22v10, but needed two GAL20V8 to fit, at least with my current understanding of WinCUPL. I've split the design into state machine GAL20V8 with 5 registers representing various states of CF disk, and combinatorial GAL20V8 driving the CF signals. New design, new (old) device, new (old) design software, so I expect problems. I'll breadboard it and find a way to test it.
Since the CPLD-based CF bootstrap is working as described in previous posts, I'll build the GAL20V8 implementation in parallel and compare their outputs to CPLD. Here are pictures of the two GAL20V8 in parallel with CPLD-based design.
When I received GAL22V10, I'll also prototype it in parallel and compare its outputs with working hardware.
The CF bootstrap circuit should fit a GAL22v10, but needed two GAL20V8 to fit, at least with my current understanding of WinCUPL. I've split the design into state machine GAL20V8 with 5 registers representing various states of CF disk, and combinatorial GAL20V8 driving the CF signals. New design, new (old) device, new (old) design software, so I expect problems. I'll breadboard it and find a way to test it.
Since the CPLD-based CF bootstrap is working as described in previous posts, I'll build the GAL20V8 implementation in parallel and compare their outputs to CPLD. Here are pictures of the two GAL20V8 in parallel with CPLD-based design.
When I received GAL22V10, I'll also prototype it in parallel and compare its outputs with working hardware.