Jump to content
IGNORED

Creating a Lynx hardware debugger setup


LX.NET

Recommended Posts

He everyone,

I am currently working on creating a debugging tool for the Atari Lynx using normal hardware. It is derived from the Pinky/Mandy hardware. I have analyzed and reverse engineered most of the workings of the original hardware. It seems that it is very doable to create a debugger that can do the following:

  • Transmit data between the Lynx hardware and a normal PC using a ComLynx to USB cable. It will be able to send registers, code and memory.
  • Enable breakpoints in your 65C02 code
  • Step through code instruction by instruction
  • Manipulate memory
  • Show currently executing code including symbols from compilation

The setup would require a normal Lynx (I or II) and a Comlynx to USB cable. You need to compile your rom image to include a small monitor program. This monitor program will establish the communication between the Lynx and the PC program. The PC program in its turn will be the master when in control after hitting a breakpoint.

 

The setup will be even better when you can use the NMI pin of the Mikey processor to force a break into the monitor program. Lynxman was kind enough to modify a Lynx II model that has the oldest board TailChao reported about having a NMI pin, and allowed me to connect a button to trigger the NMI interrupt. Alternatively you can use and modify a Lynx I that always has the NMI pin.

 

I wonder if there is any interest in getting this to work. And if there are people willing to help out getting it all to work.

Here's what I have accomplished so far:

  • Use a button to trigger the NMI
  • Create a program that installs an NMI Interrupt Service Routine to start communication from the Lynx to the PC.
  • Transfer data from the Lynx to the PC and back
  • Return control to the program

There are some technical issues to solve. It seems that an old-fashioned button triggers multiple NMI interrupts, causing stack overflows or hangs in cases when it happens. I think it might be bounces of the signals, creating multiple edges in the signal. Lynxman will probably know how to solve it. Related is the stability of the UART communication. It might be influenced by the NMI issues.

 

 

Well anyway, let me know if you are interested in this at all and who is willing to contribute. I might do a video of the Pinky/Mandy setup and show what the functionality looks like. It will give a great overview of what I am aiming for.

Edited by LX.NET
  • Like 1
Link to comment
Share on other sites

The cc65 can also include debugging information in the binary. I have really been thinking to create 65C02 support to the Code::Blocks IDE environment. Downloading and running the code on a real Lynx instead of emulating is a nice thought. It would take a _lot_ of time to do this. On the other hand it is educational.

 

Have to think about this.

 

I just googled gdb. It has a serial mode for debugging that includes the routines:

getDebugChar, putDebugChar, flush_i_cache, memset, exceptionHandler.

The Lynx should only need

getDebugChar, putDebugChar, memset and a ComLynx driver with interrupts enabled.

In the cc65 suite we would also need to link in the debugging support. In gdb it is:

set_debug_traps();breakpoint();

at the start of your program.

 

--

Karri

Edited by karri
Link to comment
Share on other sites

Do you really need NMI? Would it not be sufficient to just use a modified interrupt-aware ComLynx driver and BRK commands?

 

The gdb has a neat communication structure:

 

post-2099-0-33773900-1399464542_thumb.png

 

2.3.1. Packet Acknowledgment

Each packet should be acknowledged with a single character. '+' to indicate satisfactory receipt, with valid checksum or '-' to indicate failure and request retransmission.

Retransmission should be requested until a satisfactory packet is received.

 

Link to comment
Share on other sites

He everyone,

I am currently working on creating a debugging tool for the Atari Lynx using normal hardware. It is derived from the Pinky/Mandy hardware. I have analyzed and reverse engineered most of the workings of the original hardware. It seems that it is very doable to create a debugger that can do the following:

  • Transmit data between the Lynx hardware and a normal PC using a ComLynx to USB cable. It will be able to send registers, code and memory.
  • Enable breakpoints in your 65C02 code
  • Step through code instruction by instruction
  • Manipulate memory
  • Show currently executing code including symbols from compilation

The setup would require a normal Lynx (I or II) and a Comlynx to USB cable. You need to compile your rom image to include a small monitor program. This monitor program will establish the communication between the Lynx and the PC program. The PC program in its turn will be the master when in control after hitting a breakpoint.

 

The setup will be even better when you can use the NMI pin of the Mikey processor to force a break into the monitor program. Lynxman was kind enough to modify a Lynx II model that has the oldest board TailChao reported about having a NMI pin, and allowed me to connect a button to trigger the NMI interrupt. Alternatively you can use and modify a Lynx I that always has the NMI pin.

 

I wonder if there is any interest in getting this to work. And if there are people willing to help out getting it all to work.

Here's what I have accomplished so far:

  • Use a button to trigger the NMI
  • Create a program that installs an NMI Interrupt Service Routine to start communication from the Lynx to the PC.
  • Transfer data from the Lynx to the PC and back
  • Return control to the program

There are some technical issues to solve. It seems that an old-fashioned button triggers multiple NMI interrupts, causing stack overflows or hangs in cases when it happens. I think it might be bounces of the signals, creating multiple edges in the signal. Lynxman will probably know how to solve it. Related is the stability of the UART communication. It might be influenced by the NMI issues.

 

 

Well anyway, let me know if you are interested in this at all and who is willing to contribute. I might do a video of the Pinky/Mandy setup and show what the functionality looks like. It will give a great overview of what I am aiming for.

Sounds like a nice project! The only think that worries me is the overhead of the code to handle the NMI etc. I guess if its really small and just breaking then it likely won't be an issue. Would be really nice to be able to step through code though!

Link to comment
Share on other sites

Nice work :)

 

There are some technical issues to solve. It seems that an old-fashioned button triggers multiple NMI interrupts, causing stack overflows or hangs in cases when it happens. I think it might be bounces of the signals, creating multiple edges in the signal. Lynxman will probably know how to solve it. Related is the stability of the UART communication. It might be influenced by the NMI issues.

Yes, you will need a debounce circuit if your monitor is going to be doing anything extensive. Luckily, you can just borrow some of the example reset circuits for the 6502.

In my case the handler is literally just setting a flag (telling the game engine to load the debug / stage select menu on the next frame) and then leaving. So there's not much threat of stack overflow. But this is much less complicated than what you're trying to do.

 

 

Do you really need NMI? Would it not be sufficient to just use a modified interrupt-aware ComLynx driver and BRK commands?

You can also do it that way, but the advantage of using NMI is that there is no way to trigger it on an unmodified Lynx and you don't need to be connected to a PC / host.
The ideal situation would be to reserve a couple hundred bytes of memory to fit a monitor program. So then you can just press a button and step through memory, check the state of the hardware, etc.

Link to comment
Share on other sites

I think the BLL kit contains debugging code for the lynx transfering data by comlynx. support for breakpoints etc.

maybe you can steal some code there.

As debugging/tracing etc within the emulator is easier, i didnt use it, thus i cannot tell you how good it is.

 

if you manage to teach gdb 65c02 code, it would be nice to have a gdb debugging port to en emulator. mednafen features this for some platform, but not for the lynx.. (as always)

Link to comment
Share on other sites

Thanks everyone for the feedback and ideas. I'm currently looking into gdb and the bll debugger. Great tjp, sage! What was the debugger counterpart for the bll 6502 monitor/break handler? Pc or Atari ST based? The bll debugger approach has very similar features to the Epyx development kit. I'll report back asap.

Link to comment
Share on other sites

I've gone through the BLL source code in debug.inc a couple of times.

 

The following is speculation and I want to verify this!

 

It seems that there are a couple of ways the debugger works:

  • Profiling BRK commands
  • Host BRK remote commands
  • Code BRK commands?

The profiling BRKs seem to send some data and continue automatically. Seems to be for seeing a heartbeat or something from the program to the PC.

 

Host BRKs are sent from the PC over the serial port. It raises an IRQ for receiving data on ComLynx UART and accepts a couple of commands

$82 - continue
$83 - set registers
$84 - write addr,n
$85 - read addr,n
$86 - get registers

 

Code are BRKs in your code followed by a command. Same as for serial BRKs.

 

Some questions:

How is the IRQ handler installed?

What is sent over the serial port to indicate a BRK? Just the command itself or a special byte ($81 could be the special one)?

Why installing the loader separately? Is that for the saving memory?

 

Thanks guys.

I have also drawn some picture for the GDB debugger combined with the Lynx and will share those shortly

Link to comment
Share on other sites

Did some more digging around in the BLL source code and samples. I think I am getting a better understanding of what is happening there.

 

Debug.inc is used in a couple of places and for a variety of purposes.

When you use the Serial communication part of BLL it includes part of the debugger stack for special commands.

The commands are all starting with $81 followed by the char value of a character:

'P': Upload functionality we have discussed before

'R': Resets current program

'S': Sends screen to PC

 

To use the upload the serial code stack calls InstallLoader (if the DEBUG conditional compilation constant is set). The debug-handler in debug.inc called do_debug is only called by the serial.inc code.

 

Then there is the other set of commands that you can send.

$82 - continue

$83 - set registers

$84 - write addr,n

$85 - read addr,n

$86 - get registers

 

So, whenever the serial stack is active and the $81 is sent, followed by "P" and the load address and length of the upload. The loader.doc document has this info (thanks GadgetUK for mentioning this in a previous post)

 

- The ComLynx-Loader wants :

 

start-sequence : $81,"P" ; command : load program

init-sequence : LO(Start),HI(Start) ; start address = dest.

LO((Len-10) XOR $FFFF),HI((Len-10) XOR $FFFF)

; and len of data

Xmit-sequence : .... ; data

checksum : none at all !!

 

To start using the other commands, you need to install the BRKserver, which is the piece of code that listens for incoming commands $82-$86. Commands can come in through BRK commands in the code (placed there by yourself as breakpoints) or commands over the serial connection.

 

INITBRK will install both the break server and the break service routine for incoming UART traffic and prepare the memory control, then jump into the break handling routine.

The irq.asm file holds the interrupt jump table to support multiple IRQ handling routines. It looks for the B flag in the Processor Status on the stack (pushed as part of the interrupt routine of the 65SC02). If set it was a BRK instruction in the code (user breakpoint). The break server is called directly. A special case for debugging is when the interrupt was caused by the UART. Then the interrupt jump table is not used and instead the break server is called.

 

A lot of confusing words, so a picture to clarify things a bit.

 

post-27403-0-94113300-1400082412_thumb.jpg

 

Bottom line is that there are a couple of cool ideas implemented in the wiring of the BLL debug facilities:

  • User breakpoints
  • Serial activation (instead of an NMI) of host initiated breaks
  • Sending screendumps across
  • Initiate a reset remotely
  • Profiling breaks

Next I will show how the Pinky/Mandy and mandebug setup works. Then we can see what the initial implementation should have.

Any ideas and feedback welcome as usual.

 

Link to comment
Share on other sites

For those following along, this blog post I just wrote might be worth reading: http://atarilynxdeveloper.wordpress.com/2014/05/16/overview-of-epyx-development-kit-part-2/

 

Further investigation of the BLL internals showed that it doesn't actually do serial activation of the monitor program. It is possible, but will overrule normal IRQ handling for serial.

Link to comment
Share on other sites

Small update:

Here is a new version of the BLL diagram that I think is a bit better.

post-27403-0-17985400-1400621167_thumb.jpg

 

And a before and after picture of the CC65 stack. Before shows how normal IRQs are handled.

post-27403-0-10818700-1400621177_thumb.jpg

 

The after picture shows what I think is the easiest way to get the monitor in place, without disrupting too much of the normal mode of operation.

post-27403-0-93249800-1400621184_thumb.jpg

 

Tomorrow I will explain the what and why.

Link to comment
Share on other sites

That would be awesome, because the protocol is one thing. How it is used is another thing. E.g. the Epyx debugger uses FillMemory to insert BRK commands in your code for single stepping. You cannot see that by looking just at the protocol.

Link to comment
Share on other sites

Seems I missed one nice thing for years. But actually I remember that the monlynx was crashing on start. Which seems to be tha case in the emulation, too...

The monlyx is not only able to upload/download and display, disasseble the lynx memory, but there is a trace feature, too.

Which is kind of half an emulation on the host PC.

and then the usual neat feature like Symbol loading etc.

Link to comment
Share on other sites

I am interested to know more about the tracing feature. The rest seems to be on par with the ManDebug debugger from the Epyx development kit.

Does or doesn't monlynx work? I couldn't figure it out from how you described it.

Link to comment
Share on other sites

Tomorrow I will explain the what and why.

 

Okay, so tomorrow was a few days later.

 

The idea is that a small piece of code (interceptor) is placed in front of the existing CC65 construct for building a interruptor table. CC65 doesn't create a table that is 8 large, btw, but determines it from the number of .interruptor marked pieces of code. The interceptor checks whether there is a BRK command or an interrupt for incoming data over serial. If so, it will delegate control to the monitor program. The monitor program waits for commands that the host (debugger on the PC) needs to send. If there is no BRK or received data, the normal flow continues.

Similarly, when an NMI occurs, control is immediately send to the monitor.

 

I've got the basics of inserting the interceptor working. A couple more days to look into serial communication.

Link to comment
Share on other sites

Perhaps a new debug+comlynx module? The interruptors are called on every interrupt and it is up to the interruptor to find out who interrupted.

 

--

Karri

That would be a pretty natural place to put it indeed. The reason I looked beyond that is the following:

To do the most effective debugging, the first thing that needs to happen when the monitor gains control is that it can store (and send) the register values for A, X, Y, PC, PS and SP. As far as I can tell from the CC65 implementation of the interrupters, it does the following in crt0.s:

	.segment "CODE"
IRQStub:
	phy
	phx
	pha
	cld
       	jsr    	callirq
	lda	INTSET
	sta	INTRST
	pla
	plx
	ply
	rti

Then in callirq.s

callirq:
        ldy     #.lobyte(__INTERRUPTOR_COUNT__*2)
callirq_y:
        clc                             ; Preset carry flag
loop:   dey
        lda     __INTERRUPTOR_TABLE__,y
        sta     jmpvec+2                ; Modify code below
     	dey
        lda     __INTERRUPTOR_TABLE__,y
        sta     jmpvec+1                ; Modify code below
       	sty    	index+1                 ; Modify code below
jmpvec: jsr    	$FFFF                   ; Patched at runtime
        bcs     done                    ; Bail out if interrupt handled
index: 	ldy    	#$FF                    ; Patched at runtime
       	bne     loop
done:   rts

So, the callirq.s trashes the A and Y register. Also, there are two JSRs before the debug interruptor will be called (assuming we give it the highest priority). Crt0.s has placed A, X and Y onto the stack, so it would be possible to grab them from there. I figured that this was more difficult to do, plus the downside of having to restore the stack again to unroll everything again for the RTS's.

 

Here's my first piece of code that inserts the interceptor and the interceptor itself checking for a BRK (might be buggy, although it seems to work):

_install_interceptor:
	php
        sei
        lda		#$c         
        sta		$fff9
	lda		#<_irq_interceptor
	ldx		#>_irq_interceptor
	sta		INTVECTL
	stx		INTVECTH
	cli
	plp
	rts

_irq_interceptor:
	phy
	phx
	pha
	cld
	tsx
	lda $104,x
	bit #$10
	beq no_break
	pla
	plx
	ply
	jmp _nmi_int
	 
no_break:
	jsr		callirq
	lda		INTSET
	sta		INTRST
	pla
	plx
	ply
	rti

Any comments on this approach? Would an interruptor like Karri suggested for debugging be feasible (easily)? What do you think, @Karri?

 

For a final implementation we might end up changing the crt0.s implementation. The interceptor is actually the IRQstub from with an optional section.

Edited by LX.NET
Link to comment
Share on other sites

  • 2 years later...

Connecting a lynx to a pc for multi player games via an emulator or trough the internet or for sending & recieving sounds awesome.

 

But what bugs me is that eventrough the lynx designers did had the idea of infrared in mind but decided to scrap it and go for uart link instead, WHY NOT choosing for a 2 way digital output instead?? That would,ve be way more cheaper,reliable,effective and more functional.

 

Ofcourse they could,ve decided for a 2 line uart system to allow transfering 2 directional signals atonce,but added extra costs.

 

Or they could,ve decided to allow even transfer 2 directional signals on 1 wire by coding the back signals to high frequency's and the forth signals into low frequencies in order to avoid collision( similar how a internet modem works with an antenna coax cable), but again it adds extra costs because 2 modules are needed.

 

But since the lynx uart system only uses 1 wire for sending & recieving data, it has to deal that limited bandwidch with other lynxes,so if lynx A talks, all other lynxes has to listen untill lynx A stops talking sothat lynx B can finaly talk to lynx A and so on,

 

IN THEORY there might be a way to quickly alternate back & forth (aka ac stream) sothat each lynxes can talk and listen to eachother in an alternate manner but that requires synching stuff and the software most understand this to not get confused and to avoid collision and once each lynxes will recieve and send a final stop signal from eachother, that the software will understand that, sothat all other lynx systems will know that this is seriouse,but again that will add to the latency.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...