Using MPlabX to Program Arduino Boards in Straight C/C++

I wanted to use MplabX to replace the graphical front-end of the Arduino app and write my own bare metal C/C++ code, but use the arduino’s built-in USB programming function. The method below can be done in multiple different IDEs, but I show how to set up MplabX. It is important to note that this method expects the Arduino’s bootloader to be stay on the board.

1. Setting up the Path to the Arduino IDE’s Compiler:

These are different for every computer so you have to find it yourself. To do this, open the Arduino IDE , go to File–>Preferences and click “Show Verbose Output” for both Compile and Download.

Next, plug in a board and send an example project to your Arduino (such as Blink.ino). The command line will spill over with commands.

Scroll to the top of the command window in the ArduinoIDE and look for the line after it says “Compiling Sketch”:

Copy this entire line and paste it to a text file so we can edit it. (Double-click this line to highlight it to copy). Here’s mine:

"C:\\Users\\adamp\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Users\\adamp\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IC:\\Users\\adamp\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\eightanaloginputs" "C:\\Users\\adamp\\AppData\\Local\\Temp\\arduino_build_752190\\sketch\\Blink.ino.cpp" -o "C:\\Users\\adamp\\AppData\\Local\\Temp\\arduino_build_752190\\sketch\\Blink.ino.cpp.o"

 

The highlighted portion above is the file path to the C++ compiler Arduino uses. If we want to write our own bare-bones C or C++ code for the arduino, this is all we need.  Open MPlabX and select “Tools–>Preferences.  In the popup, select the “Embedded” tab.  On the left side, click the Add… button to add a new toolchain. A new popup will appear where you can paste the “Base Directory”. Paste in the highlighted part of your path only up to but NOT including the “avr-g++” part.  This will allow MPlabx to use the AVR-G++ compiler for Atmel chips.

2. Creating a MplabX project:

In MpLabx, start a new standalone project. I’m using an Arduino nano so I will choose the chip “Atmega328P” I recommend you select “Simulator” for the “Tool” entry here as it can be really handy for debugging code.

Then select the new entry “AVR-GCC” for the toolchain.

3. Set up the Programming Tool in MPlabX:

Now to take advantage of the built-in USB programming of an arduino board we need to set up the correct commands. In the Arduino IDE scroll down in the command window and find the last line of white text before the red text begins. The red text is the output from the programmer app (called avrdude.exe).  The line just before this is the command that calls avrdude with the appropriate settings.

 

C:\Users\adamp\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\adamp\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -carduino -PCOM7 -b115200 -D -Uflash:w:C:\Users\adamp\AppData\Local\Temp\arduino_build_752190/Blink.ino.hex:i

Scroll to the rightmost of the command below to see the highlighted text in the line above. This is the path to the actual hex file the programmer is sending. This changes based on where you name the MPlabx project. You need to change this file path to the following to work with any MPlabX project:

-Uflash:w:${ImagePath}

Once you make this change, simply copy this entire command and paste it into the MplabX project properties.

In Mplabx, right-click the project you want to work on, select Properties, then select “Building” from the left sidebar in the popup window. Make sure to click “Execute this line after build” and paste the entire command from above in the blank.

***BIG NOTE: If you change the port number of the board you are programming (plugging in a different board, or using this same project on a different computer) you MUST change the COM port in this option in the project or it will fail to program and give a cryptic error.

4. Testing with a Blink project:

If you have set everything up correctly, then you can right-click your project and select New–>main.c

Replace the code in this file with the following:

#define F_CPU 16000000UL //You must define the clock frequency before you can use the delay function. This should match the crystal on your board.

#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h> //must use this to use the _delay_ms() function
#include <avr/io.h> //Must use this to access port and pin numbers on our chip

/*
*
*/
int main(int argc, char** argv) {

       //this is where your setup() function goes
       DDRB |= (1 << PORTB5); //Make Arduino Pin13 (AVR PortD Pin5)) and output pin

      while (1) {//this is your "loop" function
           PORTB ^= (1 << PORTB5); //Toggle the value of this pin using an XOR function with itself
          _delay_ms(100); //Change this number to change the LED flashing frequency to know if it is working or not.
        }//end while 1

       return (EXIT_SUCCESS);
}//end main

Then click the build icon and it should compile, then you should see the familiar text from the Arduino IDE. The Avrdude programming information is the red text when you turn on Verbose mode.

Troubleshooting:

If you don’t see this text, a few things might be the cause:

  1. You forgot to click the “Execute after build” checkbox in the build properties
  2. You have the wrong COM port or U:flash setting in the line you want it to execute after building.
  3. Make sure you set your project up with the correct chip and correct toolchain (AVR-GCC)
  4. You have a compilation errors. This can be hard to see, but you can make it easier

If your Arduino isn’t doing what you want it to, then you likely need to debug your code. There’s a LOT to be said with this. The easiest method is to set up a UART library so you can print text out the serial port to your computer. Search github and AVR freaks for examples you can import.

Another method is to use the Simulator in MPlabx to see what bits are being set/changed in the memory location of the Atmega chip.

A third option allows you to run the code line by line on the actual chip. This would require a proper programmer (not just the arduino’s built-in USB programming).  Here’s an example of how to set that up.

Now you can learn to write your own libraries to better understand the magic of the Arduino project. Learn some of the tricks that are used to simplify the interface for programming on this site.

 

 

Leave a Comment