LMM P2 Debugger - Uses Serial Tx & Rx for debugging single cog programs
Cluso99
Posts: 18,069
Update 28 May 2013:
The latest code v0.86 is posted on threads #275 & #276
http://forums.parallax.com/showthread.php/146688-LMM_SerialDebug-Simple-Serial-Tx-amp-Rx-for-debugging-single-cog-programs?p=1184834&viewfull=1#post1184834
The latest writeups are on posts just prior to these.
The debugger now includes simple instruction decoding as well as display/modify of both hub and cog ram.
I have also changed the thread title to better reflect the debugger.
Update 18 APr 2013:
Works on both DE0 & DE2 emulators.
Additional features and versions on page 3.
Update 24 Mar 2013:
Latest code adds RX mode to receive a serial character. This now permits the users cog code to interact simply with the serial terminal.
(see v0.22 below, and in post #33)
Update 20 Mar 2013:
Here is working v0.10 code for debugging single cog pasm.
Requirements: 11 longs of user cog space, plus 2 longs per call.
The cog space is an LMM execution unit and the hub space (currently set to $1000, but can be changed in the CON section) stores the LMM debug code.
The current code permits the user to call the routine to send an 8bit character to the serial port (transmit only for now, at least).
Baud can be set in the CON section.
Z & C flags are saved and restored.
LMM_SerialDebugger.spin
Previous posting...
Here is a simple Tx program using P90 and USB & PST on the DE0.
It uses 12/13 longs of COG ram plus 2 longs for each tx/debug call.
It is based on Chips ROM Monitor.
I used the constant #511 which gives ~2% higher baud rate than 115,200. It seems to work fine, and saves a long.
Serial_test.spin
The latest code v0.86 is posted on threads #275 & #276
http://forums.parallax.com/showthread.php/146688-LMM_SerialDebug-Simple-Serial-Tx-amp-Rx-for-debugging-single-cog-programs?p=1184834&viewfull=1#post1184834
The latest writeups are on posts just prior to these.
The debugger now includes simple instruction decoding as well as display/modify of both hub and cog ram.
I have also changed the thread title to better reflect the debugger.
Update 18 APr 2013:
Works on both DE0 & DE2 emulators.
Additional features and versions on page 3.
Update 24 Mar 2013:
Latest code adds RX mode to receive a serial character. This now permits the users cog code to interact simply with the serial terminal.
(see v0.22 below, and in post #33)
Update 20 Mar 2013:
Here is working v0.10 code for debugging single cog pasm.
Requirements: 11 longs of user cog space, plus 2 longs per call.
The cog space is an LMM execution unit and the hub space (currently set to $1000, but can be changed in the CON section) stores the LMM debug code.
The current code permits the user to call the routine to send an 8bit character to the serial port (transmit only for now, at least).
Baud can be set in the CON section.
Z & C flags are saved and restored.
LMM_SerialDebugger.spin
Previous posting...
Here is a simple Tx program using P90 and USB & PST on the DE0.
It uses 12/13 longs of COG ram plus 2 longs for each tx/debug call.
It is based on Chips ROM Monitor.
I used the constant #511 which gives ~2% higher baud rate than 115,200. It seems to work fine, and saves a long.
Serial_test.spin
Comments
I look forward to trying this out.
Another way for doing serial might be the SNDSER/ RCVSER commands designed for inter-prop communication. Its not clear whether they can be adapted for start & stop bits, etc. We will need to wait for the detail on these
If I had a DE2, I suppose I could just run monitor in the other cog, but this may be even easier.
One question, would it be easy to make it 9600 baud?
Or, do you want to do it fast so as not to mess up video drivers?
Or, are you trying to save a long that would be needed for the period?
I think I see you did it to save a long, now that I look closer...
If you not want save a long you can make any baudrate: Andy
As you have seen, yes you can make it any baud you like. I only posted a snippet from the file, so the baud and clock are defined as constants at the top.
Here is the next bit of code I used to locate my file in hub (just wanted to check it was there, hey hey) at $E80...
I am on to getting it working using LMM. So far, seems like I will need 8 longs to do it.
David: How are you compiling LMM with GCC ?
If you want to build LMM C code for P2 just use the version of PropGCC that I posted a month ago with the -mp2 command line option. Now that I have flash loading working I guess I should make another release.
What I've been working on recently is getting C programs to boot from flash at reset. As you know, the ROM loader only loads a single COG image. That has to contain a second-stage loader that pulls in the rest of the hub image. That is what I got working last night.
I need to compile a pasm program for the P2 that has LMM code. What I am trying to do is put the tx routine (above in the serial program) as an LMM routine resident in hub, and then have a simple routine in COG that will run an LMM routine when required. This is for using the serial output to debug COG code with a minimal footprint in the cog. This way, the hub LMM routines could be expanded with calls frm the cog LMM routine.
So I am looking for a simpler way to compile LMM. Currently I have to specifically code LMM instructions and use P2 pnut.exe. Is there a better way by using GAS in PropGCC without learning GCC?
Here is an example of where I am currently up to (there is a bug - no output)
The macros are described in the propeller section of the assembler manual: as.pdf.
https://code.google.com/p/propgcc/downloads/detail?name=as.pdf
Well I guess I misunderstood "looking for macros" then. Whatever.
I just looked at the GAS document (thanks Steve) and it would seem to do what I require. The BRS & BRW are the macros (or extended instructions if you like) I would need.
What do they expand to?
Presuming they perform an add/subtract or move to the PC, can the location of the PC in cog be simply relocated???
Is there a description of the LMM execution instructions you are using? I see you predefine about 18 regsters beginning at Cog $0.
I am using a very simple and compact LMM execution unit. The hardest part is compiling the LMM debug code that will reside in hub and be executed by this LMM execution unit - currently this has to be hand crafted.
This is what I am trying to do...
1. Have a minimal LMM execution unit that can be added to anyones cog pasm code (minimum footprint)
2. When they execute a CALL to my LMM execution unit, it performs some specific debugging (currently just transmits a character passed to it, to the serial port, and returns to the users code).
3. When this works, I may add some extra features, such as calling parameters in addition to the simple char to tx.
I don't think it is possible to move the registers to a different location. The LMM kernel depends on R0 being at COG location 0.
That's a pretty neat idea. Sort of the reverse of fcache.
Eric may be able point to more info on the LMM engine.
The only doc I know of is in the repository here: http://propgcc.googlecode.com/hg/doc/Memory.html
Here is a working version of your LMM trial code.
You need 3 delay slots between modifying a cog register and executing it. You should perhaps read the long LMM-P2 thread from Bill Henning, where we have discovered the LMM possibilities of P2.
Doing the LMM code in PNUT is not that hard, if you use realtive jumps.
Andy
Currently uses 11 longs in the users cog, plus 2 longs per call. The debug tx routine currently lives in hub at $1000 but his can be changed.
Z & C flags are saved and restored. BTW this is so simple to do - thanks Chip!
LMM_SerialDebugger.spin
The passcnt instruction should follow the setpc instruction and then the 1/4s delay at teh end is not required.
I like your sub LMM_PC,#5*4 instruction.
There are a few thing that I can do to shorten the cog code, but for now it is fine.
All:
I am thinking about a calling method where I can call a number of different LMM routines. Perhaps I can use the LMM_x register to use the upper bits for a calling method number.
Just in case you didn't realise, the method to save and restore the Z & C flags is so simple!!! Thanks Chip
I am trying to add some function calls to my serial debugger, such as outputting hex, etc.
How do I do a call in LMM? I need to save the return address but how???
otherwise you will need PASM helper routines for call and return, which handels a stack (easy on P2 if you can use the stack ram).
Andy
I don't want to use cog resources such as the stack, etc, so that there are minimal restrictions on the users program.
If you try it dont forget to add $E80 to every subroutine address:
rdlong LMM_PC,LMM_PC
long @subr1+$E80
Andy
I hadn't noticed that feature. Thanks for pointing it out!
My thoughts are to build a second version with the ability to contain additional LMM code to output...
- Tx an 8 bit character in X (where X is LMM_X) - same as done
- MOV LMM_X,#"7"
- CALL LMM_TX WZ,WC
- Preset a mode (LMM_Y) with a value for a Function to be performed
[LIST=|INDENT=1][*]MOV LMM_Y,#mode+n 'n is a nibble parameter as required by some modes (only needs to be preset once)
[*]MOV LMM_X,[#]value
[*]CALL LMM_FN WZ,WC
[*]This mode is static (only needs to be set once) using "MOV LMM_Y,#mode+n"
- mode is in bits 8..4; n is a nibble parameter 0-15 in bits 3..0
[*]modes are...- ASCII
- X is lower 8 bits
- X=$00..$1F displays "<xx>" where xx is the hex value of X
- X=$20..$7E displays the ascii character
- X=$7F..$FF displays "<xx>" where xx is the hex value of X
- HEX
- X is 32 bits
- n sets the number of hex digits displayed
- DECIMAL
- X is 32 bits
- n sets the number of decimal digits displayed
- BINARY
- X is 32 bits, lowest bits used
- n sets the number of nibbles (quad bits) displayed
- STRING
- X is the address of the string, $0 terminated
- if X<511 then the address is in COG RAM
- if X>511 then the address is in HUB RAM
[/LIST]This does...
1. sends characters to the serial port
2. options for displaying in hex and hex reversed (ie. swaps endian), and option for no. of digits(nibbles) 1-8
3. options for displaying strings, nul terminated, residing in hub
4. apart from ~15 longs, all code resides in hub and runs in LMM mode
5. mode only needs to be set each time the mode is required to change
LMM_SerialDebugger_010c.spin
This will be very useful for everyone debugging cog code.
Here is the latest v0.20 update...
- Two basic call types are provided
- LmmTx
- Displays the char copied to lmm_x
- Does not have a mode setting
- This call does not interfere with LmmCalls and their modes
- LmmCall
- Displays chars according to the mode setting
- Modes are:
- ASCII
- Displays visible chars $20..$7E (" ".."~")
- All other chars are displayed in hex n the form "<xx>"
- STRING
- Displays a "nul" terminated string (currently only from hub)
- HEX
- Displays hex digits of a value supplied in a long.
- Digits selectable from 1..8 in mode call.
- HEXREV
- Same as HEX, but reverses the byte order first.
- DUMP
- Displays 4 longs (16 bytes) in HEX and ASCII plus address (currently only from hub)
- Similar line display to the P2 Rom Monitor
- Once mode and address are set, subsequent single instruction calls display the next line address.
- Mode
- Once set, the mode remains set until a new mode is required (i.e. "sticky")
- Mode is set in bits b7..4
- A mode Modifier is set in bits b3..0 (typically to specify number of digits in Hex mode)
- Z & C flags are maintained for the user
- Currently uses 16 longs in COG
- Serial Debug code resides in hub and is executed as LMM.
- Uses minimal Prop Cog resources.
It is my intention to convert this back to Prop1 code later.LMM_SerialDebugger_020.spin
Postedit:
Current v0.20 hub usage is <1KB (~$3A0) plus the 16 longs (loaded into user cog) and any user calls.
(but I am certain you were already planning to add it)