This is a tag page.

Prevent ATMega328P crashes with a stack monitor

John Peck
Published

The ATmega328P is used on the Arduino UNO, the Nano, and on many other mass-produced microcontroller boards. But it has only 2048 bytes of SRAM, which is shared between the stack and storage for things like local variables. Bizarre behavior can happen if the SRAM needed for variable storage overlaps that needed for the stack, but it's hard to understand how much space these variables will use until the program is actually running. This is where Michael McTernan's stack monitor is useful.

The stack monitor "paints" SRAM storage registers with a magic value before application code executes. You can then check for unused stack memory during execution by counting up these magic values. Here's some debug output from my Diamond firmware running on the EVL-510:

debug trace

The unused SRAM is initially 200 bytes, but falls to 179 after turning the volume knob. Changing the volume calls a few functions that allocate local variables in SRAM. These get cleaned up when the function exits, but the stack monitor can see that the memory was used. The idea is to exercise as much of the system as you can and then make sure you still have some unused memory.

I call the function with a scheduler made from avr-simple-scheduler. The code block below shows adding the stack reporting function to the scheduler with a period of 5s. I could have made this even longer, since I only need the report to run after I've excercised as much as I can.

if (strcmp( LOG_LEVEL, "debug" ) == 0) {
    // Start the task to monitor free memory
    OS_TaskCreate(&system_report_stack_free, 5000, BLOCKED);
}

Findcoms: Find the COM port of Arduinos and use it in a makefile

John Peck
Published

My AVR-based Arduino workflow is automated by GNU makefiles, which call avrdude to interact with the hardware. It's nice to also have the makefile find the Virtual COM Port (VCP) assigned to the hardware programmer or USB/UART device. Findcoms is a Tcl script that finds the device and writes the VCP name to a file. You can then access this file from your makefile to get the name to avrdude.

From the command line

Findcoms uses a -d parameter to decide which device to detect. Use -d? to get a list of available d parameters.

list of d params

Use the pololu_isp parameter to detect the Pololu USB AVR Programmer v2 — a very nice device that can program the flash on an ATmega2560.

pololu detection

Take a look at the GitLab repo for more details.

Use avrdude and the AVR Dragon to restore the bootloader on the XMEGA-A3BU Xplained board

John Peck
Published , updated

Use the AVR Dragon -- not the JTAGICE3 on Linux

I was initially excited to use my new JTAGICE3 programmer with my XMEGA board, but I couldn't get it to work with avrdude on Linux. I don't want to switch to Windows just for this project, so I hooked up the AVR Dragon as shown below.

XMEGA connections

Upgrade the Dragon's firmware

My original AVR Dragon had firmware that didn't support XMEGA programming. Updating this required booting into Windows and starting Atmel Studio. I ended up upgrading the firmware to version 7.39.

Set some udev rules

Linux Mint puts my user in the plugdev group -- not the dialout group. But udev seems to want to put everything in the dialout group, and it somehow isn't enough to just add my user to that group. In the end, I wrote some udev rules to support the Dragon, the Common Device Class Abstract Control Model (CDC-ACM) protocol, and the Atmel bootloader protocol:

# Support the AVR Dragon
ATTR{idVendor}=="03eb", ATTRS{idProduct}=="2107", MODE="660", GROUP="plugdev"

# Support the CDC virtual COM port provided by the demo application
ATTRS{product}=="CDC Virtual Com", SYMLINK+="xmega", GROUP="plugdev"

# The stock bootloader shows up as idVendor 0x03eb, idProduct 0x2fe2
ATTR{idVendor}=="03eb", ATTRS{idProduct}=="2fe2", MODE="660", GROUP="plugdev"

Get the bootloader image

Some Google searches for the original bootloader image eventually let me to this page, and this link for the Xmega bootloader images.

Flash the image with avrdude

avrdude -p atxmega256a3bu -c dragon_jtag -P usb -e -U flash:w:atmel_bootloader/binary/atxmega256a3bu_104.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e9843
avrdude: erasing chip
avrdude: reading input file "atmel_bootloader/binary/atxmega256a3bu_104.hex"
avrdude: input file atmel_bootloader/binary/atxmega256a3bu_104.hex auto detected as Intel Hex
avrdude: writing flash (267770 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 267770 bytes of flash written
avrdude: verifying flash memory against atmel_bootloader/binary/atxmega256a3bu_104.hex:
avrdude: load data flash data from input file atmel_bootloader/binary/atxmega256a3bu_104.hex:
avrdude: input file atmel_bootloader/binary/atxmega256a3bu_104.hex auto detected as Intel Hex
avrdude: input file atmel_bootloader/binary/atxmega256a3bu_104.hex contains 267770 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 267770 bytes of flash verified

avrdude done.  Thank you.

...and you're welcome.

Boot into the bootloader with the magic button

Remove the JTAG cable, remove the USB cable, hold down the SW0 button, then plug in the USB cable. You'll now be in the bootloader.

Test it -- load the XMEGA A3BU demo

You can download the XMEGA demo here. You can flash the image using the dfu-programmer utility:

dfu-programmer atxmega256a3bu flash sample_hexes/XMEGA_A3BU_XPLAINED_DEMO1.hex
Validating...
35062 bytes used (13.81%)

...and you'll need one final power cycle to boot into the application code when dfu-programmer finishes.

Check out the grinloader project for more details

My grinloader project has a makefile that automates the steps I just described. It also archives the bootloader hexes and the demo application.