Debug coexisting with serial output?
I was thinking that it'd be convenient to have the newish P2 debug window and regular smart serial output working together.
It seems can use debug window as serial terminal if set baud to 2_000_000.
But, in this little test here, if I add a debug statement then P2 seems to hang.
Or, serial output stops anyway.
Is there a solution for this?
Also: It'd be convenient if the Prop Tool did not require a debug statement to be present in order to launch the debug window...
Comments
Hehe, you'll be throwing a curve ball with that. I think the Debug handler always re-init's the serial smartpins on every call. Any partial transfer will be cut short, which will likely mess with the debug framing as well as lose user data. And of course the user code will also lose the smartpin IN state.
Flexspin can handle it though. Where using compile option
-g
instead of-gbrk
then it'll handle using both user terminal and debug terminal together. It's a legacy hangover that's still supported.I haven't used DEBUG much lately and don't really know its current feature set but if there was a way to use the debug mechanism to identify regular "non-debug" serial data to the PC and then demux it accordingly, then a serial object could be coded to choose to use a suitable transmit path (assuming it knew when DEBUG was active vs not compiled in). There well may need to be a special debug format symbol (the "CHR" format below) or other named tag to identify this case. Sort of like the following pseudocode.
PUB tx(val) #ifdef DEBUG ' run this when DEBUG is enabled DEBUG(CHR(val)) ' use the debug path send a character to the regular output terminal in order to sync it with any other serial debug activity #else ' directly access smartpin wypin(tx_pin, val) txflush() 'rja #endif
Is there a good way for the compiled code to know when DEBUG is active or not and let it alter its behaviour like this? It might not need to be a conditional compilation approach.
Note that this idea is only for transmit. The serial receive case still assumes it can access the smartpin hardware directly from a COG taking input from it.
Hmm didn’t realize debug reset smart pin on every use…
Maybe it also resets it after use ?
That might explain what I’m seeing…
I seem to recall Chip saying this would work, but I’m definitely missing something…
Is the DEBUG multiplexing scheme documented anywhere? I wonder if the non-debug data in the serial stream is already being identified via the absence of some given debug "escape" sequence already. If you have to tag each and every non-debug character explicitly as being non-debug and intended for the usual console/terminal it could potentially increase the serial transfer requirements by at least 2x or possibly more depending on the actual scheme, which is not ideal.
There was a change a year or so back to provide settable baud. One or both smartpins now alternate between repository and async-serial mode. So that'll ensure there is no remaining user comms activity. So the debug code now computes the X register clock divider each time as well.
Ok, seems all I have to do is restart serial like this before using regular serial after a debug call:
PUB Loop(n) 'Loop Routine Testing(n) waitms(1000) ser.start(2_000_000)'115200*2) ser.str(@"This is a string for loop #") ser.dec(n) 'This causes P2 to hang? ser.tx(13) 'carriage return
This might become my new favorite way to use prop tool with serial...
Don't have to deal with PST... PST is OK for the most part with F12, but doesn't always work like I'd want.
Plus, can use debug, if needed.
Think I'll add a fake debug statement to serial driver so don't need one in main code.
Actually, maybe can make a MyDebug() routine that restart serial after use....
Above seems to also work in FlexProp using internal PST terminal and "print debug" and baud set to 2MEG.
But, FlexProp doesn't require restarting serial to work...
This might be a solution:
obj 'Objects ser : "SimplerSerialDebug" 'For serial diagnostics PUB Main()|nLoop 'Main Routine Setup() repeat Loop(nLoop++) PUB Setup()|i 'Setup Routine 'Start serial and do countdown ser.start(2_000_000)'115200*2) PUB Loop(n) 'Loop Routine ser.dudec(n) 'debug unsigned decimal waitms(1000) ser.str(@"This is a string for loop #") ser.dec(n) 'This causes P2 to hang? ser.tx(13) 'carriage return
This some things added to SimplerSerial to make SimplerSerialDebug version:
DAT 'pins fixed to the usual rx_pin long 63 tx_pin long 62 baud long 2_000_000 PUB Start(baudrate) | bitperiod, bit_mode 'start using user defined pins 'Note: The "mode" parameter, used by fullduplexserial, has been removed ' calculate delay between bits bitperiod := (CLKFREQ / baudrate) ' calculate smartpin mode for 8 bits per character bit_mode := 7 + (bitperiod << 16) ' set up the transmit pin pinf(tx_pin) wrpin(tx_pin, _txmode) wxpin(tx_pin, bit_mode) pinl(tx_pin) ' turn smartpin on by making the pin an output ' set up the receive pin pinf(rx_pin) wrpin(rx_pin, _rxmode) wxpin(rx_pin, bit_mode) pinl(rx_pin) ' turn smartpin on baud:=baudrate PUB dUDEC(x) 'Debug an unsigned decimal number debug(udec(x)) start(baud) PUB dUHEX(x,n) 'Debug an unsigned hexidecimal number debug(uhex(x,n)) start(baud)
This test shows it can work with serial and debug in subobjects too.
But, this gets away from Spin2 documentation and makes it hard to explain...
So, probably just say to use ser.start() after every debug...
Or, before every serial output.
Or, maybe can add faster version of ser.start() where smartpin setting have been saved and add that to start of every serial operation. That might break consecutive serial outputs though...
Wishing there was an easier solution here...
Flexspin's built in serial routines for C and BASIC are written to act very much like the debug serial routines, and as a result they are (usually) compatible with debug. For example:
obj c: "libc" pub main() | a a := 1 c.printf(@"using printf: a = %d ...", a) debug("using debug: ", sdec(a)) c.puts(@"using puts") debug(sdec(a+1)) c.puts(@"done")
outputs:
Cog0 INIT $0000_0000 $0000_0000 load Cog0 INIT $0000_0404 $0000_0000 load using printf: a = 1 ...Cog0 using debug: a = 1 using puts Cog0 (a + 1) = 2 done
Good to know. I guess I never tested
-gbrk
like that.Think that maybe this is working and can also work with Spin Tools IDE and FlexProp.
Looking like the most portable way is to send both CR and LF.
Added these functions to help:
PUB crlf() 'send CR and LF tx(13) 'CR tx(10) 'LF PUB println(p) 'print a string and then do CRLF str(p) crlf()
But, do need to turn off the line feed handling in PST if want to use that instead of Prop Tool debug.
Also, need to switch back to ANSI terminal option in FlexProp.
Guess feeling moderately happy with SimplestSerial. At least for new users of Prop Tool, makes serial output easy.
Was going to post this in OBEX, but that is locked?
Added this to my "Getting started with SimpleP2 and Spin2 guide". Going to see if my kids can follow it..
Was just testing this out some more with Prop Tool debug window and appears the only real issue is using Spin2 debug statements.
The program can freeze if you don't call ser.Begin() after a Spin2 debug statement.
Assembly debug statements don't seem to be an issue.
Coginit and cogspin both emit some serial output that can get jumbled if a delay is not added after these, but it stays on the rails without it.
Attached are some more demo/tests.
Posted it to OBEX. See now there's a 24 delay before you can do that...