Greetings,
I've noticed that the function call overhead in my application code to be somewhere in the order of ~3uS for a simple function with 1 argument (eg J2[26] = 0). This strikes me as rather large given that I'm running on a 147MHz core. Is there a way I can significantly improve the performance of the call stack (I assume this is causing the overhead)?
-Pete-
Function call overhead on MOD5270
-
- Posts: 513
- Joined: Sat Apr 26, 2008 7:14 am
Re: Function call overhead on MOD5270
Pete: The PinIO Class simplifies a lot of the complexity associated with configuring pins for all the potential functions possible for a given pin. It is an easy interface. That said, it can be slow when speed counts. The solution is to get (a lot) more familiar with the register calls needed to implement a given functionality; the NB platform gives you full access to all the registers when and if you need them. For GPIO, the register interface is it is not too bad at all.
See http://www.netburner.com/downloads/mod5 ... O-R1p1.pdf as a start, as well as http://www.netburner.com/downloads/mod5 ... ppNote.zip (code and register descriptions).
There is great (free!) 3rd party tool, called CFInit (http://www.microapl.co.uk/CFInit/cfinit_main.html) that is essentially a code wizard that will give you lots of insight on how to set up many of these registers to achieve a specified functionality. I often use the info it produces to get a new hardware module set up for the 1st time.
If you download CFInit, pay close attention to the Coldfire hardware module .h files it will install for most of the NB platforms (w/o affecting the NB setup). One thing I often miss w/ the NB tools is named bit fileds for all the registers. These files are of course part of The Freescale Code Warrior compiler, and unfortunately NB can't distribute them. However, the files are available for free on the MicroAPL site. This of courser means that instead of writing (cryptic) lines like:
sim.eport.epfr |= 0x10; // Clear the interrupt by CLEARING the
// EPF4 bit in the Eport flag register, EPFR.
you can write code like this:
sim.eport.epfr |= MCF_EPORT_EPFR_EPF4;
To me, this clearly communicates that we mean to set the EPFR4 bit in the EPFR register of the EPORT module. Once again: clearer design intent, fewer errors, and easier to maintain code.
Hope this helps!
See http://www.netburner.com/downloads/mod5 ... O-R1p1.pdf as a start, as well as http://www.netburner.com/downloads/mod5 ... ppNote.zip (code and register descriptions).
There is great (free!) 3rd party tool, called CFInit (http://www.microapl.co.uk/CFInit/cfinit_main.html) that is essentially a code wizard that will give you lots of insight on how to set up many of these registers to achieve a specified functionality. I often use the info it produces to get a new hardware module set up for the 1st time.
If you download CFInit, pay close attention to the Coldfire hardware module .h files it will install for most of the NB platforms (w/o affecting the NB setup). One thing I often miss w/ the NB tools is named bit fileds for all the registers. These files are of course part of The Freescale Code Warrior compiler, and unfortunately NB can't distribute them. However, the files are available for free on the MicroAPL site. This of courser means that instead of writing (cryptic) lines like:
sim.eport.epfr |= 0x10; // Clear the interrupt by CLEARING the
// EPF4 bit in the Eport flag register, EPFR.
you can write code like this:
sim.eport.epfr |= MCF_EPORT_EPFR_EPF4;
To me, this clearly communicates that we mean to set the EPFR4 bit in the EPFR register of the EPORT module. Once again: clearer design intent, fewer errors, and easier to maintain code.
Hope this helps!
Re: Function call overhead on MOD5270
Ridgeglider's suggestion about using the processor registers was a good one. The pins class was designed to be very easy to use but due to the nature of C++ classes there will be some added overhead compared to a single write to the GPIO register.
If all you are doing in the function is changing the state of a GPIO pin then you should probably make the code an inline macro instead of a function. This can be done with a define statement... ex. #define SET_J2_26 sim.gpio.ppdsdr_timer = 0x40; Now when you call SET_J2_26 only a single instruction is performed, nothing is put on the stack. If you make this a function then processor registers must be saved and restored from the stack which is where the latency comes from.
You will also get less function call latency if the calling stack is located in SRAM. Look at the following application note for more details on this: http://www.netburner.com/downloads/nndk ... rmance.pdf. By default some system tasks are located in SRAM for the newer builds so this may already be enabled for your function call if it occurs in UserMain().
If all you are doing in the function is changing the state of a GPIO pin then you should probably make the code an inline macro instead of a function. This can be done with a define statement... ex. #define SET_J2_26 sim.gpio.ppdsdr_timer = 0x40; Now when you call SET_J2_26 only a single instruction is performed, nothing is put on the stack. If you make this a function then processor registers must be saved and restored from the stack which is where the latency comes from.
You will also get less function call latency if the calling stack is located in SRAM. Look at the following application note for more details on this: http://www.netburner.com/downloads/nndk ... rmance.pdf. By default some system tasks are located in SRAM for the newer builds so this may already be enabled for your function call if it occurs in UserMain().
Re: Function call overhead on MOD5270
These are good suggestions and I've already made significant performance gains by using #define's to inline my GPIO get/set operations.
I have an older version of the NDDK which does not make use SRAM for fast data access. I'll download the new NDDK, and try locating my critical data in SRAM.
Thanks for your help.
-Pete-
I have an older version of the NDDK which does not make use SRAM for fast data access. I'll download the new NDDK, and try locating my critical data in SRAM.
Thanks for your help.
-Pete-
Re: Function call overhead on MOD5270
The stack overhead is completely eliminated by using inline functions.pwhiteis wrote:Greetings,
I've noticed that the function call overhead in my application code to be somewhere in the order of ~3uS for a simple function with 1 argument (eg J2[26] = 0). This strikes me as rather large given that I'm running on a 147MHz core. Is there a way I can significantly improve the performance of the call stack (I assume this is causing the overhead)?
-Pete-
Below code spends as little as 0.5 us to change level of GPIO pin (mod5270 with 147.456 MHz core clock)
Code: Select all
#include "sim5270.h" // mcf5270 register definitions.
//----------------------------------------------------------------------------
// Configure mcf5270 pins PDATAH[15:8] and PDATAL[7:0]
// as General Purpose Outputs and set output to high level.
// These pins are GPI by hardware reset.
// These pins have output data value 1 by hardware reset.
inline void D15_D0_GPO( void )
{
sim.gpio.par_ad &= ~0x01; // D[15:0] now are GPIO.
sim.gpio.podr_datah = 0xff; // D[15:8] now have output data ones.
sim.gpio.podr_datal = 0xff; // D[7:0] now have output data ones.
sim.gpio.pddr_datah = 0xff; // D[15:8] now are GPO.
sim.gpio.pddr_datal = 0xff; // D[7:0] now are GPO.
}
//----------------------------------------------------------------------------
// Set high level output.
// Netburner/Freescale pin name: J2[8]/PDATAH15/AN2)
// The pin needs also be configured as General Purpose Output.
inline void G1_High( void )
{
sim.gpio.ppdsdr_datah = 0x80;
}
// Set low level output.
// Netburner/Freescale pin name: J2[8]/PDATAH15/AN2)
// The pin needs also be configured as General Purpose Output.
inline void G1_Low( void )
{
// sim.gpio.pclrr_datah = ~0x80;
sim.gpio.pclrr_datah = 0x7f; // To eliminate warning.
}
Yevgeni Tunik
Embedded/RealTime software engineer
https://www.linkedin.com/in/yevgenitunik/
________________________
Embedded/RealTime software engineer
https://www.linkedin.com/in/yevgenitunik/
________________________