Jump to content
43oh

Software debugging without hardware tools


Recommended Posts

This is for assembler programmers, way of debugging based on software without any hardware tools (only uC). So if you are programming MSP430 with C, playing in (launchpad) lego world, this is not for you.

 

I will not publish complete source here, but will introduce idea, and help someone to build it's own version (not only for MSP430).

 

I was working (before MSP430) on some other uC that don't have debugging interface (like MSP430), and there is no nice way for checking the code.

 

There was (for some uC) debugging based on inserting software layer under the user program, or only adding some software around breakpoints. And than this special software inside uC was communicating with debugging hardware, or only with PC application. Big minus for debugging on this (only possible) way was in losing some flash/ram memory blocks, original vector table or registers, because debugger was using them for itself.

 

All uC have (at least one) uart port, or it can be created (by software) if not exist. My idea was to use one uart for uC/PC main application, and another uart for uC/PC debugging. Debugging function are placed in separate file and just in lined in main assembler source (#include "dbg_uart.s43"). If debugging in main file is enabled (#define DBG_UART) also will be enabled all debugging functions (#ifdef DBG_UART). If debugging in main file is disabled, produced program (final release) will be in original form, without any debugging part.

 

I made mine own BLS version, and I use it not only for flashing, but also for standard MSP430/PC uart communication when I need it. It is based on MAX3243E (SOIC) from TI, and placed inside DB9 connector.

 

bsl.gif

 

bslg.jpg

Link to post
Share on other sites

All debugging functions for working use only stack, average about 10 words. For today uC's (MSP430F5xx) this is not big issue. State after calling debugging functions must be the same like before call, all registers must be unchanged (except R15, that is used as input/output parameter for debugging functions). Of course, uart used for debugging can't be used in main application for something else.

 

Application on PC side is simple. After opening serial port it start reading from uart. Always read just one byte, and if the reading failed (timeout) read again, and again... (forever). Display received character on CMD and save it in log file. After receiving CR create new line. There is no need to close port during flashing/reseting uC.

 

Here is assembler source with debugging functions:

 

C932                                                      
C932 B01200C0                     call #DbgCR             
C936                                                      
C936 B01228C0                     call #DbgStr            
C93A 50726F677261*                db 'Program Begin', 0   
C948 B01200C0                     call #DbgCR             
C94C                                                      
C94C 3A403412                     mov.w #01234h, R10      
C950 3B404523                     mov.w #02345h, R11      
C954 3C405634                     mov.w #03456h, R12      
C958 3D406745                     mov.w #04567h, R13      
C95C 3E407856                     mov.w #05678h, R14      
C960 3F408967                     mov.w #06789h, R15      
C964                                                      
C964 B012CAC2                     call #DbgRegs           
C968 B01200C0                     call #DbgCR             
C96C                                                      
C96C B012D4C1                     call #DbgPC             
C970 B01200C0                     call #DbgCR             
C974                                                      
C974 3F403930                     mov.w #012345, R15      
C978 B01272C1                     call #DbgWordDec        
C97C                                                      
C97C B01228C0                     call #DbgStr            
C980 202B2000                     db ' + ', 0             
C984                                                      
C984 0E4F                         mov.w R15, R14          
C986                                                      
C986 3F40A05B                     mov.w #023456, R15      
C98A B01272C1                     call #DbgWordDec        
C98E                                                      
C98E B01228C0                     call #DbgStr            
C992 203D2000                     db ' = ', 0             
C996                                                      
C996 0F5E                         add.w R14, R15          
C998 B01272C1                     call #DbgWordDec        
C99C B01200C0                     call #DbgCR             
C9A0                                                      
C9A0 3012434B                     push.w #04B43h          
C9A4 30125441                     push.w #04154h          
C9A8 30122053                     push.w #05320h          
C9AC 30124F4E                     push.w #04E4Fh          
C9B0 B01216C2                     call #DbgStack          
C9B4 B01200C0                     call #DbgCR             
C9B8 3F41                         pop.w R15               
C9BA 3F41                         pop.w R15               
C9BC 3F41                         pop.w R15               
C9BE 3F41                         pop.w R15               
C9C0                                                      
C9C0 22C3                         clrz                    
C9C2 B01266C2                     call #DbgSR             
C9C6 B01200C0                     call #DbgCR             
C9CA                                                      
C9CA B01228C0                     call #DbgStr            
C9CE 537472696E67*                db 'String', 0, 0       
C9D6 B01200C0                     call #DbgCR             
C9DA                                                      
C9DA 22D3                         setz                    
C9DC B01266C2                     call #DbgSR             
C9E0 B01200C0                     call #DbgCR             
C9E4                                                      
C9E4 3F400ACA                     mov.w #Mem, R15         
C9E8 B01270C3                     call #DbgMem            
C9EC B01200C0                     call #DbgCR             
C9F0                                                      
C9F0 B01228C0                     call #DbgStr            
C9F4 50726F677261*                db 'Program End', 0     
CA00 B01200C0                     call #DbgCR             
CA04                                                      
CA04 B01200C0                     call #DbgCR             
CA08                                                      
CA08 FF3F                         jmp $                   
CA0A                                                      
CA0A 2E4D656D6F72*Mem             db '.Memory.', 0        
CA13                                                      

 

Here is log file on PC side:

 

[30.9.2012 19:10:11]
[30.9.2012 19:10:14] Program Begin
[30.9.2012 19:10:14] R4:FFFF R5:FFFF R6:0002 R7:FFFF R8:245C R9:0000
[30.9.2012 19:10:14] R10:1234 R11:2345 R12:3456 R13:4567 R14:5678 R15:6789
[30.9.2012 19:10:14] PC:C970
[30.9.2012 19:10:14] 12345 + 23456 = 35801
[30.9.2012 19:10:14] SP:33F8 33F8: 4F 4E 20 53 54 41 43 4B ; ON STACK
[30.9.2012 19:10:14] SR:010C 0000000100001100
[30.9.2012 19:10:14] String
[30.9.2012 19:10:14] SR:010E 0000000100001110
[30.9.2012 19:10:14] CA0A: 2E 4D 65 6D 6F 72 79 2E ; .Memory.
[30.9.2012 19:10:14] Program End
[30.9.2012 19:10:14]

Link to post
Share on other sites

I made USB CDC (for MSP5xx) in assembler, and without this kind of debugging it will be mission impossible.

 

Here is log of enumeration process:

 

[30.9.2012 17:38:25] --- Reset USBIFG 80 ---

[30.9.2012 17:38:26] --- Reset USBIFG 80 ---

[30.9.2012 17:38:27] --- Reset USBIFG 80 ---

[30.9.2012 17:38:28] --- Setup USBIFG 04 USBSUBLK 2380: 80 06 00 01 00 00 40 00 ;

Link to post
Share on other sites

At the beginning of main source is something like this:

 

#define DBG_UART

...

#ifdef DBG_UART
	#include "dbg_uart.s43"
#endif

 

Before starting point in main program is debugging uart configuration (for MSP430F5510):

 

#ifdef DBG_UART
	bis.b #(BIT4 + BIT5), &P4SEL		; P4.4/P4.5 = USCI_A1 TXD/RXD

	bis.b #UCSWRST, &UCA1CTL1		; Put USCI state machine in reset

	bis.b #UCSSEL_2, &UCA1CTL1		; SMCLK

	; 25 MHz 460800 bps
	mov.b #036h, &UCA1BR0
	mov.b #000h, &UCA1BR1
	bis.b #(UCBRS_2 + UCBRF_0), &UCA1MCTL

	bic.b #UCSWRST, &UCA1CTL1		; Initialize USCI state machine
#endif

 

Later, debugging somewhere in main program:

 

#ifdef DBG_UART
	call #DbgRegs
	call #DbgCR
#endif

Link to post
Share on other sites

At the begining of "dbg_uart.s43" is uart selection:

 

;--------------------------------------------------------------------
; Uart used for debugging
;--------------------------------------------------------------------

UartIF		equ UCA1IFG

UartBuff	equ UCA1TXBUF

 

And simplest function is:

 

;--------------------------------------------------------------------
; DbgCR
; 10 13 -> Uart
;--------------------------------------------------------------------

DbgCR			push.w SR

DbgCR1		bit.b #UCTXIFG, &UartIF
			jnc DbgCR1
			mov.b #00Ah, &UartBuff

DbgCR2		bit.b #UCTXIFG, &UartIF
			jnc DbgCR2
			mov.b #00Dh, &UartBuff

			pop.w SR

			ret

 

Bytes are directly sent to uart, and all registers are unchanged (except debuging uart registers).

Link to post
Share on other sites

For all this (PC/uC uart connection) we need some kind of hardware, RS232 chip and USB/uart bridge (BTW, PL2303HXD is the best one, it works with any baud rate under 12 Mbps, for example: 123456 bps, 654321 bps...) if PC is without standard uart.

 

But why? MSP430F55x have USB, so debugging can go by USB (CDC)? Yes, but in this case things are become more complicated. If the main application also use USB, then composite device must be configured/enumerated with #ifdef statements. If release version (without debugging) is generated, it must be in original form without any debugging part.

Link to post
Share on other sites

At the beginning of main source is something like this:

 

#define DBG_USB

...

#ifdef DBG_USB
     #include "dbg_usb.s43"
#endif

 

PC logging application can't be open all the time (like with uart), because during flashing/restarting uC, virtual serial port (CDC used for debugging) will disappear. After uC is started, and enumeration is done (CDC created), uC must wait (or need to be triggered by) logging application on PC. It's enough just to send one byte to uC, for starting. End point 2 is used for debugging.

 

				#ifdef DBG_USB

WaitByteFromPC	bit.b #NAK, &USBOEPBCTX_2
				jnc WaitByteFromPC
				mov.b #0, &USBOEPBCTX_2

				#endif

 

Name of debugging functions is the same like with uart, so there is no need to change something in the main program (just change/adjust #ifdef statement) for switching between uart/USB debugging.

 

#ifdef DBG_USB
     call #DbgRegs
     call #DbgCR
#endif

Link to post
Share on other sites

At the begining of "dbg_usb.s43" is end point selection:

 

;--------------------------------------------------------------------
; Input Endpoint for debugging
;--------------------------------------------------------------------

IEBuf		equ USBIEPBBAX_2
IEBufCnt	equ USBIEPBCTX_2

IEBuf0		equ IEBuf + 0
IEBuf1		equ IEBuf + 1
IEBuf2		equ IEBuf + 2
IEBuf3		equ IEBuf + 3
IEBuf4		equ IEBuf + 4
IEBuf5		equ IEBuf + 5
IEBuf6		equ IEBuf + 6
IEBuf7		equ IEBuf + 7
IEBuf8		equ IEBuf + 8
IEBuf9		equ IEBuf + 9

 

And simplest function is:

 

;--------------------------------------------------------------------
; DbgCR
; 10 13 -> Ser
;--------------------------------------------------------------------

DbgCR		push.w SR

			mov.b #00Ah, &IEBuf0
			mov.b #00Dh, &IEBuf1

			mov.b #2, &IEBufCnt
DbgCR1		bit.b #NAK, &IEBufCnt
			jnc DbgCR1

			pop.w SR

			ret

 

Difference in sending data, is that with uart byte by byte is going out, and with USB all bytes can be stored first in buffer, and than sent together. Result of log application on PC side is the same in both (uart/USB) cases.

Link to post
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.

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.

×
×
  • Create New...