Closed hubertushirsch closed 3 years ago
Hey Ralf,
Yes, I know exactly what part of the code you are talking about.
This has been done on purpose, to mitigate the issue with PCB 1.6 and below, where the CE of the SRAM is permanently plugged to the ground. To minimise the chance of both the shift register and the SRAM outputting data on the data bus, I keep the emulator in "emulation" mode after boot and only enable the shift registers just before I'm ready to write the data to SRAM (and WE changes the SRAM to data line to inputs).
If you are using v1.8 and above (or you modified v1.6 as per the errata) you can change the code and keep the target reset when you power comes up.
Thanks Kris
On Sat, 5 Dec 2020 at 13:19, HubertH notifications@github.com wrote:
Hi Kris,
in setup() you starting the emulator with EN_RST = LOW, with means, the target is not in reset.
pinMode( EN_RST, OUTPUT ); digitalWrite( EN_RST, LOW ); // disable outputs to start with AD0-15 from outside
What is the reason for this setting? After the emulator is powered on, the content of the SRAM is not defined, it is random. That is, the target system's CPU starts executing random code. Maybe that's not a problem in an Atari or something similar.
In my use case I want to emulate the firmware ROM of an industrial system. This stores important data in a battery-backed CMOS RAM. The execution of unknown code after the start could overwrite data or cause unwanted signal combinations at external I/O connections.
I would prefer the emulator to start with holding the target system in reset (EN_RST = HIGH) until the SRAM contains defined content and EN_A11 to EN_A15 are set appropriately. The target system should only be released after autoload from the SPI, upload from the PC or manual load from the SPI using the push button.
Thanks Ralf
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Kris-Sekula/EPROM-EMU-NG/issues/3, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFTKLJFATYDG44C5W5AJO2LSTKPUNANCNFSM4UO2CO5Q .
Thanks Kris for the explanation.
I have the PCB 1.7. /OE of the SRAMs is connected to RESET.
Setting EN_RST to HIGH when the program starts is a bit tricky. Here is the solution to how I modified my emulator.
After resetting the MCU in the Arduino, the associated port data register and the port data direction register are set to zero (0). This means that the pin on the Arduino is in INPUT mode and therefore high-resistance/floating. It is not certain whether U1D (74HC00 pin 11,12) will treat the floating inputs as HIGH or LOW (U1 is CMOS, not TTL). So the state of RESET in emulator is also not predictable. To get a defined level in this intermediate state, I connected a 10kOhm resistor to EN_RST as an external pull-up.
The next is the initialization of EN_RST in the setup() routine. Since the Arduino first executes a series of internal code after the reset, which cannot be seen by the user, it takes a while until the setup() function is executed.
The obvious sequence
pinMode( EN_RST, OUTPUT ); digitalWrite( EN_RST, HIGH ); // target reset, enable shift register, disable 541 buffers
to initialize the EN_RST line has a pitfall. Since the port data register is at zero (0) by the MCU reset, executing pinMode (EN_RST, OUTPUT) causes EN_RST to leave the tristate state and actively go to LOW. Only after executing
digitalWrite (EN_RST, HIGH);
we get the desired high level again.
The trick to avoid this pitfall is to first set the port data register to one (1) and then set the port mode to OUTPUT. As a result, the pin changes immediately from the tristate state to active HIGH. Since the port data register is used to control the internal pull-up resistor in INPUT mode, you can set the port data register to one (1) in advance by changing from INPUT mode to INPUT_PULLUP.
The following states are passed through:
MCU reset: PORTD2=0 DDD2=0 Mode=INPUT EN_RST-Level=High by external pullup Arduino boot code: no change pinMode(EN_RST, INPUT_PULLUP); PORTD2=1 DDD2=0 Mode=INPUT_PULLUP EN_RST-Level=High by ext. pullup parallel to internal pullup pinMode(EN_RST, OUTPUT); PORTD2=1 DDD2=1 Mode=OUTPUT EN_RST-Level=High by active pin output.
The same applies to WE line (/WE on SRAM's). The original code in line 196 would run through the sequence Tristate => Active LOW => Active HIGH. Since we receive an L-H edge at the /WE pins of the SRAM, a data byte is even written in the SRAM here. At which address and with which value depends on the random states of the shift register after power on. To avoid this problem, I made the same changes here: External pullup from WE to Vcc and adapt the code.
My changes in the diff file compared to the published EPROM_EMU_NG_FW_2.0rc1.ino
EPROM_EMU_NG_FW_2.0rc1.diff.txt Greetings Ralf
Hi Ralf,
Once again, you made a great analysis and proposed a solution. Just a comment, at some point, you wrote: "Maybe that's not a problem in an Atari or something similar". Indeed the emulator design presented here was initially really meant to only be used for hobby projects Atari, Commodore, or simple Z80 SBCs alike. It's not a commercial solution, it was never intended to be used in "industrial" systems or to drive similar "mission-critical" devices. Clearly, you are an experienced engineer and you want to use the emulator to do some "real" work, so you are "sanity" checking, exposing, and helping to fix issues that could potentially cause a problem, thank you! And thank you for sharing those findings with us!
I'll add the proposed code changes to the next releases of the firmware, and I will include the 10k pull-up resistor in the next release of the PCB as those are beneficial to the design.
BTW, do we have to worry about the WE line at all? Even if we end up writing random data to the SRAM it doesn't matter as the SRAM will have random data inside at boot time anyway, and we will be restoring the data using the computer or the restore from SPI EEPROM function... or am I missing something?
Kris
Hello Kris
I am aware that this is a hobby project. But I enjoy perfecting my private projects or supporting others with their projects. If I can improve the emulator with my analyzes and tips, I'll be happy to do so. The more stable the solution, the higher the user acceptance will be. Hobby users are also happy about well-functioning solutions. Changes to software or firmware do not cost anyone any money. And a resistor more or less is not the factor to not making an improvement. Incidentally, there are suggestions from me, the decision whether they make sense and for an implementation of course you make. In addition, I can be wrong and make mistakes, I think that you test every change proposal thoroughly before you adopt it.
To the SRAM content after reset: You are right, after power on the content of the SRAM is undefined anyway. Thus, a random write command does no harm. However, if the SRAM content is valid after uploading an image to the SRAM (with saveSPI=0 and autoLoad=0), it could be corrupted by the random write command during reset if this reset is triggered by pressing the reset button on the Arduino, while the emulator is permanently under power (from USB and / or target system). You would have to point out to the user that the SRAM content is not reset-resistant as long as the unwanted write command is not suppressed during the Arduino reboot. Of course, this only becomes effective with a new PCB layout or if the user retrofits an existing emulator with pullups.
Ralf
Hi Ralf,
Just to close the loop. I'll be adding the pull-up resistors to the next rev of the PCB, for both the Reset and the WE line as it's not "costing" real money when I re-spin the PCB, but it should be noted that the emulator is not reset-resistant, even with the extra pull-ups and software improvements you are proposing. When I was designing the emulator, the Arduino "reset" button was not meant to be used for any function related to the emulator operation...but...wouldn't it be an excellent idea to perform a "target" reset using the Arduino "reset" button? :) Is this what you are trying to fix and I only just realized? haha :) The pull-ups will be required, but we will also have to add some logic in the firmware to re-store the state of the emulator after Arduino hardware "reset", for example, we need to restore the A11-A15 lines to whatever the "last used" EPROM type was...
Kris
Hi Kris
You are absolutely right. If the design does not include a reset on the Arduino for regular use, then it can stay as it is. I recognize that the situation is more complex than I thought.
mem_cfg in the configuration EEPROM is initially set to mem64kB if it has an invalid value. After that, mem_cfg is only changed when I upload an image for a different EPROM type and spiSave=1. Suppose I load a 27128 into the SPI for frequent use. Then mem_cfg is set to mem16kB. After resetting the emulator with autoLoad=1 or manual loading (push button) everything works fine.
If I now load a 2716 into the SRAM only (saveSPI=0, autoLoad=0) for a short-term test, setbus() is set correctly for the new type, but this is not saved in mem_cfg. That is ok, because mem_cfg should correspond with the image in the SPI EEPROM. The Emulator starts running my 2716 from SRAM after upload.
After a reset on the Arduino (with all changes that prevent corruption of the SRAM) there is no information for which ROM type an image is in the SRAM. You have to send (in this example) a ":ini16" and a ":EMUON" from the PC to the emulator so that it starts running on the correct bus. The manually ":EMUON" to start is necessary anyway, because the emulator should not start with autoLoad=1 and the SPI content (in my vision), but with the SRAM content. The whole thing can only work if the lastEPROM type is saved in a further configuration variable in the EEPROM config.
I think this is getting very special and doesn't justify the effort.
But thanks anyway for the exciting discussion.
Ralf
Hi Kris,
as discussed in the mail, here my current state of development. There are many changes in it, some of which I have already provided separately. The diff file against the public v20rc1 is therefore very complex, so I am also sending the full sketch.
The latest changes:
to include or not include special code for unfixed PCBs (/OE=GND)
ROM type in SRAM and ROM type in SPI are now handled separately, the new configuration option sram_cfg has been introduced for this purpose. Only after loading the SRAM from the SPI (autoload, push button) or uploading a new image to the SRAM with saveSPI=1 is sram_cfg=mem_cfg.
SPI clock increased to 8MHz (fosc/2). The 25LC512 can tick with 10MHz or higher. Further changes to performance tuning in load_SPIEEPROM() spi_transfer() --- could be renamed to spi_write ()?
The start of the time measurement in load_SPIEEPROM moved to the beginning of the function. So the measurement is more realistic than just measuring the loop.
New remote control sequence: LOADSPI Loads SRAM from the SPI, emulator remains in reset. The behavior of the pushbutton is controlled by sending : LOADSPI : EMUON to the emulator.
I hope you can find your way around the code despite the many simultaneous changes.
Ralf
Hi Sorry, yesterday I made a little mistake in the description. The last point has to be:
New remote control sequence :LOADSPI Loads SRAM from SPI EEPROM and starts emulation It is the same behavior as short pressing the pushbutton, but remote controlled.
Ralf
Thanks Kris for implementing my ideas in the new v2.0rc3 firmware.
I wish everyone a Merry Christmas.
Ralf
Hi Kris,
in setup() you starting the emulator with EN_RST = LOW, with means, the target is not in reset.
pinMode( EN_RST, OUTPUT ); digitalWrite( EN_RST, LOW ); // disable outputs to start with AD0-15 from outside
What is the reason for this setting? After the emulator is powered on, the content of the SRAM is not defined, it is random. That is, the target system's CPU starts executing random code. Maybe that's not a problem in an Atari or something similar.
In my use case I want to emulate the firmware ROM of an industrial system. This stores important data in a battery-backed CMOS RAM. The execution of unknown code after the start could overwrite data or cause unwanted signal combinations at external I/O connections.
I would prefer the emulator to start with holding the target system in reset (EN_RST = HIGH) until the SRAM contains defined content and EN_A11 to EN_A15 are set appropriately. The target system should only be released after autoload from the SPI, upload from the PC or manual load from the SPI using the push button.
Thanks Ralf