Over a million developers have joined DZone.

Optimized BitIO_LDD Programming with Processor Expert

DZone's Guide to

Optimized BitIO_LDD Programming with Processor Expert

· Performance Zone ·
Free Resource

xMatters delivers integration-driven collaboration that relays data between systems, while engaging the right people to proactively resolve issues. Read the Monitoring in a Connected Enterprise whitepaper and learn about 3 tools for resolving incidents quickly.

In my tutorial “Bits and Pins with Kinetis” I showed how to use the BitIO_LDD approach for Bit I/O access. I do not like this LDD (logical device driver) approach for several reasons:

  1. It requires an extra "device handle" passed to the functions, even if such a device handle is not needed or desired.
  2. The code efficiency/size is negatively impacted by this.

Luckily, there is a way to hack around this. :-)

DeviceDataPtr for BitIO_LDD

If using the BitIO_LDD approch as in “Bits and Pins with Kinetis,” then every call to the BitIO routines need to have the "device" pointer parameter which is created with the Init() method. With the component property "Auto Initialization" set to "yes", it will call that Init() method for me automatically as part of the PE_low_level_init() inside main():

Auto Initialization for BitIO_LDD

Auto Initialization for BitIO_LDD

This automatically created device handle needs to be passed to very BitIO_LDD function:


As you can imagine, passing such a parameter comes with some cost (code size and execution cycles). And this is even more disappointing if I look at the source code of the function called:

** ===================================================================
**     Method      :  GREEN_ClrVal (component BitIO_LDD)
**     @brief
**         Clears (set to zero) the output value. It is equivalent to
**         the [PutVal(FALSE)]. This method is available only if the
**         direction = _[output]_ or _[input/output]_.
**     @param
**         DeviceDataPtr   - Pointer to device data
**                           structure returned by <Init> method.
/* ===================================================================*/
void GREEN_ClrVal(LDD_TDeviceData *DeviceDataPtr)
  (void)DeviceDataPtr;                 /* Parameter is not used, suppress unused argument warning */

We pass a parameter which is not used at all. :-(

Hacking Around the Device Parameter

If that parameter is not used, why enforce it at all in the API? That parameter would make sense if I want to have concurrent access to the peripheral (e.g. if I have an RTOS and multiple tasks that want to use a Bit I/O). But in my case I do not use an RTOS, and Processor Expert should know this. I would expect Processor Expert to take advantage of this knowledge, but at least up to MCU10.5 it does not. The good news is: I can hack around it. ;-)

The idea is to define macros like the ones below that do *not* need that device handle parameter:

#define RED_Clr()     GPIO_PDD_ClearPortDataOutputMask(RED_MODULE_BASE_ADDRESS, RED_PORT_MASK)
#define SW1_Get()     (GPIO_PDD_GetPortDataInput(SW1_MODULE_BASE_ADDRESS) & SW1_PORT_MASK)
define SW1_Get()      (GPIO_PDD_GetPortDataInput(SW2_MODULE_BASE_ADDRESS) & SW2_PORT_MASK)

The macros are what is implemented inside the methods (which are using the NULL parameter, but do not use it).

With this, I can change my original implementation from:

GREEN_ClrVal(GREEN_DeviceData); /* turn on green LED */
GREEN_SetVal(GREEN_DeviceData); /* turn off green LED */
for(;;) {
  if (SW1_GetVal(SW1_DeviceData)==0) { /* button low level => pressed */
    RED_ClrVal(RED_DeviceData); /* LED cathode is connected to microcontroller pin: low level turns it on */
    BLUE_SetVal(BLUE_DeviceData); /* turn off blue led */
  } else {
   RED_SetVal(RED_DeviceData); /* turn off red led */
   BLUE_ClrVal(BLUE_DeviceData); /* turn on blue led */
  if (SW2_GetVal(SW2_DeviceData)==0) { /* switch low level => pressed */
   BLUE_ClrVal(BLUE_DeviceData); /* turn on blue led */
  } else {
    BLUE_SetVal(BLUE_DeviceData); /* turn off blue led */

To this:

GREEN_Clr(); /* turn on green LED */
GREEN_Set(); /* turn off green LED */
for(;;) {
  if (SW1_Get()==0) { /* button low level => pressed */
    RED_Clr(); /* LED cathode is connected to microcontroller pin: low level turns it on */
    BLUE_Set(); /* turn off blue led */
  } else {
    RED_Set(); /* turn off red led */
    BLUE_Clr(); /* turn on blue led */
  if (SW2_Get()==0) { /* switch low level => pressed */
    BLUE_Clr(); /* turn on blue led */
  } else {
    BLUE_Set(); /* turn off blue led */

The positive impact: instead of 1544 bytes, the optimized version needs 1416 bytes of code for the application, about 10% less. :-)


The Processor Expert BitIO_LDD component requires a device handle passed to very function in its API, but this parameter is not used at all inside the functions if there is no RTOS used. Even with using an RTOS, and not needing concurrent access to the bits, the parameter is not necessary and only increases code size and code latency. But macros could be used to bypass this for better code efficiency without losing the advantage of using Processor Expert. It is just that these additional macros are hacking around something which Processor Expert should do out of the box.

:idea: It would be very cool if Processor Expert could have the property "do not use device handle pointer" or something similar. At least Processor Expert knows that it is not using the parameter, so I would expect it would create the API/macros as I did above for better code efficiency.

Happy Optimizing :-)

3 Steps to Monitoring in a Connected Enterprise. Check out xMatters.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}