For me it is using a printf. I also have the ability to add colour to the string, for example. c_printf("\n\r[B][r]Hello World"); This will printf "Hello World in Bold Red.
What is you chosen method of debugging code.
I would always prefer to have a proper debugger.
But "printf" and blinking LEDs are also invaluable.
You can also learn a lot by looking at the current consumption - perhaps one could call that, "side-channel debugging" ... ?
EDIT
As well as blinking an LED, looking at an output port on a scope is good for higher-speed output.
And then there's a logic analyser on multiple pins.
See this thread for a whole load of debugging tips & tricks: https://www.avrfreaks.net/forum/...
EDIT 2
It's important to have all the right tools to hand ...
I prefer a real debugger! Of course, "real" varies with the device. And, I really want tools like a profiler and something with trace capability.
I "grew up" (in the embedded world) with an In-Circuit Emulator for 8051 that had these things and really miss profile and trace in the AVR.
Jim
When doing intensive debugging it's important to have the right size tool also.
In a recent project, with an STM32, I have used for debugging:
- the IDE debugging tool
- printf to a bluetooth serial port controlled by many #ifdef statements
- comparison with previous project's behaviour
- a 32 channel logic analyser
Another project, a processor emulator, has required
- the IDE debugging tool (GDB)
- printf
- debugging mechanisms in the emulator itself (so the GDB shows me the emulator line by line, and the emulator has a simple change-mode-to-trace when it hits a breakpoint in the code being emulated/executed
- a copy of Tiny Basic for 8080
All good fun...
Neil
When doing intensive debugging it's important to have the right size tool also.
I was thinking along the lines of:
I still have a file with a sack of tricks to debug ATMEGA8 (it was in ASM: use of flags, test var, test subs and macros). Each one sec selected data are printed to LCD.
That is the past, with JTAGICE mkII it is easy to debug the whole project on ATMEGA16, and then import tested to '8.
So, this device is only one that can not be debugged (and also programmed) with mkII.
I "grew up" (in the embedded world) with an In-Circuit Emulator for 8051 that had these things and really miss profile and trace in the AVR.
Same here. And before the '51 it was 8085s and 8086s. I do miss a proper ICE, being able to run through how your code got to where you stopped it is a great debugging technique. And being able to break on memory access, ah, those were the days.
Use a port pin and the scope, or maybe stuff a character out the uart.
For many programs, the error is a compile error, so you never even run the thing. If it compiles properly, it usually runs fine.
Using care in ensuring your values are within the allowed range & double-checking your logic helps avoid many potential flaws.
Many things can be found by inspection (why does the compressor come on when the switch is closed, instead of opened.)
If it compiles properly, it usually runs fine.
Hmmm ... not so sure about that one ... ?
I do miss ... being able to break on memory access
Atmel-ICE can do that on an AVR:
http://atmel-studio-doc.s3-websi...
I've done Linux kernel development work in the past where (well back 20 years ago anyway) your only recourse for debug was printk() but that's pretty torturous!
I also spent some years working with an NEC MIPS processor but sadly one that had just limited support through JTAG. It was running about 4MB of code in around about 100 threads in the Nucleus Plus operating system. It was not a protect mode operating system and something like a rogue pointer in one task was being written through and corrupting data in another task. The bugger of the thing was that while the CPU had JTAG address comparators to do execution breakpoints it didn't have comparator support for data breakpoints. Had it done so I might have found the bug in about 5 minutes. Just put a data breakpoint on the range of addresses known to be corrupted. In reality that is the best part of six months of my life I'll never be getting refunded.
So these days I simply would not choose to develop on a device that did not have the full gamut of On Chip Debug features. If it has a micro trace buffer that's a double tick in the box!
I myself have the JTAG-ICE for the ARM. Never used it. I like to just throw the data out the serial port. I'm not often working in the hardware and when I do it either works or I've done something wrong, "happens all the time".
I myself have the JTAG-ICE for the ARM.
Remember that you're posting in the AVR forum - so the majority of answers are naturally going to be in that context.
Never used it
You really are missing out on a whole lot of very valuable facilities there!
The amount of time I spend debugging has gone down significantly since I started using test driven development. When I do need to do some debugging, run logs, logic analyzer/oscilloscope observations, and a quick look at the relevant source code are typically enough to get a good handle on what is going on. I'll break out a debugger if those tools end up not being enough.
VOM measurements, Serial prints, LED's, Debugger, scope, and a Logic analyzer are all good, but my number one tool is a sharp pencil and notepad and writing down the details of operation as I observe them.....
Then spending some time to think about the code and relating the observations with what I have witnessed!
Jim
That reminds me of an old saying:
The best debugging tool is the one between your ears.
For me it is using a printf.
Sink Data Conversion | Data Visualizer Software User's Guide
QTools: QS Target Component | Application-Specific Data Elements
edit : re QS
[beginning of second paragraph]
The QP/Spy™ data protocol has many elements of the High Level Data Link Control (HDLC) protocol defined by the International Standards Organization (ISO).
USBee has an HDLC decoder :
[3/4 page]
Debugging is performed by viewing and analyzing the PacketPresenter output and relating it back to the logic analyzer waveforms and decoded bus traffic for the various types of busses. For example, you can see the PacketPresenter display of HDLC communication packets, and correlate that back to the raw byte stream that was decoded from the ASYNC bus, as well as the voltage versus time waveforms of the bus Tx and Rx lines.
I "grew up" (in the embedded world) with an In-Circuit Emulator for 8051
... and really miss profile and trace in the AVR.
RCA COS/MAC Microprocessor Trainers | Development System
[2/3 page for CDP18S008]
(in-circuit emulator)
Z8000 ICE was by Hewlett-Packard with a target pod and a "boat anchor".
User Instrumented Trace - Developer Help (MPLAB® REAL ICE™)
Troubleshooting real-time software issues using a logic analyzer - Embedded.com
edit : for parallel data, the above can be eased by
Protocol decoder:numbers_and_state - sigrok
...
Which can help identify machine states, or locations along a code path, or RTOS tasks.
...
[mid-page]
Options:
...
- Interpretation: unsigned, signed, fixpoint, fixsigned, ieee754, enum
...
- Enum to text map file: name of a Python or JSON file which maps integers to text strings
...
Using care in ensuring your values are within the allowed range ...
Many things can be found by inspection
Yesterday & today were spent discovering & debugging a random glitch in my continuous SPI output which relies on tight unbroken timing across a 105 byte frame. I sit in a spin loop feeding the hardware FIFO of an SPI peripheral (PIC32). The logic analyser clearly showed a break in transmission of a few milliseconds. Something was very very wrong to create a break that long.
Now for various reasons I cannot disable interrupts, but I knew no ISR took milliseconds.
I ended up writing some instrumentation code to time and test each ISR from entry to exit which executed a NOP instruction if my threshold were reached. A breakpoint on those NOPs quickly found the culprit.
So what was wrong:
I was inadvertently reading my group of ADC channels twice. The first pass went through just fine but the second pass found the DataReady status flags cleared (by the first read). It sat in another spin loop waiting for a DataReady flag that wasn't ever going to happen. That loop eventually times out and returns the previous conversion count.
I would always prefer to have a proper debugger.
I have been using a "debugger" since the "monitor programs" were created.
I sit in a spin loop feeding the hardware FIFO of an SPI peripheral (PIC32).
versus DMA?
A very good point. DMA lends itself to this sort of thing ideally.
I'm already using DMA for another purpose so didn't consider it, But on checking I find I have eight channels of DMA available. DOH !
That code was written according to the principles of lean. I wrote the simplest code I could think of and it worked very well so left it alone..(that is; up to the introduction of my bug, which I otherwise wouldn't have found)
... and it worked very well so left it alone.
If no concern about bounds then done (compute, memory, input/output, electrical power)
Someone on some projects report to the customer the state of the bounds (CPU utilization, memory usage, frame duration usage, electrical power or battery capacity usage or fuel used)
Using state machines and the like can be an edge against needing an all out debugger. When something is going wrong, I can usually tell which state it is in and very quickly figure out what I got backwards, left out, etc.
Usually the "bugs" I find on AVR are not raw coding mistakes at all, but a misunderstanding of something that needs done ...Oh, the datasheet says, the power driver only comes on when both EN pin AND SYNC pins are high (rather than just EN).
On the other hand, I did have a pic app years ago that had some very twisted & failing logic...the debugger really stepped in to help (the old "that can't be happening syndrome" )
Many many years ago (like 1986) I was using a debugger which proved to be a mistake. The monitor debugger inserted an escape hook into ram code, which unfortunately fixed the issue I was having. So tracing with the debugger indicated the fault was not happening and was impossible. After 8 hours I realized the debugger was "fixing " the problem (it prevented an overflow, which prevented a cascade IRQ failure). The issue was a single missing terminator char in some string processing.
So people are using a debugger for software bugs ONLY?? I debug my brand new PCBs with the ICE, no or very little code required.
I have noticed that for some people AVRFreaks is their best debugging resource.
debugging mechanisms in the emulator itself ...
Reason :
Protocol | Protocol decoder:z80 - sigrok
The data bus lines plus the control signals /M1, /RD and /WR are sufficient to display full disassembly.
...
I have noticed that for some people AVRFreaks is their best debugging resource.
Seems that way on a lot of forums, I guess it's easier to ask how to do something then researching and or trying it yourself.
I don't think some people could survive without; ^c and ^v
barnacle wrote:Instruction stream?debugging mechanisms in the emulator itself ...Reason :
Protocol | Protocol decoder:z80 - sigrok
The data bus lines plus the control signals /M1, /RD and /WR are sufficient to display full disassembly.
...
Indeed they are, but as yet there *are* no external control lines, and won't be until I start sticking 74hc logic together.
In this case, the emulator can run full speed until it reaches a breakpoint, and at that point drop into a single-step trace mode with each instruction disassembled and with a key input required to get the next instruction (or the trace can run all the time and still have the breakpoint) so that's debugging the code I'm trying to run, in an effort to find instructions which are still incorrect. But it's tricky because the input and output uses the same channels - you may recall some time ago I was trying to get a second terminal window working from a linux console to differentiate between emulator i/o and executable i/o.
And then there is the normal breakpoint mechanism in the IDE so I can debug the broken instruction. It turns out that emulating an 8-bit micro in C is not a trivial activity... Svofksi, late of this parish, has done some fine work on the subject.
It's not quite working yet, but it's a low priority issue at the moment.
Neil
Using state machines and the like can be an edge against needing an all out debugger. When something is going wrong, I can usually tell which state it is in and very quickly figure out what I got backwards, left out, etc.
Usually the "bugs" I find on AVR are not raw coding mistakes at all, but a misunderstanding of something that needs done ...Oh, the datasheet says, the power driver only comes on when both EN pin AND SYNC pins are high (rather than just EN).
Totally agree. To follow states, you just need to send a few pulses to an I/O port and record with a logic analyzer. Sometimes, also serial data if you need to see the state of some variable. I rarely need to use a "proper" debugger.
As avrcandies says, the trickiest bugs are documentation misunderstandings, I can totally relate ...Ah, so when I write a partial address to the NVM controler via UPDI, it not zero extended, as I assumed. Duh...
Using state machines
... was one of quality of software checks /in my former firm/. State machine = quality++.
I typically use an LED and an O'scope.
Many projects have a small display for the User Interface, so it is easy to display variables, otherwise I can dump that out a SW USART to a small terminal or a PC terminal.
I also find a few 4-letter words sprinkled throughout the debug session are helpful.
Well, not really helpful for the debugging itself, but helpful for letting off steam and keeping my BP under control.
There is usually a short stream of them right after I find the root cause of the problem under investigation!
Then I can go days at a time without uttering another one!
JC
It can be fun trying to debug a system which requires a response within a short time to avoid the target turning off the messaging...
- data is in a short packet including three bytes of metadata, zero to twelve bytes of data, and an EOT byte
- every byte expects to see a complemented echo of itself, unless it's the EOT which requires nothing
- it's a single wire bus so every byte sent is immediately received by the sender before the echo is seen
A logic analyser and lots of printf was the only way... any use of the IDE breakpoint immediately turned off the far end. It would have helped if the language used to describe this behaviour (I have data sheets in Italian and English) was consistent and indeed correct...
Neil
I should add that, in some cases, debugger is inadequate because it requires halting things to tell what the internal state of the MCU is. Often, timing is so tight that serial data will change the functionality of the device being tested.
In that case, with AVRs anyway, another way is to devote several GPIO pins for debugging. I'll set one pin when it enters a subroutine being checked and clear said pin on exit. This can be done in a very small number of clock cycles; usually with minimal impact on the system. Often, several of these need to be used. Logic analyzer then shows how long code execution takes, what the timing is between entries and exits of a routine and between exit of one routine and entry to another. I can then tell if routines are being called when I expect and take the expected time.
This method is especially helpful with ISRs as that can reveal when various events occur within the system.
In the systems I work with, things are usually too brief to make an LED useful.
Jim
...with AVRs anyway, another way is to devote several GPIO pins for debugging...
Ditto.
//and now some debug pins #define DEBUG1 PORTC.1 #define DEBUG2 PORTC.2 #define DEBUG3 PORTC.3
This method is especially helpful with ISRs as that can reveal when various events occur within the system.
OH YEAH!!!
In the systems I work with, things are usually too brief to make an LED useful.
Toggle the pin each entry to the routine (to see it being called), then usually much easier to see than a narrow "spike".
Remember the good old days of bondout chip emulators? $9000 for an 8096 microcontroller emulator...and we thought it was a reasonable deal!
I remember finding out (the hard way) it did not emulate wait states properly.....now which floppy is that code on??
In that case, with AVRs anyway, another way is to devote several GPIO pins for debugging.
Features | UPDI | AVR® DB Family
...
Debugging:
- Memory-mapped access to device address space (NVM, RAM, I/O)
...
- Support for advanced OCD features
- Run-time readout of the CPU Program Counter (PC), Stack Pointer (SP) and Status Register (SREG) for code profiling
- Detection and signalization of the Break/Stop condition in the CPU
- Program flow control for Run, Stop and Reset debug instructions
- Nonintrusive run-time chip monitoring without accessing the system registers
...
A BREAK instruction in a temporary assertion handler may aid troubleshooting.
UPDI Instruction Set | AVR® DB Family
AVR - Calibration & Daq toolchain? | AVR Freaks
edit :
ka7ehk wrote:...with AVRs anyway, another way is to devote several GPIO pins for debugging...
Ditto.
//and now some debug pins #define DEBUG1 PORTC.1 #define DEBUG2 PORTC.2 #define DEBUG3 PORTC.3
Oh yes. If you take one of my pet feeders to bits, you'll find eight pads on the PCB close to the processor, whose sole purpose is to allow easier soldering to the port pins for a logic analyser or scope. When the code was finished, nothing was talking to them... but I saw no reason to remove the pads :)
Neil
PDI or UPDI is in parallel with the CPU (AVRxm, AVRxt; low pin count)
Yes, even using just the publicly available UPDI programming instructions (i.e. the P in UPDI) it's possible to read/write volatile memory and I/O registers without disturbing the CPU unit.
It's not possible to set breakpoints, step by step instructions and other advanced stuff, because those need debug interface info that Microchip doesn't disclose (i.e., the D in UPDI). But the P is quite powerful already
In principle it would be possible to do a lot of debugging using just a USB/serial adapter connected to the UPDI interface. You can at least inspect memory, and therefore, variables (if you know their memory addresses).
It's not possible to set breakpoints,