Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
October 26, 2020, 04:23:25 04:23


Login with username, password and session length


Pages: [1]
Print
Author Topic: Using Proteus to simulate Arduino uising extenally generated .elf file  (Read 570 times)
0 Members and 1 Guest are viewing this topic.
chicowood
Junior Member
**
Offline Offline

Posts: 80

Thank You
-Given: 75
-Receive: 19


« on: August 08, 2020, 11:12:58 23:12 »

Hi - For years I've been using Proteus to simulate PIC firmware and hardware by using the MPLAB/MPLABX Proteus plugin. It's been a useful tool in my development workflow. Proteus simulation isn't perfect, but it's saved me a lot of time and solder...

I recently started doing the same with the Arduino IDE and the AVR processors in Proteus. Since there is no plugin to tie the Arduino IDE (or any other Arduino IDEs, like VSCode, PlatformIO, etc.) to Proteus, I generate .elf files from the GCC-AVR compiler and load them directly into the AVR processor on Proteus.

I encountered a number of frustrating issues doing this, but eventually worked through them. I'd like to share my workflow to assist others who may want to do the same, perhaps save someone time or trouble.

Proteus has the ability to set up a firmware project itself. However, I encountered a number of issues when using this. You can set up Proteus to directly use the Arduino IDE compiIer toolchain but I found sometimes sketches would compile in the Arduino IDE but not the Proteus IDE, and I was not able to figure out why (sometimes Proteus couldn't find libraries that were right there). The Proteus system compiles to a hard-to-locate temp directory unless the project settings "Embed Files" box is unchecked, which dumps all the compiler output into the project folder.  I also found the Proteus editor and IDE user interface to be awkward. I prefer to develop code in the Arduino IDE, VSCode, or more sophisticated editor suites, and let Proteus do the simulation, not the code building.

Because of these issues, I decided to avoid using the Proteus firmware development environment, and to use the Arduino IDE toolchain directly. Here is the way I've set up my system:

1) Create the hardware schematic in Proteus, using one of the AVR processors.

2) Create the firmware project in the IDE of choice. I prefer to write code using VSCode as my editor and to use the VSCode Arduino Extension to compile the code using the Arduino IDE toolchain. That way I can easily switch from the Arduino IDE to VSCode as desired for different purposes. Some prefer to use the PlatformIO extension in VSCode or Eclipse, that's fine, but I prefer to avoid creating a separate toolchain from the default Arduino IDE toolchain.

3) Edit the Arduino preferences.txt file. This text file is referenced in the Arduino IDE preferences window. Add the line "build.path=(path)", setting the path to wherever you prefer the Arduino build output to be placed (* if anyone knows how to make this path dynamic rather than static so you could place the output in the project folder, I'd appreciate a how-to...*)

4) If you are using VSCode to edit and build the Arduino firmware, edit the arduino.json project file to include the line, "output": "../VSCode_output", to place the Arduino build output into the specified VSCode_output folder.

5) When building for Proteus simulation, instruct the compiler to turn off optimization. If this isn't done, the resulting .elf file will display incomplete code addresses in Proteus, and sometimes even fail to provide a .ino file for debugging purposes.

To do this, preface the Arduino sketch with:

Code:
#pragma GCC optimize ("-O0")
#pragma GCC push_options
...and terminate the Arduino sketch with:

Code:
#pragma GCC pop_options

This will tell the compiler not to perform any optimization. This will result in larger firmware files, so these #pragma lines can be commented out when building and uploading the firmware to the actual hardware.

6) Build the file in the Arduino IDE, VSCode or (your choice).  The .elf file will be written to the output folder specifed in item #3 or #4 above.

7) In Proteus, add the .elf file to the processor properties (control-i, "Properties"). Simulate using the Proteus system debugger, as described in the Proteus documentation.

Works well for me. Hope it's helpful for someone else too.

Now if only there were a similar firmware/hardware simulation environment for the ESP8266/ESP32... Wink

« Last Edit: August 08, 2020, 11:16:16 23:16 by chicowood » Logged
chicowood
Junior Member
**
Offline Offline

Posts: 80

Thank You
-Given: 75
-Receive: 19


« Reply #1 on: August 15, 2020, 08:14:14 20:14 »

Addendum: If you encounter the issue of Proteus simulation not displaying local variable values, despite having compiler optimization turned off:

The compiler will sometimes use registers to handle local variables. If you can't find a particular local variable in the "AVR Variables" list, press control-D in the AVR Source Code window to view the compiler-generated assembly code. Next open "Debug -> AVR -> CPU Registers". Search for the desired local variable in the Source Code window, and step through the disassembled code below the C++ code line that contains the variable.

You should see the processor load a variable into the register indicated in the source code, and you will see the value of the local register in the CPU Registers window.

For example, if the C++ source code line is "x = 0", you will see assembly code that looks something like "ST Y+5, R1" below it, and as you step through, you will see R1 change to reflect the value of x.

If the C++ source code line is "if (x == false)", you will see assembly code that looks something like "LD R25, Y+1" below it, and as you step through, you will see R25 change to reflect the value of x before the comparision occurs.

I haven't done assembly coding since the original days of the Z80 and 8031/8048 chips, but even if you've never played with assembly, it's pretty self-explanatory for simple usage cases like this.

EDIT: Someone just pointed out to me that as an alternative, you can just declare the local variable as "volatile" to get it to appear as a listed variable in Proteus, since in that case the compiler won't store it solely in a register instead of ram. I tested this, it works. I'm not sure why turning off optimization doesn't do this as well, but it doesn't, so...
« Last Edit: August 15, 2020, 10:24:25 22:24 by chicowood » Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC