0
votes

I'm starting an embedded AVR project in C with QtCreator.

I believe I have everything setup and working correctly; I can write code that #include's headers from avr-libc, build with a custom makefile, and the binary is automatically flashed onto the chip for me. Unfortunately, even though my code compiles without any warnings from avr-gcc, QtCreator's ClangCodeModel plugin does not recognize a subset of the #define'd port and register names--it claims that there are errors, and autocompletion does not work.


I think I've identified the problem:

The boilerplate #include in avr projects is #include <avr/io.h>.    io.h itself #include's a number of other headers unconditionally, no-matter-what, such as headers that define register names common to all AVR devices. And code completion does work correctly with the names defined in those headers. However, it also conditionally includes one other header based on which specific AVR device you are targetting. There are many hundreds of AVR devices out there, each one having its own header file that defines port and register names. io.h determines which one to include like this:

#if defined (__AVR_AT94K__)
#  include <avr/ioat94k.h>
#elif defined (__AVR_AT43USB320__)
#  include <avr/io43u32x.h>
#elif defined (__AVR_AT43USB355__)
#  include <avr/io43u35x.h>
#elif defined (__AVR_AT76C711__)
#  include <avr/io76c711.h>
.
.
.

and so on. I reason that the correct header must actually be included since compiling throws no errors, even though ClangCodeModel does show error tags. By that I mean, I can write code that references a device-specific register name and compile without problems, but ClangCodeModel does not recognize that register name.

EDIT: Note that if I actually directly #include <avr/iom328p.h> at the top of main.c, ClangCodeModel parses the header just fine and autocompletion works. Unfortunately, I can't actually leave it like that. From <avr/io.h>:

This header file includes the apropriate IO definitions for the device that has been specified by the -mmcu= compiler command-line switch. This is done by diverting to the appropriate file <avr/ioXXXX.h> which should never be included directly. Some register names common to all AVR devices are defined directly within <avr/common.h>, which is included in <avr/io.h>, but most of the details come from the respective include file.

and from <avr/iom328p.h>:

/* This file should only be included from <avr/io.h>, never directly. */

From the ClangCodeModel documentation:

The feedback you get through warning and error markers is the same as a compiler will give you, not an incomplete set or a close approximation, as when using the built-in Qt Creator code model.

That doesn't seem to be the case. To me, that claim implies ClangCodeModel would go ahead and evaluate the #if defined (__MY_AVR__), and parse the correct device-specific header, which isn't happening here.

It is essential to me that code completion works since embedded projects require typing esoteric register and port name macros all day long.

What am I missing?


makefile, and the makefile referenced at the bottom include.

The general <avr/io.h>.

The device-specific header <avr/iom328p.h> which has all the names I need, and ClangCodeModel is failing to parse.

Contents of QtCreator's MyProjectName.includes (I added these lines manually).

1

1 Answers

0
votes

You should add

#define __AVR_ATmega328__

to your MyProjectName.config file. QtCreator's code model cannot get all compiler defines, because your Makefile is not generated by qmake, cmake, or qbs.