EEVblog Electronics Community Forum
Products => Computers => Programming => Topic started by: metertech58761 on March 20, 2023, 07:57:24 am
-
I thought I'd take a break from tearing my hair out while trying to untangle this bit of code and ask a dumb question -
What happens if you tell the CPU to access a given address and no RAM exists at that location - not even a 'shadow copy' from partial address decoding?
The code I'm looking at was apparently used in two different models - one with the main board set alone and the other with an ADC daughterboard.
This rare (and likely now extinct) ADC daughterboard had a second EPROM, along with an additional 128 bytes of RAM (either an MC6810 or 2x HM-6561).
-
If the bus controller doesn't know this and throw an error it will just try to read air, I think.
-
What happens if you tell the CPU to access a given address and no RAM exists at that location - not even a 'shadow copy' from partial address decoding?
my 68hc11 EVB board has 512-byte of internal ram, 32Kbyte of ram, 16Kbyte of ROM, 2Kbyte of expandable addresses mapped to physical devices { LCD-2x16, Eth0 }
CPU <----> 74HC138: decode(addr)->/CS <----> device=devices(/CS)
So it has (64Kb - (512 + 32K + 16K + 2K)) addresses mapped to no device.
If I try to issue a read request to those addresses, I always get 0xff.
- -
While on my atlas mips board I always get a error bus exception.
CPU <----> bus controller: decode(addr)->/CS, wait for /ack|bus err <----> device=devices(/CS)
When the CPU issues an address on the bus, the device on the other side of the bus has to acknowledge itself within a time limit, counted in terms of bus-cycles, 10 clock edges at 33Mhz, in my case.
-
So in other words, given that the data bus has a pull-up on it, it should just come back as FF... makes sense.
Like I said, it was a dumb question I should have known the answer to... :)
-
Depends on how well 'tied' to logic 1 the bus is. You might get #FF 99.9999% of the time, but random bus noise/ringing might make the outcome less than a boolean certainty.
-
Yes, more or less three possibilities:
Real mode, open bus: reads last data asserted (the previous value is stored on bus capacitance -- it's like having one byte of DRAM made in a PCB). On many CPUs, the last data fetched will simply be the instruction currently executing.
Real mode, pulled bus: 0xff or 0x0 (or maybe something mixed, but that would be weird?). If the pulls are weak, it could be a mix of the above, depending on timing and maybe noise.
Protected mode: likely the address isn't mapped and a protection flag is thrown. The kernel could just as well map it of course, in which case the above applies.
Open bus is relevant to a number of systems; in fact it appears in a number of classic console games, when abusing glitches to cause out-of-bounds reads. There is such a glitch in Super Mario World, for example (SNES, 65C816 CPU).
Tim
-
I thought I'd take a break from tearing my hair out while trying to untangle this bit of code and ask a dumb question -
What happens if you tell the CPU to access a given address and no RAM exists at that location - not even a 'shadow copy' from partial address decoding?
The code I'm looking at was apparently used in two different models - one with the main board set alone and the other with an ADC daughterboard.
This rare (and likely now extinct) ADC daughterboard had a second EPROM, along with an additional 128 bytes of RAM (either an MC6810 or 2x HM-6561).
You would expect the S/W to look for a particular pattern in the EPROM to determine the presence of that daughterboard.
If the daughterboard only contains RAM the S/W would normally attempt to write and verify several different patterns throughout the expected RAM address range to determine if the RAM is present.
Detecting whether it is a shadow copy or not is a little more difficult. You need to write a specific pattern in one of the locations, write a different pattern in the potential shadow location and then go back and see if the original pattern has changed or not.
-
srb1954: One of the first things the code does in the reset code is to look for a particular value at $E000 and jump to $E001 if a particular value was seen.
After that first jump, I'm not sure how it shifted between the daughterboard code and the main code. It likely relied on the IRQ and SWI vectors to do so.
The memory map is just plain weird due to partial address decoding:
PTM: $0000, external input latch: $0008, PIA: $000C, SRAM: $0080, NVRAM: $0C00, daughterboard RAM: $0C80, daughterboard ROM: $E000, and main ROM: $F000
-
srb1954: One of the first things the code does in the reset code is to look for a particular value at $E000 and jump to $E001 if a particular value was seen.
After that first jump, I'm not sure how it shifted between the daughterboard code and the main code. It likely relied on the IRQ and SWI vectors to do so.
It could be that the functionality of the unit is so significantly changed when the daughterboard is added and the programmers chose the simpler route to have a different main loop. This would be a lot easier than having repeated tests and branches in the standard main loop to change program functionality on the fly.
As well as using IRQ and SWI to access the main code the jump-to-subroutine (JSR) can access the whole 64k address space and so could be used to access subroutines in the main ROM.
The memory map is just plain weird due to partial address decoding:
PTM: $0000, external input latch: $0008, PIA: $000C, SRAM: $0080, NVRAM: $0C00, daughterboard RAM: $0C80, daughterboard ROM: $E000, and main ROM: $F000
Actually, this is a fairly standard memory map for a 6800 system. There is a code size and speed advantage using the direct addressing mode to access the bottom 256 bytes of memory. Putting the scratch RAM and frequently accessed peripherals in this address space is common practice.
In the 6800 architecture the power-on reset vectors reside at $FFFE and $FFFF so the EPROM must be present at the top of the memory space to start the processor up. Additional EPROMs are commonly built downwards from this point leaving the maximum space building up from address $0000 for RAM and peripherals.
-
I meant weird as to how the memory was allocated. :)
I agree that it works best to have as much memory as possible in the lower addresses to make use of zero-page (direct) mode.
So, I can see using SWI as the hook to jump from the daughterboard EPROM back to the main EPROM.
Thing is, though, there's only the one path from the main to the daughterboard EPROM, which is in the initialization sequence. However...!
One of the IRQ-related routines actually ends in an infinite loop ($F685: BRA $F685).
Also, given that the main code otherwise manipulates a pin on the PIA to feed the input to the watchdog circuit, do you suppose that infinite loop is just a way to force the watchdog to time out and 'kick' the MPU back to the reset vector and return to the daughterboard EPROM that way?
-
Just a footnote: This whole thread was based on an incorrect assumption on the design of the load terminal unit I was reverse engineering. :palm:
The load terminal uses the full $0C00-$0CFF page while the test terminal logic board uses some decoding to split the range into $0C00-$0C7F (RAM) and $0CF0-$0CFF (74x138).
My mistake was assuming that the distribution terminal had the upper RAM relocated to the daughterboard like in the test terminal.
I have to the conclusion / realization it apparently does NOT, therefore, its upper RAM would be the same range as the load terminal; ergo, $0C00-$0CFF.
The distribution terminal's daughterboard should consist solely of the ADC and support circuitry, which is driven from the PIA.
Too bad there are likely no remaining examples of the distribution terminal (I have been told few were ever made, and all were bespoke regarding installed options).