All of us who do some programming know that logging is a time-tested way to output messages about the internal state of our code. With varying degrees of adjustable granularity, these messages allow us to keep track of not only the state of the application, but also its overall health. When things do end up going FUBAR, these log messages are usually the first thing we look at as a software equivalent of a Flight Data Recorder in an airplane.
Spending some time and care in not only designing the logging system, but also in deciding what should be logged and at what level, can make our future self appreciate life a lot more. We’re all familiar with the practice of ‘printf-debugging’, where logging is added as part of the usual post-crash autopsy as one tries to figure out what exactly went wrong. It’s one way of doing it, and eventually it works, but we can do much better.
People are lazy, and you’re only going to stick to good logging practices if they are at least as easy if not easier than sprinkling printf() statement throughout the code. Yet at the same time we want to be able to handle things like log levels and newlines without too much extra typing. The most successful logging libraries are built with this
Continue reading “Beyond Printf(): Better Logging Practices For Faster Debugging”
Hackaday editors Mike Szczys and Elliot Williams fan through a fantastic week of hacking. Most laser cutters try to go bigger, but there’s a minuscule one that shows off a raft of exotic components you’ll want in your bag of tricks. Speaking of tricks, this CNC scroll saw has kinematics the likes of which we’ve never seen before — worth a look just for the dance of polar v. Cartesian elements. We’ve been abusing
printf() for decades, but it’s possible to run arbitrary operations just by calling this Turing-complete function. We wrap the week up with odes to low-cost laptops and precision measuring.
Direct download (~65 MB)
Places to follow Hackaday podcasts:
Continue reading “Hackaday Podcast 071: Measuring Micrometers, The Goldilocks Fit, Little Linear Motors, And 8-bit Games On ESP32”
[Nicholas Carlini] programmed a C implementation of two-player Tic Tac Toe, and he did it in a single call to
printf(). The arguments for that single function call get mind-bendingly complex, so it may come as no surprise that it was written for The International Obfuscated C Code Contest (IOCCC).
Most of us are aware that
printf() is one of those functions that is considerably more complex under the hood, and capable of far more, than it may appear to be. But did you know that it is capable of Turing-complete computation?
[Nicholas] clearly steps through the theory, so give it a read. In short, a maze of arguments handles the logic of the game while an embedded
scanf() reads user input, and printing the game board is always preceded by an escape code to clear the screen.
[Nicholas] is certainly no stranger to in-depth understandings; we’ve seen his work before in demonstrating how to fool speech recognition with hidden commands, including a powerful example showing how two virtually identical-sounding audio files transcribe entirely differently.
printf is something [StorePeter] has always found super handy, and as a result he’s always been interested in tweaking the process for improvements. This kind of debugging usually has microcontrollers sending messages over a serial port, but in embedded development there isn’t always a hardware UART, or it might already be in use. His preferred method of avoiding those problems is to use a USB to Serial adapter and bit-bang the serial on the microcontroller side. It was during this process that it occurred to [StorePeter] that there was a lot of streamlining he could be doing, and thanks to serial terminal programs that support arbitrary baud rates, he’s reliably sending debug messages over serial at 5.3 Mbit/sec, or 5333333 Baud. His code is available for download from his site, and works perfectly in the Arduino IDE.
The whole thing consists of some simple, easily ported code to implement a bare minimum bit-banged serial communication. This is output only, no feedback, and timing consists of just sending bits as quickly as the CPU can handle, leaving it up to the USB Serial adapter and rest of the world to handle whatever that speed turns out to be. On a 16 MHz AVR, transmitting one bit can be done in three instructions, which comes out to about 5333333 baud or roughly 5.3 Mbit/sec. Set a terminal program to 5333333 baud, and you can get a “Hello world” in about 20 microseconds compared to 1 millisecond at 115200 baud.
He’s got additional tips on using serial print debugging as a process, and he’s done a followup where he stress-tests the reliability of a 5.3 MBit/sec serial stream from an ATMega2560 at 16 MHz in his 3D printer, and found no missed packets. That certainly covers using
printf as a debugger, so how about a method of using the debugger as printf?
Anyone who has worked with a microcontroller is familiar with using
printf as a makeshift debugger. This method is called tracing and it comes with the limitation that it uses up a UART peripheral. Believe it or not, there are 8051 variants out there that come with only one serial block and you are out of luck if your application needs it to communicate with another device.
[Jay Carlson] has a method by which he can piggyback these trace messages over an on-chip debugger. Though the newer ARM Cortex-M software debugger already has this facility but [Jay Carlson]’s hack is designed to work with the SiLabs EFM8 controllers. The idea is to write these debug messages to a predefined location in the RAM which the debugger can access anyway. His application polls a certain area of the memory and when it finds valid information, it reads the data and spits it out into a dedicated window. It’s using the debugger as a makeshift
[Jay Carlson] used slab8051.dll interface and put together a C# program and GUI that works alongside the SiLab’s IDE. The code is available on GitHub for you to check out if you are working the EFM8 and need a helping hand. The idea is quite simple and can be ported to other controllers in a multitude of ways like the MSP430 perhaps. For those of you who like the Teensy, you might want to take a look at adding debugger support to the Teensy 3.5/3.6.
[Brandon] is taking us further down the rabbit hole by demonstrating how to use newlib with the TI Stellaris Launchpad. This is a nice continuation of the framework he built with his post about using GCC with ARM hardware. But it is most certainly one level of complexity deeper than that initial article.
Using newlib instead of glibc offers the option of compiling C code that includes system calls common when coding for computers but which are rare in embedded systems. Using something like printf is generally avoided because of the overhead associated with it. But these processors are getting so fast and have so much RAM that it may be useful in certain cases. We briefly thought about implementing malloc for creating a linked list when working on our STM32 snake game. [Brandon’s] work here makes the use of that command possible.
The process starts by adding labels for the beginning and end of the stack/heap. This makes it possible for functions to allocate memory. After taking care of the linker script changes you must implement a few system call functions like _sbrk.
First off, if you’re looking at that title and thinking it’s flame-bait, please hold off. What [Ihsan Kehribar] is working with is another way to get some feedback for what’s going on with your Arduino project. Or really any AVR project that uses an ISP connection. He’s added text output for AVR programs similar to the printf function used for a lot of non-embedded C development.
So, we’d bet you’re asking yourself why he’s not just using outright debugging? The AVR line supports many different types of it. But that can be complicated, and usually requires a proper programmer. If you just want to watch to see what values are changing, and when functions are being executed, this isn’t a bad solution. He uses the computer to continually poll the chip. Whenever the sketch calls the his print library it answers back with the payload to be displayed in the terminal. The overhead shouldn’t be too high, and if you’re smart about it this can be flagged as a debug option at the top of the program file.