GCC 12 AVR array subscript 0 is outside array bounds

Where I describe a new error caused by a bug in GCC 12 as it relates to the AVR microcontrollers.

Sources:#

Description#

While debugging a setup script, I ran across this error on my Linux system, however, it didn’t show up on my macOS or Windows computers.

$ make flash
avr-gcc -Os -mcall-prologues -g3 -std=gnu99 -Wall -Werror -Wundef -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums  -ffunction-sections -fdata-sections  -DF_CPU=16000000UL   -DBAUD=9600UL -DSOFT_RESET=0 -I.  -I../../Library -mmcu=atmega328p -c -o main.o main.c
main.c: In function 'main':
main.c:33:9: error: array subscript 0 is outside array bounds of 'volatile uint8_t[0]' {aka 'volatile unsigned char[]'} [-Werror=array-bounds]
   33 |   PORTB &= ~_BV(PORTB5);
      |         ^~
cc1: all warnings being treated as errors
make: *** [<builtin>: main.o] Error 1
$

It does seem rather odd as 0 is certainly not “outside array bounds”, therefor I had no idea as to how to remediate it.

Using Makefiles to Automate Development

Where I demonstrate how to use make and makefiles to automate your build process.

Update#

While this entry accurately describes how to use a Makefile, the approach has changed significantly. See Developing in C for the ATmega328P: Make, Makefile and env.make for the latest information.

Automate using a Makefile#

We’ll use the Makefile from Elliot William’s book, he has in the folder setupProject. This Makefile is comprehensive and delivers an Arduino IDE type of simplicity with significantly increased speed. I’ve made some changes to it to make it easier to switch between different types of systems. Here is the file:

Comparing Board and Language Speeds

Where I compare the execution speeds of different combinations of boards and languages. I will continue to update this post with other languages and processor combinations.

Table for the impatient#

ucontroller/Speed(MHz) Method* frequency Language
ATSAMD21/48Mhz Integral .6kHz CircuitPython
ATSAMD21/48Mhz Integral function .7kHz CircuitPython
ATSAMD21/48Mhz Library .7kHz CircuitPython
RP2040/133Mhz Integral function 1.0kHz CircuitPython
RP2040/133Mhz Library 1.44kHz CircuitPython
ATmega328/16MHz struct/function pointer 6.1kHz Arduino C++
ATmega328/16MHz words in an infinite loop 27KHz FlashForth
ATmega328/16MHz struct/function pointer 55kHz C
ATmega328/16MHz struct/function pointer 56kHz Arduino C++ w/ native toggle
ATmega328/16MHz Assembly language toggle 108kHz FlashForth
ATmega328/16MHz Assembly language toggle inlined 444kHz FlashForth
RP2040/133Mhz struct/function pointer 578.7kHz C
RP2040/133Mhz words in an infinite loop 2.841 MHz Mecrisp Forth
*See text for an explanation of method.

Introduction#

While writing about CircuitPython and the FIDI board, I was curious as to the execution speed of CircuitPython on a extremely powerful (relative to the AVR ATmega328) ARM M0+ microcontroller. The M0+ is a modern RISC 32-bit processor with a considerable amount of memory, while the ATmega is 20 year old RISC 8-bit processor with a limited amount of memory. That said, one can’t run CircuitPython on ATmega processors, one must use C or Forth.

Git: Beginning to Use It (ESP32)

Where I discuss what to do once you’ve downloaded a repository from Github.

Introduction#

I’ve advocated using the AVR_C (among others) repository to learn how to use C instead of the Arduino “C++” language. (I write C++ in quotes as while the language used is C++, there are some extensions which some people assume are part of the language, causing more confusion.) In this post, I want to start a short series on using Git as it is extremely helpful, once you begin to develop code. And it becomes mandatory, once you begin using someone’s git repository.

Developing in C for the ATmega328: PRNG, FSM and more!

Where I discuss psuedo-random number generators (PRNG), finite state machines (FSM) and other software topics.

Sources#

Mersenne Twister#

Introduction#

This entry covers several topics, random number generation, finite state machines and native programming. All of the code discussed is in AVR_C on GitHub. The objective is to continue to expand on the development of a standard C library for the Arduino Uno and other ATmega328-based microcontroller boards.

Hardware Debug: Exploring the ATmega328PB Xplained Mini

Where I demonstrate how to use the ATmega328PB Xplained Mini from Microchip to understand how to program in Standard C.

Sources#

ATmega328PB XPLAINED Mini Board Image

ATmega328PB XPLAINED Mini Board Image

Introduction#

Due to its size and shape, I’m conflicted on this board. For the price, its fantastic! Why the conflicting thoughts? The good is that this board has an embedded hardware debugger which solves the controller board/debugger tool issue and it only costs $12! The bad is the board is physically large without adding extra value, thus it requires two breadboards to easily interface. All this said, I would recommend this board over any other, if you plan to do any hardware debugging.

Developing in C for the ATmega328: Hints on Using Bloom and avr-gdb

Where I provide hints on using avr-gdb and bloom to debug code on the ATmega328P.

Sources#

Hints#

  1. Check the version number on avr-gdb as of December 2021, it is 11.1. On Ubuntu, the latest version is 8.1 from 2018 which had quite a few bugs. See notes on this page as to how to ensure you have the latest version.
  2. Be sure to use target remote:1442 in gdb, if you are having connection issues.
  3. If you find your self executing a lengthy command quite a bit (such as “monitor reset init”), use “define” to create a shorter command for it. If you put it into the .gdbinit file (as I have), it will remember from session to session.
  4. gdb can be incredibly easy to use. Norman Matloff’s tutorial is great for illustrating the commands needed. I recommend reading and practicing with it, its well worth it!
  5. Another great tutorial is Beej’s Quick Guide to GDB, particularly for the gdb –tui guidance.
  6. Start with using gdb to replace printf statements. Run code, have it stop by using a “breakpoint function name” or “breakpoint line number”, then use “print” or “display” to get the values of variables. This will work the same as inserting print statements, however, it doesn’t affect your code.
  7. It took me less time to learn gdb, and write these two tutorials than the time I spent attempting to debug Visual Studio Code. Your mileage may vary, however, a simple gdb/code editor setup is fast and easy to learn and use.
  8. If your code ends, you will see “exit(status=0)….”. To restart the program, simply issue a monitor reset, which will reset the processor. Press “c” and the program will begin running again.
  9. gdb operates in at least two modes:
    • command, indicated by (gdb) prompt. This is where you will enter all of the commands to interact with gdb
    • execution, indicated by a lack of a (gdb) prompt. This means the program is running and hitting a breakpoint or watchpoint will return you back to command mode. Or you can hit Ctrl-C which will interrupt the process and put into command mode.
  10. Enter the command layout src or start by using gdb –tui and the window will divide into two horizontal windows. The top window will show 20 lines of source and the bottom window will continue to be the command window. This is a great way to view a breakpoint. For example, set a breakpoint on a function name, then “n(ext)” through the code to view execution. Once you have entered “n”, you can simply hit the return key and it will advance using the next command.
  11. If in tui, use info win to show the number of lines per window then use wh [window name] n to change the number of lines to n. For example, use wh src 40 to change the window showing the source code to 40 lines. Use fs [window name] to change the window focus. Typically, it is in the source (src) window, and to change the focus to the command window, use fs cmd.
  12. Note found elsewhere, I’ll link to it when I find it: “remember to use -g only for the image you pass to gdb, not the firmware you load into the device (if it can grok elf). Also another very critical prerequisite for C programs is -O0 (which is usually default). But if you use -Os or something, you can get very unpredictable debugging results. This btw. makes debugging some code on avrs for example almost impossible, as they often rely on -Os to fit the image in there. But.. it is very possible and comfy to debug simple optimized C programs in assembly, if you know roughly what to expect. Use objdump -dS on the optimized .elf file with debugging info and you’ll roughly see what assembly code was produced for what C code.”

Developing in C for the ATmega328: Examples of Bloom with gdb to Debug

Where I show some examples as to how to use Bloom and avr-gdb to debug code on the ATmega328P.

Sources#

Introduction#

In a previous entry, I discussed how to setup Bloom and gdb using an MPLAB Snap. Given the power of Bloom’s feature called Insight, I want to present some examples of how to use Insight to debug the AVR8 family of microcontrollers.

Developing in C for the ATmega328: Setup Bloom and gdb for Hardware Debug

Where I illustrate how to setup using avr-gdb to debug code on the ATmega328P and replacing avarice with Bloom and the Atmel Dragon with the Microchip Snap.

Sources#

Introduction#

In a previous entry, I discussed using an Atmel Dragon (no longer available), avarice (an older application managing communication between the Dragon and gdb), and avr-gdb to debug a program running on a Uno (ATmega328P). My goal has been to find a suitable board which replaces the Dragon, however, at a reasonable (<$50) price point. The board would need to work with avarice or I need to find a replacement for avarice as well. This new combination needs to provide both the ability to debug as well as program the 328P.

Hardware Debug: Using gdb to Debug

Where I illustrate debugging code for the ATmega328P using the Atmel Dragon, avr-gdb and avarice. This is a overview of a hardware debugger approach, for a more detailed view on Linux using Bloom, follow this guide.

Update (Feb 2022): I also recommend reviewing this tutorial as it is quite detailed and offers another method for using gdb. While it does use PlatformIO and VS Code, I believe its helpful to review the author’s approach to using gdb.