Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Working with configuration data is a common task when creating Industrial Communication devices. Therefore, GOAL comes with a module allowing to generically create variables of different types for storing configuration data. Once created, the GOAL CM will handle the data for us including storing and loading those data to and from a nonvolatile memory.

The available data types are:

  • GOAL_CM_UINT8: an unsigned 8 bit value

  • GOAL_CM_UINT16: an unsigned 16 bit value

  • GOAL_CM_UINT32: an unsigned 32 bit value

  • GOAL_CM_INT8: a signed 8 bit value

  • GOAL_CM_INT16: a signed 16 bit value

  • GOAL_CM_INT32: a signed 32 bit value

  • GOAL_CM_IPV4: an IPv4 address (32bit)

  • GOAL_CM_STRING: a null terminated string

  • GOAL_CM_GENERIC: a generic blob

Declaring variables

Variables are grouped in modules, so you can build logical groups of variables in your application.

...

Now the GOAL CM has to generate the enumeration of the variable IDs of each defined variable. The macro GOAL_CM_VAR_IDS will do this for us:

Code Block
/* generate 'enum APPL_CM_VARS_ID_T' that contains all variable names */
#include <goal_cm_id.h>
GOAL_CM_VAR_IDS(APPL_CM_VARS_ID_T, APPL_CM_VARS);

...

Thats it! GOAL CM now knows our variables and has reserved the according memory to store our values. It’s now time to set some initial values.

Reading and writing data

The GOAL CM module provides access functions to set and read values from our variables. First, lets set the initial baud rate for the serial interface to 115200 via goal_cmSetVarValue:

...

Code Block
    val32 = 0;
    res = goal_cmGetVarById(APPL_CM_MOD_ID, APPL_CM_VAR_BAUD, &pCmVar);
    if (GOAL_RES_ERR(res)) {
        goal_logErr("error reading baud rate");
    } else {
        goal_logInfo("current baud rate: %d" FMT_x32, GOAL_CM_VAR_UINT32(pCmVar));
    }

Please note that we used GOAL_CM_VAR_UINT32 to convert the data to the correct uint32 type of the actual architecture.

Validating variable values

But wait, shouldn’t we only accept valid values for our baud rate? Let’s assume our hardware guys have messed it up (again… 🤪) and our serial interface only works with 9600 and 115200. We can control which values are accepted using a validation callback for our variable. A validation callback is defined as:

...

Code Block
#define APPL_CM_VARS \
/*              Name,                  Data type,       Max. size,            Validation Cb,      Change Cb */   \
...
    GOAL_CM_VAR(APPL_CM_VAR_BAUD,      GOAL_CM_UINT32,  sizeof(uint32_t),     appl_baudVal,       appl_cmChg),   \
...    

Saving and loading values to/from nonvolatile memory

GOAL CM has built-in functionalities for writing a set of variables to nonvolatile memory like flash memory and those data can also be load.

Calling goal_cmSave stores the data of all modules using the specific target-dependent function goal_targetNvsWrite:

Code Block
/****************************************************************************/
/** Saves all variables to permanent storage using the appropriate target
 *  function
 *
 * @retval GOAL_OK Values saved
 * @retval other failed
 */
GOAL_STATUS_T goal_cmSaveImpl(
    void
);

To get the data back from storage, use goal_cmLoad which uses the target-specific goal_targetNvsReadData function:

Code Block
/****************************************************************************/
/** Loads the variables from permanent storage using the appropriate target
 *  function
 *
 * @retval GOAL_OK Values loaded
 * @retval other failed
 */
GOAL_STATUS_T goal_cmLoad(
    void
);

Virtual variables

When we think about our firmware revision variable GOAL_CM_FWVERSION, this would be normally a value that is “baked in” in our firmware itself, and not a value you would set and store.

For such uses cases, GOAL CM offers so called virtual variables. Those variables can be created using an API and are excluded from the storage functionality. To declare such a variable, use the function goal_cmRegVarVirtual:

Code Block
/****************************************************************************/
/** Register a callback to handle access to virtual variables of a specific
 * module id.
 *
 * @retval other failed
 */
GOAL_STATUS_T goal_cmRegVarVirtual(
    uint32_t modId,                             /**< module ID */
    uint32_t varId,                             /**< variable ID */
    GOAL_CM_DATATYPE_T type,                    /**< variable type */
    uint32_t sizeMax,                           /**< maximum size */
    goal_cm_validate validate,                  /**< validate callback */
    goal_cm_changed changed                     /**< change callback */
);

It gets the module id, the variable id, the data type, the max. data size and pointers to validation and change callbacks (null if not used) as parameters.

Note

Virtual variables can only be added to existing modules, as the module id must be known to GOAL CM prior calling goal_cmRegVarVirtual.

So let’s declare our firmware variable as virtual! First, remove the declaration from the variable list. Now we redeclare our variable as virtual:

Code Block
#define APPL_CM_FWVERSION_VIRTUAL_ID (1024)
...
    /* register virtual fw revision variable. Module must be known to the cm */
    res = goal_cmRegVarVirtual(APPL_CM_MOD_ID, APPL_CM_FWVERSION_VIRTUAL_ID, GOAL_CM_GENERIC, APPL_CM_STRING_LEN, NULL, NULL);
    if (GOAL_RES_ERR(res)) {
        goal_logErr("error registering virtual fw revision variable");
    }

That’s it! The firmware revision is now excluded from saving and loading. You just have to set the value at startup of your application.

Summary

In this tutorial, you’re learned how to use the GOAL CM to

  • declare modules and variables,

  • declare virtual variables and

  • and load and save variables to flash.