Electronics > Repair

Fluke 8840A Faulty CPU

<< < (6/22) > >>

essele:
And bus writing now also works :-) ... I can initialise and write to the display, and once I stopped testing with an 8840A that seems to have a broken display everything sprang nicely into life -- so it looks like this is really going to be possible. The timing all seems ok, at least with the keyboard and display controller and the EPROM, it may be a little more challenging with the ADC, I'm not sure if the reads and writes are clock dependent.

I love these PSoC devices .. that extra capability to do some clever stuff at the hardware level really makes a big difference. With my current implementation I'm at 63% UDB usage, but that's with zero optimisation, and there are quite a few things I could do if needed. It's looking like everything else can be done with software, so this shouldn't be required.

Now to focus on the translation of the firmware, there do seem to be a few register indirect accesses to firmware addresses presumably for lookup tables or preset data, so these will take a bit of manual effort ... the rest I'm hoping can be fully automated, and then I can worry about tidying later.

essele:
A quick update...

I've spent quite a lot of time on automated code-path discovery so I can track RP, tests-followed-by-conditional-jumps etc, all with the aim of being able to automate reasonably efficient code generation, however I'm going to have to put that on hold for a bit ... there are quite a few nasties in the code that mean I need to rethink it slightly ... things like popping an extra return address off of the stack so you don't actually return from the CALL you think you should, and pushing FLAGS so you can use an IRQ handler (and IRET) as a normal CALL.

I still think this is the best approach, but I need some time to work out how best to code it ... my current solution doesn't revisit already travelled paths, which then makes it virtually impossible to properly track stack usage.

So, instead I've built a basic CPU emulator for the Z8, which should hopefully be good enough to prove the whole principle. The basic emulator is done, I'm now working on translating the register reads/writes into PSoC related code to simulate the same behaviour, then I'll need to figure out the interrupt side of things. It wasn't until I was well into this that I discovered there is also an emulator in MAME ... that was very useful in checking my logic. The MAME one isn't really focused on speed, so I've had to approach things a little differently.

I've discovered a few things that need some work...

1. The power line frequency is determined by counting how long P20 stays low, this is a tight loop and therefore dependent on execution frequency, it would actually work for me as is (since 50Hz is the slowest), however I'll need to think about how to address this for 60Hz and 400Hz line frequencies. The simplest way would be to adjust the compares in the firmware, but it will be interesting to see how far off the performance is by default (I can do an isolated test for this) and I'm not really sure how I can test 60Hz/400Hz ... maybe I can test outside of the unit and inject a signal.

2. Timer0 is used as the baud rate generator for the UART for the GPIB board. This is only ever used at a fixed 31250 baud so that can simply be hardcoded into the UART for now. It's relatively easy to translate the prescaler values into PSoC baud rates, so I could get a bit more flexible (not sure if the 8842 uses a different rate?)

3. Timer1 is used to set the ADC sampling rate, these vary depending on line frequency and slow/med/fast speed setting. So I've added a PSoC PWM module to output the timer and can translate the prescaler/initial-value settings into PSoC friendly calls.

4. Most annoyingly it seems that the ADC reads are all done using 'extended bus timing', this is a slower version of the bus interface that adds cycles to allow for slower devices. Interestingly the datasheet says it adds two cycles to the DS phase, however the timing diagram only shows one. (Did nobody ever proof read these things? There are loads of errors!) I am going to have to revisit my Verilog component to cater for this, at the moment I don't have a free control bit to switch modes, but I have a way to work around that.

5. On the interrupts ... we have keyboard, ADC, serial-in, ADC-timer ... two aren't used - the other timer (serial baud) and serial output. Serial output appears to be polled. I don't think there are any real issues here, I just need to figure out how to translate the whole priority side of things and make sure the behaviour of the various registers is the same.

Lee.

TheDefpom:
I am genuinely impressed by your project, and I thought I was doing well decoding the ADC a few years ago in one of my first YouTube videos whilst fault checking a 8842A

essele:
Thanks DefPom ... I'm actually really enjoying this, it's a throwback to some assembly stuff I did when I was 16 (and that was a very long time ago!)

I've just done the first performance tests and things are actually looking reasonable. I've recreated the code that does the power line frequency checks, so it's pretty simple and doesn't really involve any complex instructions, so optimising further may well be a bit of a challenge. However...

As I mentioned above the code goes into a tight loop incrementing a register pair until the power line signal changes, so I'm assuming this is timing the 'off-time' of the  'freq ref' line from the power supply, so the number increases as the frequency decreases.

The firmware looks for the following (if I'm reading it correctly):

1. If it's less than 0x200, then we assume 400Hz supply.
2. If it's more than 0x470, then we assume 50Hz supply ... I assume this would actually be the 55Hz point, well that's what I would use.
3. Otherwise it's 60Hz.

Bearing in mind I'm on a 50Hz supply at the moment, I can only currently read the 50Hz value, but I've extrapolated based on that, and I get the following:

For 50Hz I get a value of 0x578, with optimise for speed, I get 0x5c8.
For 60Hz that extrapolates to 0x48e, and 0x4d1 with optimisation ... so this would miss and be assumed at 50Hz.
For 400Hz it would be 0xAF, or 0xB9 with optimisation.

So it's actually pretty close ... obviously you would want to be well inside the values to have some margin to play with, but whilst it means that this bit may not function it shows me that the emulator is actually running at a reasonable speed. I may well have to resort to cycle counting to have a better estimate of what the actual Z8 values would work out to be ... I can then look to see if I can further optimise .. but that's a job for later.

The other thing is that it proves that my external port access to port20 is working ... and that was just two lines of code!

EDIT: I'm a muppet ... I've just been trying to work out the actual cycle count and realised that actually the emulator is running faster than the original Z8 ... it's bloody obvious because my numbers are bigger than the expected ones, therefore I manage to go around the loop a few more times! That's really good news, it's much easier to slow it down ;-).

So the Z8 manages to go round this loop in 128 clock cycles (8Mhz), therefore it can do it 62500 times a second. I'm managing 70000 and 74000 depending of whether I'm optimised for speed! So it looks like I'm between 12% and 18% faster ... these are simple instructions though, I'm sure once we're in to some of the maths ones with loads of flags this won't hold.

essele:
I've now implemented the extended bus timing (but only for reads, since it's only needed for the ADC reads), the datasheet was actually correct, I was mixing clock cycles, machine cycles and the various other cycles they seems to have made up for the Z8.

I can read the 5 values from the ADC and they all come back and seem to be 6 bit values which is a good sign ... the actual values are a bit questionable, but I'm currently not reading them straight after the interrupt, so they could be a mix of samples or values mid-sample. I've got a plan for the interrupt mechanism and I'll use this as the first test.

I was looking again at the performance numbers ... actually I think I had misunderstood the performance of the Z8 and it's four times slower than I had thought...

The external clock (8MHz) is divided by 2 to give you the internal clock (obviously now 4Mhz), then the instruction 'cycle counts' seem to be "timing states" which pretty much seem to take 2 clock cycles each anyway (although some of the timing diagrams show it as 3.) So that actually means that an instruction taking 10 cycles on the Z8 is really 40 cycles at 8Mhz, which then gives us 240 cycles on the 48Mhz ARM to emulate the same behaviour.

This is born out by the tight loop for power line frequency detecting ... that was a 32 'cycle' loop (INCW, TM, JR), but actually working it through assuming I was right about my 55Hz cut-off we had 62500 iterations per second, which equates to 128 cycles at 8Mhz per iteration, so for 32 'cycles' on the Z8 that means it's effectively divide-by-4. So it's really a 2MHz CPU.

I've figured out a nice way of handling interrupts that doesn't require me to check something each cycle, and I think I've worked out how to map the various interrupt request, mask, and status lines.

I still need to work out how to deal with the Z8 reset line ... it's a normal GPIO for the PSoC, but since there's the potential for getting stuck with interrupts disabled I don't really want to handle it as a normal IRQ ... I think the watchdog reset might have potential here. I will also experiment with using another pin wired directly to the PSoC reset line, that way taking that pin low should reset the device, I can then optionally internally connect that pin to the Z8 reset line to give a configurable reset (experiments to follow -- not sure how often this is actually used during normal operation, presumably it's just an error condition.)

So next steps...

1. Interrupt mechanism + mapping interrupt registers.
2. Finish off the port configuration registers (inc. serial and timer configs.)
3. A debug exception mechanism for handling illegal instructions and register configs I don't deal with (external stack for example.)
4. Mechanism for timing instructions to see how close to the Z8 we can get.

Then I should be on to actual firmware testing -- exciting.

If it works then I think it will be worth building a board to try to extract the internal firmware from the Z8 so that we can get at the different versions, I only have v2.3 for the 8840, and I've got a working Z8 and EPROM that seems to be v2.5 that I'd love to extract.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod