spth / OpenRabbit

Loader and Debugger for Rabbit Semiconductor µC, such as the Rabbit 2000,Rabbit 3000 and Rabbit 4000.
Other
8 stars 3 forks source link

program start by RFU? #22

Open spth opened 4 years ago

spth commented 4 years ago

Currently, for a program using serial port A, I have to:

Could this be simplified? Could the RFU start the program at the end (maybe depending on commandline option), soI don't need to power-cycle? Could the RFU leave the cable in a state that allows serial I/O by a terminal program on the programming port, without requiring the use of the diagnostics port?

tomlogic commented 4 years ago

Hmmm. I think an easy solution would be to reset the processor via the control lines and send the single triplet needed to start the program (0x80, 0x24, 0x80). We could write a simple program to do that, and then fire up minicom at the desired baud rate.

But note that the minicom configuration will need to keep its hands off of DTR (or start up holding it in the correct state), otherwise you'll reset the processor again.

spth commented 4 years ago

First attempt in 66bf9c2, doesn't seem to be working yet, though.

tomlogic commented 4 years ago

I wonder if leaving the serial port open in openrabbit will allow the code to run? Closing the port might change DTR and pull it back into reset. I might try that out, and see if the LED lights up, indicating that the code is running.

tomlogic commented 4 years ago

Got it working with 5b50f671c0e4a17d6d0cb8df482d0caff435949d. Needed to drop back down to 2400 baud before sending the triplet.

The program continues to run after openrabbitfu exits, but I haven't been able to re-open the serial port in another application to monitor stdout. Both minicom and screen end up resetting the processor via the DTR line. I wasn't able to find configuration options for either to change the startup behavior.

In Google searching, I found a reference to a miniterm.py script with support for specifying the initial DTR signal level on startup.

We might want a little standalone program to just do the "reset and run" step. I'll reference my request #18 to perhaps have multiple programs instead of a single program with two modes (rfu/debug).

We could switch the serial port up to 38400 after sending the triplet, and then just dump any received data to stdout. Maybe that could be a feature of the "reset and run" program, with command-line options for the serial port and baud rate. And send any entered characters.

spth commented 4 years ago

I'm wondering if something rather basic (i.e. just invoke stty manually for settings, then just display the output via cat) would work, but so far I haven't had success.

Worst case, we could still implement a --display that just keeps the port open in the RFU and outputs whatever is received.

spth commented 3 years ago

I have now implemented a different approach instead: A --serialout option that keeps the serial connection and just outputs whatever it receives from the Rabbit. Unfortunately, it currently is not reliable yet: Once in a while, I simply see no output from the running program. Maybe there is a race condition or other timing issue?

tomlogic commented 3 years ago

IIRC, you're using hard-coded baud rate dividers instead of the run-time calculation in Dynamic C's Standard BIOS. I recently helped a customer who was seeing their hardware start up with an incorrect divider for some reason, so if you are using run-time calculations, you might want to review that code (or switch to hard-coded values).

spth commented 2 years ago

One, but not the only, problem was that reset was unreliable. It used to pull the reset line low for 250 ms.Increasing that time to 400 ms helped.

spth commented 2 years ago

I looks to me like the remaining issue is indeed a serial line speed issue: sometimes instead of seeing nothing on the host, I see some garbage, as one would expect when serial speed between host and Rabbit don't match.

When I then retry (i.e. write another image to the RCM via OpenRabbit) it tends to work again. But over time the error gets more frequent.

So I wonder on which side the choice of the serial line speed could go wrong: On the host, OpenRabbit just uses tcsetattr. On the Rabbit, the example programs (such as the "Hello, world!") use the asynchronous mode on port A, configured for the respective baud rate. I mostly test using an RCM3319 (which has a Rabbit 3000A). I have a script that alternatingly writes a "Hello, world" and a Dhrystone to the RCM. For each, it parses the output, before it continues. This typically hangs after a dozen or so iterations of the loop.

Which dividers could be wrong on start? The "Hello, world!" explicitly writes WDTTR and GCSR immediately after startup, later it writes PCFR, TAT4R, TACSR, SACR. All other I/O registers are left at startup values. Then the serial output is done via SASR and SADR. No other I/O registers are written. This should (and usually does) give us "Hello, world!" at 38400 baud. The Dhrystone is similar, but also writes GCDR, MB0CR and MB2CR - it runs at twice the speed, so it needs to configure wait states. Later it also uses RTC?C. The code is at https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc-extra/historygraphs/hello-r3ka/, https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc-extra/historygraphs/dhrystone-r3ka/ and https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc-extra/historygraphs/execute_benchmark-r3ka.

I wonder if maybe the osciallator gets unstable?

tomlogic commented 2 years ago

There could be instability in the oscillator at startup. I know that the BIOS has code to calculate a baud rate divider based on the clock, and recent/later BIOSes would re-run the calculation until it got the same result twice in a row. I think the startup instability may have been related to the 32kHz RTC clock and not the CPU clock.

You might be able to hard-code the divisor setting, since it should be a fixed value based on the CPU clock. You could use the hard-coded value to set the timer registers, and have it output the calculated value over the serial port to see what it's calculating.

If you're changing the doubler setting, I think you need to update the timer registers as well.

You could hook a logic probe up to the serial lines to see what they're doing when the module hangs. There might be some other bug in your code that causes it to go into an infinite loop. Unless you're also toggling a "heartbeat" LED in your code loop so you know it's still running...