avr-gcc vs Arduino in PlatformIO - c

I'm using PlatformIO as an IDE for programming AVR MCUs. I'm beginning AVR programming (I have a background in C/C++ and programming on OS's, not embedded, although I have done some Arduino stuff in the past) and using PlatformIO gives me code completion for the registers/pins, which is why I use it.
It seems I can't switch framework from Arduino to avr-gcc in PlatformIO without losing code-completing.
I am wondering if there's any drawbacks in keeping Arduino as the
framework?
I know Arduino uses avr-gcc in the back, but I read that it still does a bit of setup without the users knowing it (such as Timer0 setting for delays, which I need since I'm using it as a clock source for USI on my ATTiny85).
Otherwise, is there anyway in PlatformIO to keep code completion and
use avr-gcc instead of Arduino?
Thanks!
EDIT: I'm on either OSX or linux (ubuntu).

As pointed out by ivankravets on the PlatformIO community platform (see: https://community.platformio.org/t/avr-programming-without-arduino-framework/525/4), it is as simple as removing the line framework = arduino from the platformio.ini file to get rid of the Arduino framework and work in bare C for avr-gcc.

I have never used PlatformIO, and my answer is only based on my (extended) knowledge of AVR development and the Arduino mess…err…framework.
The Arduino framework is using AVR-libc (the standard low level framework that gives you all the tools you need to program on AVR), and adds a layer of abstraction so you're not directly handling registers, but use a more easily understandable interface.
So when you write on a pin, instead of looking at the AVR's IC leg number, looking for the matching PORT address to configure it and mutate it, you're using digitalWrite() on the board's pin number. So, whatever the IC is, the pin will stay the same with consistent capabilities.
The pin definition is done using a header file that's given to the compiler depending on your target setting in your IDE (so whether you use an Arduino Mega or a Leonardo the matching between AVR port/pin and board pinout will change radically).
Given your description of PlatformIO, it's using that information to give you appropriate pinout completion based on the board configuration. It's also certainly taking advantage of the object oriented approach of the Arduino framework, so that you can easily have method completion when using singletons (like when you use Serial).
Using raw AVR-libc, on the other hand, it's harder to get any meaningful completion, because most of the operations are being done on registers which are being declared through preprocessors aliases, and the whole code is pure C, so code completion is not really helpful (you cannot list all the methods that applies to a given object… like with the Serial example).
Then, Arduino offers a nice high level approach to prototyping embedded code, that you can then curate when you need to optimise in time and/or space. And some projects (like the Marlin firmware for repraps) use some sort of hybrid approach, reimplementing many parts of the Arduino interface in a more optimised way (like digitalWrite or the Serial object).
In the end, my advice to you would be to drop platform.io or the arduino IDE, and switch to eclipse if you're really into IDE GUIs, or better, use your preferred powerful editor (like vim/nvim, emacs, atom, sublime…) to have it handle AVR code like any other C code.

If you work on an Arduino project including avr-gcc internals using VisualMicro plugin and VisualStudio (Community Edititon) all the code completion / syntax highlighting / goto declaration etc. works for anything in your project and all libraries.
Is this what you're looking for?
Of course, VisualMicro is annoying if you use them "for free"

Related

Is it possible to build C source code written for ARM to run on x86 platform?

I got some source code in plain C. It is built to run on ARM with a cross-compiler on Windows.
Now I want to do some white-box unit testing of the code. And I don't want to run the test on an ARM board because it may not be very efficient.
Since the C source code is instruction set independent, and I just want to verify the software logic at the C-level, I am wondering if it is possible to build the C source code to run on x86. It makes debugging and inspection much easier.
Or is there some proper way to do white-box testing of C code written for ARM?
Thanks!
BTW, I have read the thread: How does native android code written for ARM run on x86?
It seems not to be what I need.
ADD 1 - 10:42 PM 7/18/2021
The physical ARM hardware that the code targets may not be ready yet. So I want to verify the software logic at a very early phase. Based on John Bollinger's answer, I am thinking about another option: Just build the binary as usual for ARM. Then use QEMU to find a compatible ARM cpu to run the code. The code is assured not to touch any special hardware IO. So a compatible cpu should be enough to run all the code I think. If this is possible, I think I need to find a way to let QEMU load my binary on a piece of emulated bare-metal. And to get some output, I need to at least write a serial port driver to bridge my binary to the serial port.
ADD 2 - 8:55 AM 7/19/2021
Some more background, the C code is targeting ARMv8 ISA. And the code manipulates some hardware IPs which are not ready yet. I am planning to create a software HAL for those IPs and verify the C code over the HAL. If the HAL is good enough, everything can be purely software and I guess the only missing part is a ARMv8 compatible CPU, which I believe QEMU can provide.
ADD 3 - 11:30 PM 7/19/2021
Just found this link. It seems QEMU user mode emulation can be leveraged to run ARM binaries directly on a x86 Linux. Will try it and get back later.
ADD 4 - 11:42 AM 7/29/2021
An some useful links:
Override a function call in C
__attribute__((weak)) and static libraries
What are weak functions and what are their uses? I am using a stm32f429 micro controller
Why the weak symbol defined in the same .a file but different .o file is not used as fall back?
Now I want to do some white-box unit testing of the code. And I don't want to run the test on an ARM board because it may not be very efficient.
What does efficiency have to do with it if you cannot be sure that your test results are representative of the real target platform?
Since the C source code is instruction set independent,
C programs vary widely in how portable they are. This tends to be less related to CPU instruction set than to target machine and implementation details such as data type sizes, word endianness, memory size, and floating-point implementation, and implementation-defined and undefined program behaviors.
It is not at all safe to assume that just because the program is written in C, that it can be successfully built for a different target machine than it was developed for, or that if it is built for a different target, that its behavior there is the same.
I am wondering if it is possible to build the C source code to run on x86. It makes debugging and inspection much easier.
It is probably possible to build the program. There are several good C compilers for various x86 and x86_64 platforms, and if your C code conforms to one of the language specifications then those compilers should accept it. Whether the behavior of the result is representative of the behavior on ARM is a different question, however (see above).
It may nevertheless be a worthwhile exercise to port the program to another platform, such as x86 or x86_64 Windows. Such an exercise would be likely to unmask some bugs. But this would be a project in its own right, and I doubt that it would be worth the effort if there is no intention to run the program on the new platform other than for testing purposes.
Or is there some proper way to do white-box testing of C code written for ARM?
I don't know what proper means to you, but there is no substitute for testing on the target hardware that you ultimately want to support. You might find it useful to perform initial testing on emulated hardware, however, instead of on a physical ARM device.
If you were writing ARM code for a windows desktop application there would be no difference for the most part and the code would just compile and run. My guess is you are developing for some device that does some specific task.
I do this for a lot of my embedded ARM code. Typically the core algorithms work just fine when built on x86 but the whole application does not. The problems come in with the hardware other than the CPU. For example I might be using a LCD display, some sensors, and Free RTOS on the ARM project but the code that runs on Windows does not have any of these. What I do is extract important pieces of C/C++ code and write a test framework around it. In the real ARM code the device is reading values from a sensor and doing something with it. In the test code that runs on a desktop the code reads from a data file with fake sensor values and writes its output to a datafile that can be analyzed. This way I can have white box tests for the most complicated code.
May I ask, roughly what does this code do? An ARM processor with no peripherals would be kind of useless. Typically we use the processor to interact with some other hardware like a screen, some buttons, or Bluetooth. It's those interactions that are going to be the most problematic.

Can you open and edit .c files in the Arduino IDE? And subsequently load them to an Arduino board

I have been trying to open c files in the Arduino IDE (which some people claim is possible).
I have not been able to do so.
How can I program the Arduino in c given that I have a project/files in another IDE? (for example, MPLABX)
I am not sure what you are trying to archive. Is it that you want to open it via the Arduino IDE or also compile the source code?
I am not aware of programming in bare c in the Arduino IDE. But if you're looking into using real c code, it might be a good time start either compiling and uploading via terminal yourself, or use an IDE which is suited for development with micro controllers.
I think you can tell the Arduino IDE to more elaborately log outputs. This would tell you exactly the commands the IDE is using (uses avrdude). Then you can use an IDE/Editor of your choice for coding.
Otherwise, have a look at eg. Atmel Studio. They also support Arduino.
There are two answers in one:
If you really want to use the ArduinoIDE you have to have a basic *.ino file having at least the defines and includes which are in the project file and the reqiured setup() loop() usually whats in main in c goes to loop() in ArduinoIDE. Thats the stoney path because there are some specific issues coming from the philosophy behind ArduinoIDE (help makers with little (no?) programming skills to get started quickly).
If you just need the Arduino tool-chain and want to work more comfortable you have two other options:
EclipseIDE with the Sloeber add-on. Download the Sloeber-AllInOne-Package for an easy start and THEN add the other modules you need (like for web development or similar)
PlatformIO an IDE for micro controller development - there is also a cloud based version for testing around.
All mentioned tools are real open source and available cross PC platform and not a gift from a company like MS for probably later lockin of devs

Run executable on MINI2440 with NO OS

I have Fedora installed on my PC and I have a Friendly ARM Mini2440 board. I have successfully installed Linux kernel and everything is working. Now I have some image processing program, which I want to run on the board without OS. The only process running on board should be my program. And in that program how can I access the on board camera to take image from, and serial port to send output to the PC.
You're talking about what is often called a bare-metal environment. Google can help you, for example here. In a bare-metal environment you have to have a good understanding of your hardware because you have to take care of a lot of things that the OS normally handles.
I've been working (off and on) on bare-metal support for my ELLCC cross development tool-chain. I have the ARM implementation pretty far along but there is still quite a bit of work to do. I have written about some of my experiences on my blog.
First off, you have to get your program started. You'll need to write some start-up code, usually in assembly, to handle the initialization of the processor as it comes out of reset (or is powered on). The start-up code then typically passes control to code written in C that ultimately directly or indirectly calls your main() function. Getting to main() is a huge step in your bare-metal adventure!
Next, you need to decide how to support your hardware's I/O devices which in your case include the camera and serial port. How much of the standard C (or C++) library does your image processing require? You might need to add some support for functions like printf() or malloc() that normally need some kind of OS support. A simple "hello world" would be a good thing to try next.
ELLCC has examples of various levels of ARM bare-metal in the examples directory. They range from a simple main() up to and including MMU and TCP/IP support. The source for all of it can be browsed here.
I started writing this before I left for work this morning and didn't have time to finish. Both dwelch and Clifford had good suggestions. A bootloader might make your job a lot simpler and documentation on your hardware is crucial.
First you must realise that without an OS, you are responsible for bringing the board up from reset including configuring the PLL and SDRAM, and also for the driver code for every device on the board you wish to use. To do that required adequate documentation of the board and it devices.
It is possible that you can use the existing bootloader to configure the core and SDRAM, but that may not meet your requirement for the only process running on the board should be your image processing program.
Additionally you will need some means of loading and bootstrapping; again the existing Linux bootstrapper may suit.
It is by no means straightforward and cannot really be described in detail here.

Is there a way or tutorial for converting Arduino code to C code?

I know that this question is general, but I couldn't find a tutorial or a good coding way to convert Arduino code (I mean the code that we are writing on Arduino software and it doesn't matter for Arduino Uno or Mega or ... ) even if a small sample.
Is there a tutorial?
I just want to learn the technique, and I know that it depends on the project.
Arduino code is, more or less, C code.
The unique things that happen with Arduino is that the code is preprocessed (for example, they give simple hooks by establishing the setup and loop functions) and has a managed build/upload process that takes care of board limits, includes, libraries, etc...
It is certainly possible to use the same toolkit yourself to build and run the code, that's how I do it. Arduino and GCC, compiling and uploading programs using only makefiles is the most useful link I've found covering the steps you need to get started.
As I said, I've left the Arduino IDE and taken up the avr-gcc route myself, because if you know the GNU tools, you can do much more powerful things - like use the C++ standard libraries. I missed my vectors, what can I say. avr-libc is lagging quite a bit when it comes to full C++ functionality, making it hard to cram in the STL, but Andy Brown has gotten much of it working.
Throw those things together and you have quite a powerful development environment.
(Edit: I missed the very useful link in Matt's answer while writing my own answer. So let's say that what is below is a non technical summary of the link).
Matt answered right. I would like to add additional information.
The key to understand Arduino programming is in the directory Arduino-1.0\hardware\arduino\cores\arduino
You will find the main.cpp file containing:
#include <Arduino.h>
int main(void)
{
init();
#if defined(USBCON)
USB.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
Do "setup()" and "loop()" (and even "serialEventRun() if you read the Arduino documentation) ring a bell? :-)
Arduino hides only that.
Arduino uses the C++ language. Of course, you can use C if you compile your code yourself with avr-gcc, but the way the Arduino IDE is configured, it is pure C++.
However, as microcontrollers are not really adapted to object-oriented development, some features are missing. I think about the "new" and "delete" operators. They do not exist, so out of the box, you should avoid using the heap when you develop with Arduino. It is why you should be careful if you want to use some standard C++ libraries. They may not be adapted for microcontroller programming (too many memory operations).
In the Arduino-1.0\hardware\arduino\cores\arduino directory, you can also see the implementation of the Arduino library. It allows watching which "low-level" microcontroller functions (from avr-libc) exist and how you can implement your own libraries and tools.
By the way, as you wanted to know how you could port Arduino code in C, avr-libc is a C library and not a C++ one. So you can see how Arduino wraps its C++ code over C code.
In the File/Preferences menu, you can check "see verbose output" to see which parameters and files are used to build the final Arduino binary (and where the temporary build directory is).
Finally, you must also know that Arduino boards have a bootloader embedded with your code. It eases the deployment from the Arduino IDE to the Arduino board. So the Arduino board actually contains more code than your own.
It's not a conversion tutorial but a very nice write up about what's behind arduino's hello world:
A tour of the Arduino internals. How does hello world actually work?

Testing Code for Embedded Application

Background:
I am developing a largish project using at Atmel AVR atmega2560. This project contains a lot of hardware based functions (7 SPI devices, 2 I2C, 2 RS485 MODBUS ports, lots of Analogue and Digital I/O). I have developed "drivers" for all of these devices which provide the main application loop with an interface to access the required data.
Question:
The project I am developing will eventually have to meet SIL standards.
I would like to be able to test the code and provide a good level of code coverage. However I am unable to find any information to get me started on how such a testing framework should be set up.
The idea is that I can have a suite of automated tests which will allow future bug fixes and feature additions to be tested to see if they break the code. The thing is I don't understand how the code can be tested on chip.
Do I require hardware to monitor the I/O on the device and emulate externally connected devices? Any pointers that could be provided would be highly appreciated.
--Steve
This is a very good question - a common concern for embedded developers. Unfortunately, most embedded developers aren't as concerned as you are and only test the code on real hardware. But as another answer pointed out, this can basically test just the nominal functionality of the code and not the corner/error cases.
There is no single and simple solution to this problem. Some guidelines and techniques exist, however, to do a relatively good job.
First, separate your code into layers. One layer should be "hardware agnostic" - i.e. function calls. Do not ask the user to write into HW registers directly. The other (lower) layer deals with the HW. This layer can be "mocked" in order to test the higher level. The lower level can not be really tested without the HW, but it's not going to change often and needs deep HW integration, so it's not an issue.
A "test harness" will be all your high-level HW agnostic code with a "fake" lower level specifically for testing. This can simulate the HW devices for correct and incorrect functionality and thus allow you to run automated tests on the PC.
Never run unit tests on or against the real hardware. Always mock your I/O interfaces. Otherwise, you can't simulate error conditions and, more importantly, you can't rely on the test to succeed.
So what you need is to split your app into various pieces that you can test independently. Simulator (or mock) all hardware that you need for those tests and run them on your development PC.
That should cover most of your code and leaves you with the drivers. Try to make as much of the driver code as possible work without the hardware. For the rest, you'll have to figure a way to make the code run on the hardware. This usually means you must create a test bed with external devices which respond to signals, etc. Since this is brittle (as in "your tests can't make this work automatically"), you must run these tests manually after preparing the hardware.
Vectorcast is a commercial tool to run unit tests on the hardware with code coverage.
Do you have a JTAG connector? You may be able to use JTAG to simulate error conditions on the chip.
I like to separate the tasks. For instance, when I made a circular buffer for my Atmel AVR I wrote it all in Code::Blocks and compiled it with the regular GCC compiler instead of the AVR GCC compiler, then I create a unit test for it. I used a special header file to provide the proper data types that I wanted to work with (uint8_t for example). I found errors with the unit tests, fixed them, then took the fixed code over to AVR Studio and integrated it. After that I used wrote support functions and ISRs to fit the buffer into useful code (ie, pop one byte off the buffer, push it into the UART data output register, append a string constant to the buffer for a printf function, etc). Then I used the AVR simulator to make sure that my ISRs and functions were being called and that the right data showed up in registers. After that I programmed it onto the chip and it worked perfectly.
I greatly prefer the debugging capabilities of Code::Blocks compared to AVR Studio so I use the above approach whenever I can. When I can't I'm usually dealing with hardware only. For instance I have a timer that automatically produces a square wave. The best I could do was see that the pin bit was being twiddled in the simulator. After that I just had to hook a scope up and make sure.
I like to use a multi-level approach when debugging problems. For instance with the clock the first layer is 'Put a probe on the clock pin and see if there's a signal there'. If not, probe out the pin on the uC and look for the signal. Then, I coded a debug interface in one of my UARTs where I can look at specific register values and make sure they are what they're supposed to be. So if it doesn't work the next step is 'call up the register value and ensure it's correct.'
Try to think ahead four steps or so whenever you're planning your debugging. There should be +5V here, but what if there isn't? Write into the debug interface a way to toggle the pin and see if that changes it. What if that doesn't work? Do something else, etc etc etc. You get to a point where you run into 'I HAVE NO IDEA WHY THIS DANG THING DOESN'T WORK!!!!' but hopefully you'll figure out the reason beforehand.

Resources