As I don't have a worklog thread for the NuCF, I suppose it's time to start one. I've finally revisited the NuCF and issue it has on the IIfx; recap is around a year ago I suspected something screwy is going on with the /AS strobe seen by the IO bus and PDS slot. It's generated in a PAL in the 20mhz clock domain used for those subsystems, rather than coming out of the 030. Unfortunately, I was not able to capture the *what* as even putting a scope or LA probe on /AS would suddenly cause it to start working. Hacky fixes like adding some resistance or capacitance would help, but that's ultimately a wretched hack and is just reducing the probability rather than removing the cause.
For that among other reasons the NuCF project went on the shelf for the past year.
I *finally* captured the smoking gun, though. While I still haven't captured /AS directly for lack of an active scope probe, I was instead able to find an indirect and damning symptom. I started from square 1 and started building the logic up from scratch again, and found even the well-tested writing to the flash wasn't working correctly. That's a pretty fundamental issue!
Below is a strobe to the DeclROM on the card. By process of elimination if I swapped it to be a product of /DS instead of /AS, my prior inability to write to flash would clear up. Easy enough to capture on the scope, and would you look at that glitch. It can be inferred that it's worse in actuality since there's propogation delays/hysteresis in the CPLD generating this strobe. My assumption is the actual root cause is likely ringing.
I suppose that's the peril of working with high speed CMOS logic (flash, CPLD, and CF cards) - where the geriatric IO devices on the logic board are too slow to react in time or be disrupted by it, the modern stuff I'm using is fast enough. Remains to be seen how I'll choose to address this, but there's options, at least the cause is *confirmed*, finally.

Some incidental tidbits about bare metal code on IIfx:
Disable ROM overlay, stolen directly from SuperMario source
How to put the SCC IOP into bypass mode for direct access. Also stolen directly from SuperMario. Looks like they tell the IOP to set a couple of its private registers then hang it.
For that among other reasons the NuCF project went on the shelf for the past year.
I *finally* captured the smoking gun, though. While I still haven't captured /AS directly for lack of an active scope probe, I was instead able to find an indirect and damning symptom. I started from square 1 and started building the logic up from scratch again, and found even the well-tested writing to the flash wasn't working correctly. That's a pretty fundamental issue!
Below is a strobe to the DeclROM on the card. By process of elimination if I swapped it to be a product of /DS instead of /AS, my prior inability to write to flash would clear up. Easy enough to capture on the scope, and would you look at that glitch. It can be inferred that it's worse in actuality since there's propogation delays/hysteresis in the CPLD generating this strobe. My assumption is the actual root cause is likely ringing.
I suppose that's the peril of working with high speed CMOS logic (flash, CPLD, and CF cards) - where the geriatric IO devices on the logic board are too slow to react in time or be disrupted by it, the modern stuff I'm using is fast enough. Remains to be seen how I'll choose to address this, but there's options, at least the cause is *confirmed*, finally.

Some incidental tidbits about bare metal code on IIfx:
Disable ROM overlay, stolen directly from SuperMario source
Code:
#define OSSRomCntl 0x204 //offset to ROM control register. Bits are:
#define OSSRomInit 0xD // initial value for ROM control register<3.5>
// overlay off, 2 ROM wait states
move.b #OSSRomInit,(OSSRomCntl+ADDR_OSS)
How to put the SCC IOP into bypass mode for direct access. Also stolen directly from SuperMario. Looks like they tell the IOP to set a couple of its private registers then hang it.
Code:
#define ADDR_SCC_IOP 0x50F04000
#define ADDR_SCC (ADDR_SCC_IOP+32) /* actual SCC address, in passthrough mode */
#define iopRamAddrH (0x0000-0x20) // high byte of shared RAM address register
#define iopRamAddrL (0x0002-0x20) // low byte of shared RAM address register
#define iopRamAddr (iopRamAddrL-1) // WORD access to shared RAM address register
#define iopRamData (0x0008-0x20) // shared RAM data register (byte, word, or long)
#define iopStatCtl (0x0004-0x20) // IOP Status and Control register
// bit numbers within the iopStatCtl register
#define iopInBypassMode 0 // IOP is in BYPASS mode
#define iopIncEnable 1 // enable addr pointer increment
#define iopRun 2 // 0 -> reset IOP, 1 -> run IOP
#define iopGenInterrupt 3 // interrupt the IOP
#define iopInt0Active 4 // interrupt 0 active
#define iopInt1Active 5 // interrupt 1 active
#define iopBypassIntReq 6 // peripheral chip interrupt request in bypass mode
#define iopSCCWrReq 7 // 0 -> SCC REQ active, 1 -> inactive
// commands bytes to write to the iopStatCtl register
#define resetIopRun ((0<<iopRun)+(1<<iopInt0Active)+(1<<iopInt1Active)+(1<<iopIncEnable))
#define setIopRun ((1<<iopRun)+(1<<iopInt0Active)+(1<<iopInt1Active)+(1<<iopIncEnable))
SetSCCIOPBypass:
movea.l #ADDR_SCC_IOP,%a3
move.b #resetIopRun,iopStatCtl(%a3) | init the Status/Ctl reg, hold IOP reset
| Download the IOP code
lea SCCIOPInitCode,%a0 | a0 <- start of IOP code (in this ROM)
move.w (%a0)+,%d0 | get the size code (-1 for DBRA)
move.w (%a0)+,iopRamAddr(%a3) | setup the code load address
LoadLoop:
move.b (%a0)+,iopRamData(%a3) | download a byte
dbra %d0,LoadLoop | load all of the bytes
| Start IOP execution
move.b #setIopRun,iopStatCtl(%a3) | release IOP reset (let it rip!)
lsr.w #6,%d0 | 0xFFFF -> 0x03FF -> loop 1024 times
wait:
dbra %d0,wait | delay a bit while IOP initializes
rts | return to caller
|----------------------------------------------------------------------------
| 6502 code to throw SCC IOP into bypass mode
SCCIOPInitCode:
dc.w (2f-1f)-1 | (byte) size of the code
dc.w 0x8000-(2f-1f) | (word) load address
1: | code starts here
dc.b 0xA9,0x81 | 7FEE: lda #1*DEBUG+0*SCCISM+1*BYPASS
dc.b 0x8D,0x30,0xF0 | 7FF0: sta SCCControlReg
dc.b 0xA9,0x44 | 7FF3: lda #SccIOCtlReg
dc.b 0x8D,0x31,0xF0 | 7FF5: sta IOControlReg
dc.b 0x80,0xFE | 7FF8: bra 0x7FF8
dc.b 0xEE,0x7F | 7FFA 7FEE Non-Maskable Interrupt vector
dc.b 0xEE,0x7F | 7FFA 7FEE Processor reset vector
dc.b 0xEE,0x7F | 7FFA 7FEE Interrupt Request vector
2: | code ends here

