Introduction
It's no secret that microcontrollers of the AVR family are firmly established in the practice of home crafts. In addition, for several years, there has been a massive (
on the verge of an epidemic) enthusiasm for debugging Arduino boards built on the basis of the same AVR. I will not judge whether this is good or bad, because there are more than enough articles on this topic on the resource. I want to protect my reader from the debate on "what is Arduino and good or bad." The article is not about that.
Sooner or later, for any “arduinschik” (assuming that he wants to reach a higher professional level), the moment comes when within the framework of the Arduino platform it becomes cramped and he begins to think about what actually happens under the hood. And the answers to all his questions already exist, for example, in the form of the remarkable course
“AVR. Training course " from the respected
DIHALT . If you are a user of Windows OS, then you will not have a shortage of development tools, a free Atmel Studio is enough to cover all software development issues for AVR MC.
Although I am a team leader in the software development team of the application level, the issues of “hardware” which in our office is being done on the basis of AVR have recently become very interesting for me. There was a desire to understand well all aspects of software development for MK. And since I am a staunch supporter of using Linux kernel-based OS in development, I was interested in the question, how is it in Linux: is it possible to / is it possible to write and debug software, stitch it into a crystal with the same (or approximately the same) level of convenience which is available to us in Windows. Those who are also interested in this question, and in particular those to whom the topic of the post seems far-fetched, I invite you to the cat.
With regard to development in C / C ++, there is no particular problem with Linux, in view of the general orientation of this system to the use of this language and the availability of a decent set of tools. However, the same
DIHALT , for example, asserts that programming for MK is inseparable from knowledge of assembler, which I agree with, in view of the consistency of its theses set forth in the “Training Course” and its own (albeit small) experience of system development under x86.
')
Guided by the thesis that we cannot get away from ASMA AVR and we are sitting under Linux, we will try to look at how to write and debug programs. I use the Arch Linux distribution, so in my story I will rely on its ecosystem.
1. Choose a compiler
At once I will say that I will not offer a bunch of Atmel Studio + wine. I do not like wine (although I use it as needed). Let us dwell on the native means, first of all, compilers, the review of which in the network and the personal picks gave access to the triumvirate of
gavrasm ,
avra and
avr-as . The choice was made according to two conflicting criteria: support for the syntax of the proposed Atmel and the ability to debug the firmware step by step in the emulator. The latter is more important to me, and in the plane of the course @DIHAL is so straightforwardly necessary for understanding the process of the microcontroller. The commonality of syntax with Atmel compilers gives, again from my point of view, only the ability to easily adapt Atmel Studio projects to work in Linux, which is a very dubious advantage, because the same avr-as also exists under Windows. I offer the reader an overview of the listed trinity.
gavrasm and avra
Support Atmel syntax. The first
was found in the AUR and is set by the command
$ yaourt -S gavrasm
The second is also
available in AUR
$ yaourt -S avra
View Program
test.S
;---- .device atmega16 ;---- .dseg ;---- .cseg .org 0x0000 ldi r16, 10 M1: inc r16 rjmp M1 ;---- EEPROM .eseg
It is compiled by both compilers at once in * .hex and the result of the work looks approximately the same. In order not to disturb the noble Dons with long footcloths, I put the compilation results under the spoilers
Exhaust gavrasm $ gavrasm test.S +------------------------------------------------------------+ | gavrasm gerd's AVR assembler Version 3.5 (C)2015 by DG4FAC | +------------------------------------------------------------+ Compiling Source file: test.S ------- Pass: 1 14 lines done. Pass 1 ok. ------- Pass: 2 14 lines done. 3 words code, 0 words constants, total=3 = 0.0% No warnings! Compilation completed, no errors. Bye, bye ... $ ls -l 12 -rw-rw----+ 1 maisvendoo users 52 29 15:46 test.hex -rw-rw----+ 1 maisvendoo users 741 29 15:46 test.lst -rw-rw----+ 1 maisvendoo users 92 29 15:46 test.S
The contents of the firmware hex file
:020000020000FC
:060000000AE00395FECFAB
:00000001FF
Listing file contents
gavrasm Gerd's AVR assembler version 3.5 (C)2015 by DG4FAC
----------------------------------------------------------
Source file: test.S
Hex file: test.hex
Eeprom file: test.eep
Compiled: 29.07.2017, 15:46:38
Pass: 2
1: .device atmega16
2:
3: .dseg
4:
5: .cseg
6: .org 0x0000
7:
8: 000000 E00A ldi r16, 10
9: M1:
10: 000001 9503 inc r16
11: 000002 CFFE rjmp M1
12:
13: .eseg
14:
Program : 3 words.
Constants : 0 words.
Total program memory: 3 words.
Eeprom space : 0 bytes.
Data segment : 0 bytes.
Compilation completed, no errors.
Compilation endet 29.07.2017, 15:46:38
Exhaust avra $ avra -l test.lst test.S AVRA: advanced AVR macro assembler Version 1.3.0 Build 1 (8 May 2010) Copyright (C) 1998-2010. Check out README file for more info AVRA is an open source assembler for Atmel AVR microcontroller family It can be used as a replacement of 'AVRASM32.EXE' the original assembler shipped with AVR Studio. We do not guarantee full compatibility for avra. AVRA comes with NO WARRANTY, to the extent permitted by law. You may redistribute copies of avra under the terms of the GNU General Public License. For more information about these matters, see the files named COPYING. Pass 1... Pass 2... done Used memory blocks: Code : Start = 0x0000, End = 0x0002, Length = 0x0003 Assembly complete with no errors. Segment usage: Code : 3 words (6 bytes) Data : 0 bytes EEPROM : 0 bytes $ ls -l 16 -rw-rw----+ 1 maisvendoo users 92 29 15:46 test.S -rw-rw----+ 1 maisvendoo users 0 29 15:55 test.S.cof -rw-rw----+ 1 maisvendoo users 13 29 15:55 test.S.eep.hex -rw-rw----+ 1 maisvendoo users 55 29 15:55 test.S.hex -rw-rw----+ 1 maisvendoo users 61 29 15:55 test.S.obj
Hex file content
:020000020000FC
:060000000AE00395FECFAB
:00000001FF
Listing is generated with the -l option when building
$ cat test.lst
AVRA Ver. 1.3.0 test.S Sat Jul 29 16:02:05 2017
.device atmega16
.dseg
.cseg
.org 0x0000
C:000000 e00a ldi r16, 10
M1:
C:000001 9503 inc r16
C:000002 cffe rjmp M1
.eseg
Segment usage:
Code : 3 words (6 bytes)
Data : 0 bytes
EEPROM : 0 bytes
Assembly completed with no errors.
Analyzing the results we can say that:
- Generates a file in Intel HEX format, suitable immediately for firmware in the MK
- Syntax compatible with Atmel
There are definitely differences in the avra syntax, for example
.device atmel16
gives an indication of the MC, hiding from the programmer an explicit indication of references to the * .inc file of macros. There are a number of other nuances that are easier to read in the
documentation or in a
good overview article of Valber in Russian. About the features of gavrasm can be
read here .
Both of the considered compilers have a significant
fatal flaw - they do not generate debug information. Although in avra documentation this possibility is stated
Debugging support AVRA creates a coff file everytime the assembly was sucessful. This file allows you to use the program.
but the * .cof file in the exhaust invariably turns out to be empty. The absence of debugging information eliminates adequate debugging in steps, which is very necessary for beginners. So from these (by the way, pretty old alternatives) we move on to another, more powerful compiler from the GNU family.
avr-as
The installation of this toolkit is available from the official repositories of any fairly popular distribution. In the case of Arch Linux
$ sudo pacman -S avr-gcc avr-libc avr-binutils
GNU assembler (gas) is a backend to the gcc compiler and is usually not explicitly invoked. This is due to the ideology of * nix systems, focused on the development of C / C ++, in which the assembler plays the role of the youngest unloved son. At the same time, it provides deep integration of assembler code into C / C ++ programs, which is rare, but sometimes necessary. In addition, if we talk about x86 / x86_64 architectures, the “bent” assembler (AT & T) syntax is very different from the adopted Intel notation (although the Intel-syntax can be used on gas, the compiler allows this). What is the reverse order of the operands in the commands in relation to intel-notation, for example
With regard to AVR gas, it does not depart from the Atmel notation regarding the design of commands - the order of operands is usual here, for example, the command:
ldi r16, 10
in gas for AVR looks familiar. Macroes and compiler directives are another matter; they differ from Atmel. The above test program will look like this:
test.S
#include "/usr/avr/include/avr/io.h" .data .section .text .org 0x0000 .global main main: ldi r16, 10 M1: inc r16 rjmp M1
As can be seen from the source, the code section is defined by the preprocessor directive .section .text (analogous to .cseg). Analog to .dseg is .data. The only thing I have not yet understood and saw in the documentation is how the contents of the EEPROM (analogue .eseg) are determined. I hope among the readers there is a kind guru who will push me to answer. For newbies like me, I advise you to smoke the documentation
here and
here to understand the specifics of using gas for AVR.
We will now compile a hex file suitable for the MK firmware. Team:
$ avr-as -mmcu=atmega16 -o test.o test.S
generates an object file for the corresponding controller (in our case, ATMega 16). This object file is then converted to hex.
$ avr-objcopy -O ihex test.o test.hex
Getting the output hex file
test.hex
:060000000AE00395FECFAB
:00000001FF
Nevertheless, we did not answer the main question and did not identify the advantage of gas on the possibility of organizing step by step debugging. For this first of all
2. Choose a debugger
In Linux there is no decent alternative to GDB. For its use in relation to the AVR MK set frontend
$ sudo pacman -S avr-gdb
This debugger possesses the entire complex of contradictions, frightening beginners: with fairly stated thermonuclear power, the threshold for its entry is rather high. To unlearn the fear of gdb and start working in it, I highly recommend the article of the greatest and mighty and, unfortunately, now deceased (earth you down, Myshch!) Nikolai Likhachev aka Chris Kaspersky
"Immersion in GDB technique and philosophy" .
The first thing you need to use gdb is to build the code accordingly, generating an ELF image containing debugging symbols.
$ avr-as -mmcu=atmega16 -g
The -g and --gstabs keys generate debugging symbols, respectively, and add the ability to use the image for remote debugging in gdb. Compose the resulting object file in ELF
$ avr-ld -m avr4 -o test.elf test.o
The resulting image we use to debug our test. You can also generate a hex file from it.
$ avr-objcopy -j .text -j .data -O ihex test.elf test.hex
explicitly specifying the -j key to include in the firmware section, the key -O ihex output format (intel HEX). We get the same file as in the previous case:
test.hex
:060000000AE00395FECFAB
:00000001FF
It remains to load the received code into the emulator and check the debugging options available.
3. AVR emulator in Linux
This question is more difficult than others. I found two worthy candidates:
simavr , available
in the official archa repositories and installed by simple:
$ sudo pacman -S simavr
and the more popular
simulavr simulator, which was not found even in AUR, while the majority of useful information on the network is about it. I did not get out of the source code to create a PKGBUILD for the AUR, although I went through all the appropriate branches in the
official repository . I had to beat the atrocious crutch by downloading the
Debian DEB package , turning it into an archa package with the help
of the debtap utility .
$ debtap simulavr_0.1.2.2-7+b2_amd64.deb
and then the resulting arch package without any problems put in the system.
This version is quite old, and the current release (judging by the date of the last commit in the repository) has gone quite far.
As for simavr, it is installed without problems, it supports a larger number of MCs, but when trying to connect to it with a debugger, it issues messages on the emulator crash to the console and I haven’t managed to figure it out yet. Here I again appeal to the reader who is knowledgeable in the question and look forward to a hint.
In the meantime, we use the simulavr set up with a crutch
4. Step-by-step debugging on the GDB + simulavr bundle
So, first we will debug the program hardcore - from the console we will launch the emulator
$ simulavr -d atmega16 -c 8000000 -g -P simulavr-disp
We start the ATMega 16 emulator (-d key) at 8 MHz (-c key) with the option of remote debugging and the possibility to view controller registers beautifully (the -P option, which has been removed from the network in the latest emulator version). We see the terminal window with the contents of the registers and memory
we observe in the start console the message
Waiting on port 1212 for gdb client to connect...
telling us that the emulator waits for the debugger to be connected on port 1212 (the port can be specified at startup with the -p switch). In another console, start the debugger:
$ avr-gdb -q -tui
the first key removes the pathetic exhaust of gdb at startup, the second group of keys activates the viewing of sources in the debugging process and is applied by me for clarity (in fact, this option is inconvenient for several reasons). In the console we will see the following:
We are connected to the emulator
(gdb) target remote:1212
We load the ELF-image into the emulator (yes, it is his and not hex, which I burned at the very beginning) d 'vekznjh
(gdb) load test.elf
Load the debug symbols:
(gdb) file test.elf
answering "yes" to the question asked, getting the following picture:
Well, we see our source and debugger, ready to receive commands. Give the command next
(gdb) n
and see the debugger move cheerfully through the code.
we can see the changed state of the controller registers as in the emulator console
and in the debugger window:
(gdb) info registers . . . r16 0xa 10 . . . SREG 0x0 0 SP 0x0 0x0 <main> PC2 0x2 2 pc 0x2 0x2 <M1>
From this point on, all the rich tools provided by the gdb debugger are available to us. However,
the Linux kernel is well reproached for saying that “dude, Atmel Studio has normal debugging with displaying source codes, moving the hot keys along the code in a sensible graphical way” and will try to solve the problem of friendliness of debugging at least partially by combining its development
5. Step-by-step debugging in the Eclipse IDE
IDE Eclipse is known for a long time. During its existence, it has firmly established itself in various areas of software development and can "stupidly everything", thanks to an extensive set of plug-ins that extend its functionality. At one time, I was delighted with her, but this time has passed, since in everyday work she has a lot of small nuances that swell into flaws (at work in production I preferred for the same C / C ++ QtCreator due to the specifics of the activity, which I don’t regret ).
Nevertheless, from the point of view of the problem we are solving, it completely satisfies its requirements. To work with AVR in Eclipse, you will need to install the following plugins
and, in order not to overload the article, I refer the reader to a search in which the installation of plug-ins for Eclipse is described in great detail. Important here is the setting up of the project, which I will discuss in detail.
Eclipse is essentially C / C ++ development oriented, so to create an assembly project we will use the project generation through the existing Makefile, which we will write for our test. Here he is
Makefile
# DEVICE = atmega16 TARGET = test OBJECTS = $(TARGET).o ELF = $(TARGET).elf HEX = $(TARGET).hex # COMPILE = avr-as -mmcu=$(DEVICE) -g --gstabs # - HEX- all: hex # : # *.S *.o .So: $(COMPILE) -c $< -o $@ # - clean: rm -f $(HEX) $(ELF) $(OBJECTS) # ELF elf: $(OBJECTS) avr-ld -m avr4 -o $(ELF) $(OBJECTS) # ELF HEX hex: elf avr-objcopy -j .text -j .data -O ihex $(ELF) $(HEX)
Having written this opus, open Eclipse and create a new project File -> New -> Project, choosing a sish project based on the Makefile
Click Next, in the next window, select the location of the source directory and the Makefile
Spank Finish and see our project in all its glory
Go to the menu Project -> Build all and get all the binaries we need:
19:34:51 **** Build of configuration Default for project test **** make all avr-as -mmcu=atmega16 -g --gstabs -c test.S -o test.o avr-ld -m avr4 -o test.elf test.o avr-objcopy -j .text -j .data -O ihex test.elf test.hex 19:34:51 Build Finished (took 128ms)
Now let's set up the emulator launch as an external project tool by going to Run -> External Tools, creating a new configuration with settings corresponding to the given screens.
Here we inform the environment that we want to run the emulator with the command line parameters we need by placing the launch point in the Run → External Tools menu.
Apply the settings, go to the Run → External Tools → atmega16 menu and watch the emulator start:
Ok, now let's set up the debug configuration of our project. Go to the Run → Debug Configuratuions menu and configure hardware debugging via GDB.
without forgetting to specify the type of connection to the simulation server:
and specifying what actions should be performed when debugging starts:
Be sure to put daws on Load image and Load Symbols - this allows the debugger to load the firmware into the emulator and read the debugging symbols. Put a breakpoint on the label M1.
Click the Apply and Debug buttons and ... voila!
The debugger obediently became at the specified breakpoint. Viewable memory dump and register contents. Hit F5 (or F6) and trace our code step by step.
Now you can even trace the code until blue in the face, watch the values ​​of the registers and variables, edit the code, trace again, and generally engage in the usual development process.
Conclusion
What do I want to say in the final? I have already said a thousand times that all my articles on Habr and Hyktimes resources are a reflection of personal experience and a mouthpiece of subjective opinion. Solved the problem - the organization of software development for AVR controllers in the Linux environment. This article is a product of long googling and gathering information from disparate network sources. Its goal is to push the beginner to search in the right direction. The article does not pretend to be academic, it is only a product of my own digging and an attempt to share the collected information, as well as to attract interested people to an interesting topic for me.
There is not much to be said about it, for example, about firmware via avrdude, which (sic!) Is a cross-platform firmware utility for the AVR family. If readers have a desire, but I have the opportunity, we will consider it, blink LEDs, send the word
"ass" "happiness" through USART and so on. The topic is inexhaustible and worthy of continuation. Time will tell.
In the meantime, thank my reader for your attention and hope for a new meeting!