Prototyping Code?

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is a general question but in the context of avr-gcc and AS7.

 

Lets suppose that I have a block of code that I want to test. I am concerned about execution time and memory footprint. So, I would like to write a little test program and run it through the simulator while tracking it through a disassembled code listing. 

 

How do folks do this? When I try, it all gets optimized away because results are never used for anything. I'm a bit reluctant to just declare everything as volatile, thinking that it would not represent what happens in the final application.

 

Am I concerned about nothing? How do others do this?

 

Thanks

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't need to declare everything to be volatile.  Just the results.

 

Say you have a function foo() you want to test, which returns uint8_t:


  volatile uint8_t results;
  while (1) {
      results = foo();
  }

The compiler is obliged to honour the call to foo(), and assign its return value to the volatile results.

 

However I suppose if foo() always returns the same value, it is possible that the compiler will see this and replace the call with a constant.

 

Can you give an example?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The odds are that you are investigating a new feature for your existing project i.e. it will be called.
Build with and without e.g. #if
Compare binary size.
Compare execution times.
Yes, this might be tight for an ATmega328p project that is already using 32766 bytes.
You might need to #if some message text.
.
In an ideal world there is a ATmega648p chip for development. Rebuild for final 328p target.
Other families have a wider memory range e.g 164, 324, 644, 1284
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Oh the joys of Codevision...

 

The #pragma keep+ directive forces a function, global variable or global constant to be linked even if it wasn’t used anywhere in the program.

 

... wink

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another option is to actually do something with the

result like send it out over a USART.

 

--Mike

 

EDIT: spelling

 

Last Edited: Tue. Jul 9, 2019 - 05:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I am trying to prepare code examples to show things here on Freaks I'm often hit by this and have the same kind of issues of things just being discarded.

Common tricks to try and defeat the optimisation:

 

1) "volatile" you already mentioned - can help to force things to happen (no compile time precalculation based on "known" values)

 

2) globals - when results are assigned to globals the compiler cannot know at the time of compilation of the one .c whether it's later going to link to other .c (.o) files so anything global might be seen/used external from the current file - therefore if the item is written the compiler will have to generate code to make the write

 

3) if you put the support functions in the same file as the main() harness you are giving the compiler the opportunity to (a) see fixed results and (b) inline it. Sometimes __attribute__((never_inline)) on a function can help. Also making sure it is NOT "static" helps a lot because then the compiler is obliged to make an externally callable copy - however it can still inline the locally called copy too.

 

4) as i just mentioned it's wise to put the code of the functions under test in a second .c file. The main() harness cannot then make any assumptions about what goes on in the called functions and equally the called functions cannot know anything about the way they are going to be called (like dropping bits because some parameter has a known, fixed input)

 

5) If the worst comes to the worst -O0 but then you aren't really looking at the "real" code so size and speed have no bearing on the final solution.

 

If you have a specific example you want to share (here or PM) I'm sure Joey, perhaps others and I would be interested at having a go at making it generate the function bodies you are looking for.

As I say, in preparing code examples for here I often spend more time trying to defeat the optimisation than writing the demonstration code in the first place.

 

(personally I never resort to -O0 though)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

Oh the joys of Codevision...

 

The #pragma keep+ directive forces a function, global variable or global constant to be linked even if it wasn’t used anywhere in the program.

 

... wink

__attribute__((used)) in GCC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No example yet. I want to try several DSP algorithms to see what the execution overhead is. I really don't want to mess with existing code.

 

The suggestions are appreciated. I think that I'll pursue Cliff's suggestions as his occasional posts of code bits (and their compiled results) are what prompted this question. So, I think that I will create a little "test harness" as he suggests and use that  to hang various experiments onto.

 

Thanks for the ideas!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
How do folks do this?
A unit test framework though do have to manually confirm code coverage.

Some development processes require Object Code Verification (OCV) that's akin to your "... and run it through the simulator while tracking it through a disassembled code listing."

Timing data acquisition is mostly automated by the unit test framework; sizing data acquisition is less automated though likely create some Python to mow through the memory maps (transform data into information)

RMA is dependent on timing data.

One finds that their cup has been over filled by the sizing data.

ka7ehk wrote:
Am I concerned about nothing?
No as your personal process may require unit testing, a safety standard may directly or indirectly require unit testing, or the customer may require unit testing.

ka7ehk wrote:
How do others do this?
Build the entire application, or a part, then drive it via the debugger; test cases are by debugger's standard input/output.

Add test drivers' code to the application then drive via a monitor; keep the monitor in the release so can diagnose assertions and exceptions.

If there's enough program space then add a shell and interpreter (a modern monitor)

 


RMA - Rate Monotonic Analysis

 

Unit testing frameworks | Introduction to Software Engineering/Testing/Unit Tests - Wikibooks, open books for an open world

 

Maybe encapsulate C if that'll fit on the MCU :

C Programming/GObject - Wikibooks, open books for an open world

 

haven't seen any use of coverage for AVR GCC :

gcov—a Test Coverage Program | Using the GNU Compiler Collection (GCC)

though coverage exists for bare board arm and RISC-V GCC :

12.7. Code Coverage | 12. Tools — GPS 20.0w documentation

 

QNX - Shell

QNX, SoftIntegration Team Up to Provide C/C++ Scripting Technology

 

"Dare to be naïve." - Buckminster Fuller