Coulomb Counter API#

Coulomb Counter Driver API.


Introduction#

DCDC converters use pulse-frequency modulation (PFM) to drive outputs. The Coulomb counter counts the number of PFM pulses delivered to each output. In order to get the total charge from an output, the charge-per-pulse (CPP) must be determined, then the total charge is computed like so: total_charge = CPP * Num_pulses.

Currently, EFP's DCDC and internal DCDC Coulomb counter (supported parts only) are supported by this driver. The Coulomb counter driver provides an abstraction on top of the Coulomb counter registers to make the calibration and reading the counters easier.


Calibration#

The goal of the calibration is to compute the charge-per-pulse value for each output. In order to achieve that, known loads are applied to outputs and the number of pulses are counted. More details can be found in application note AN1188: EFP01 Coulomb Counting.

One of the main assumption that is made to compute the CPP is that the system load current remains relatively constant during calibration, that means the application should not switch energy mode, start radio transmissions, etc. This is critical for calibration accuracy. If this is not followed, the driver will return inaccurate results.

Hardware is capable of calibrating only one output at a time. For each output, there are at least two measurements, one with low current and one with high current. In the worst case scenario, a measurement can take up to 6.5ms (that is 2^16, the size of the counter, divided by 10MHz, the oscillator frequency). So if several outputs are to be calibrated, it will happen sequentially, that means the calibration time is proportional to the number of outputs.


EM2 Output#

EFP's VOB output has different voltage and peak current configuration for EM0 and EM2 energy modes. This output can be used to power the DECOUPLE line of the MCU. It also has different Coulomb counters for these two energy modes. As peak current and output voltage are some of the parameters that determine the CPP, the output must be calibrated for each energy mode.

Typically, EM2 peak current and voltage are lower than those of EM0 for improved efficiency. In order to accurately compute the CPP, the Coulomb counter driver will request at some point during the calibration that the EM2 peak current configuration is applied. Application should take care of limiting actions that draw too much current during that time.


Recalibration#

A number of conditions can affect the CPP. Due to the following changes, a recalibraiton might be necessary for accurate results:

  • Significant change in input voltage

  • Change of output voltage

  • Change of output peak current

  • Change in energy mode

  • Change of DCDC operating mode

For the latter, the driver will report when such event is detected, to let the application know a recalibration must occur.


Configuration#

The Coulomb counter can be configured by using the configuration tool within Simplicity Studio. From there one can select the number of the EFP instance to use, which output to measure, prescaler and threshold values.


Usage#

The expected flow of execution is:

  • initialize the driver

  • calibrate

  • start the counters

  • periodically or interrupt-based event to read the counters

Initialization is done by calling sl_coulomb_counter_init(). It will prepare internal structure and setup communication with Coulomb counter device.

Calibration is the next step and is done in two folds, first the calibration is initialized by calling sl_coulomb_counter_calibrate_init() and then sl_coulomb_counter_calibrate() is called repeatedly until it reports an error or completion.

When calibration is done successfully, counters can be started by calling sl_coulomb_counter_start().

Then, periodically counters be read by calling sl_coulomb_counter_read(). This function has an output parameter to notify if some outputs must be recalibrated. That will happen in the output operates in a different DCDC mode than when it was calibrated. Note that when counters are read, they are cleared afterwards, so if the function is called too often, it will keep reading zeroes. This might be an issue for output that have a slowly increasing count of pulses, like VOB in EM2. To prevent that, one can wait for the interrupt threshold to be raised before reading registers.

Finally, to get the value of all outputs in Coulomb, call sl_coulomb_counter_get_total_charge(). If interested in only one or more outputs, use sl_coulomb_counter_get_charge() instead.

Here is a complete example:

sl_coulomb_counter_calibration_status_t status;
sl_coulomb_counter_output_mask_t outputs;
sl_status_t err;
float charge;

err = sl_coulomb_counter_init();
if (err != SL_STATUS_OK) {
  /* handle error */
}

/* get outputs that need to be calibrated */
outputs = sl_coulomb_counter_outputs_need_calibration();
status = sl_coulomb_counter_calibrate_init(outputs);

while (status == SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS
       || status == SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM0
       || status == SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM2) {

  status = sl_coulomb_counter_calibrate();

  if (status == SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM0) {
    /* Apply EM0 peak current configuration */
  } else if (status == SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM2) {
    /* Apply EM2 peak current configuration */
  } else if (status == SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS) {
    /*
     * wait for hardware to notify that operation is complete. When using
     * interrupts, one can wait on the interrupt flag instead.
     */
    status = sl_coulomb_counter_calibrate_wait();
  }
}

if (status != SL_COULOMB_COUNTER_CALIBRATION_DONE) {
  /* handle error */
}

err = sl_coulomb_counter_start();
if (err != SL_STATUS_OK) {
  /* handle error */
}

/*
 * outputs is a bitmask of outputs that need recalibration because DCDC
 * operation mode changed. If some bits are set, Coulomb counter must be stop
 * and corresponding outputs recalibrated.
 */
err = sl_coulomb_counter_read(&outputs);
if (err != SL_STATUS_OK) {
  /* handle error */
}

float = sl_coulomb_counter_get_total_charge();

Enumerations#

enum
SL_COULOMB_COUNTER_PRESCALER_ZERO
SL_COULOMB_COUNTER_PRESCALER_ONE
SL_COULOMB_COUNTER_PRESCALER_TWO
SL_COULOMB_COUNTER_PRESCALER_THREE
}

Coulomb counter prescaler enum.

enum
SL_COULOMB_COUNTER_THRESHOLD_50
SL_COULOMB_COUNTER_THRESHOLD_62
SL_COULOMB_COUNTER_THRESHOLD_75
SL_COULOMB_COUNTER_THRESHOLD_87
}

Coulomb counter threshold for counter full interrupt enum.

enum
SL_COULOMB_COUNTER_CALIBRATION_ERROR
SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS
SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM0
SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM2
SL_COULOMB_COUNTER_CALIBRATION_DONE
}

Coulomb counter calibration status enum.

Typedefs#

typedef uint32_t

Bitmask of outputs to operate on.

Functions#

sl_status_t

Enable interrupt.

sl_status_t

Disable interrupt.

sl_status_t
sl_coulomb_counter_int_is_set(uint8_t flag, bool *is_set)

Check if interrupt flag is set.

sl_status_t

Clear interrupt flag.

sl_status_t

Initialize Coulomb counter peripheral.

sl_status_t

Start counting coulombs.

sl_status_t

Stop counting coulombs.

sl_status_t
sl_coulomb_counter_read(sl_coulomb_counter_output_mask_t *outputs_need_calibration_mask)

Read coulomb counters.

float
sl_coulomb_counter_get_charge(sl_coulomb_counter_output_mask_t outputs_mask)

Return total charge only for selected outputs.

float

Return total charge.

sl_coulomb_counter_calibrate_init(sl_coulomb_counter_output_mask_t outputs_mask)

Setup calibration for selected outputs.

Wait for current step of the calibration routine to complete.

Macros#

#define
SL_COULOMB_COUNTER_OUTPUT_EFP_VOA ((sl_coulomb_counter_output_mask_t)0x01)

EFP's Output VOA.

#define
SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM0 ((sl_coulomb_counter_output_mask_t)0x02)

EFP's Output VOB in EM0 mode.

#define
SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM2 ((sl_coulomb_counter_output_mask_t)0x04)

EFP's Output VOB in EM2 mode.

#define
SL_COULOMB_COUNTER_OUTPUT_EFP_VOC ((sl_coulomb_counter_output_mask_t)0x08)

EFP's Output VOC.

#define
SL_COULOMB_COUNTER_OUTPUT_ALL ((sl_coulomb_counter_output_mask_t)0x0F)

All Outputs.

#define
SL_COULOMB_COUNTER_OUTPUT_ALL ((sl_coulomb_counter_output_mask_t)0x03)

All Outputs.

#define
SL_COULOMB_COUNTER_OUTPUT_DCDC_EM0 ((sl_coulomb_counter_output_mask_t)0x01)

DCDC's Output VOB in EM0 mode.

#define
SL_COULOMB_COUNTER_OUTPUT_DCDC_EM2 ((sl_coulomb_counter_output_mask_t)0x02)

DCDC's Output VOB in EM2 mode.

#define

Calibration done interrupt flag.

#define

Counter full interrupt flag.

Enumeration Documentation#

sl_coulomb_counter_prescaler_t#

sl_coulomb_counter_prescaler_t

Coulomb counter prescaler enum.

Each count in the counter results registers represents 2^(16 - 2 * prescaler).

Enumerator
SL_COULOMB_COUNTER_PRESCALER_ZERO

Set prescaler to 0.

SL_COULOMB_COUNTER_PRESCALER_ONE

Set prescaler to 1.

SL_COULOMB_COUNTER_PRESCALER_TWO

Set prescaler to 2.

SL_COULOMB_COUNTER_PRESCALER_THREE

Set prescaler to 3.


Definition at line 94 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_threshold_t#

sl_coulomb_counter_threshold_t

Coulomb counter threshold for counter full interrupt enum.

Expressed in percentage, the interrupt full interrupt will be raised (if unmasked) when at least one of the counters reaches that threshold.

Enumerator
SL_COULOMB_COUNTER_THRESHOLD_50

Set threshold to 50%.

SL_COULOMB_COUNTER_THRESHOLD_62

Set threshold to 62.5%.

SL_COULOMB_COUNTER_THRESHOLD_75

Set threshold to 75%.

SL_COULOMB_COUNTER_THRESHOLD_87

Set threshold to 87.5%.


Definition at line 107 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_calibration_status_t#

sl_coulomb_counter_calibration_status_t

Coulomb counter calibration status enum.

Enumerator
SL_COULOMB_COUNTER_CALIBRATION_ERROR

An error occured during calibration.

SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS

Calibration is in progress.

SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM0

User must set peak current to EM0 value.

SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM2

User must set peak current to EM2 value.

SL_COULOMB_COUNTER_CALIBRATION_DONE

Calibration is done.


Definition at line 115 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

Typedef Documentation#

sl_coulomb_counter_output_mask_t#

typedef uint32_t sl_coulomb_counter_output_mask_t

Bitmask of outputs to operate on.


Definition at line 86 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

Function Documentation#

sl_coulomb_counter_int_enable#

sl_status_t sl_coulomb_counter_int_enable (uint8_t flag)

Enable interrupt.

Parameters
[in]flag

Interrupt flag to be enabled.

Returns

  • 0 if successful, error code otherwise.


Definition at line 137 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_int_disable#

sl_status_t sl_coulomb_counter_int_disable (uint8_t flag)

Disable interrupt.

Parameters
[in]flag

Interrupt flag to be disabled.

Returns

  • 0 if successful, error code otherwise.


Definition at line 149 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_int_is_set#

sl_status_t sl_coulomb_counter_int_is_set (uint8_t flag, bool * is_set)

Check if interrupt flag is set.

Parameters
[in]flag

Interrupt flag to be checked.

[out]is_set

Boolean with result.

Returns

  • 0 if successful, error code otherwise.


Definition at line 164 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_int_clear#

sl_status_t sl_coulomb_counter_int_clear (uint8_t flag)

Clear interrupt flag.

Parameters
[in]flag

Interrupt flag to be checked.

Returns

  • 0 if successful, error code otherwise.


Definition at line 176 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_init#

sl_status_t sl_coulomb_counter_init (void )

Initialize Coulomb counter peripheral.

Parameters
N/A

Returns

  • 0 if successful, error code otherwise.


Definition at line 185 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_start#

sl_status_t sl_coulomb_counter_start (void )

Start counting coulombs.

Parameters
N/A

This starts the coulomb counter. Outputs selected for measurements must be calibrated when this function is called, or it will fail. When counting, calibration is not permitted.

Returns

  • 0 if successful, error code otherwise.


Definition at line 199 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_stop#

sl_status_t sl_coulomb_counter_stop (void )

Stop counting coulombs.

Parameters
N/A

This stops the coulomb counter. Note that the counter must be stopped before calling sl_coulomb_counter_calibrate().

Returns

  • 0 if successful, error code otherwise.


Definition at line 212 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_read#

sl_status_t sl_coulomb_counter_read (sl_coulomb_counter_output_mask_t * outputs_need_calibration_mask)

Read coulomb counters.

Parameters
[out]outputs_need_calibration_mask

Will contain mask of outputs that need to be recalibrated.

Read coulomb counters for all outputs selected via configuration header. Note that all outputs must be read at once, as counters are automatically cleared after reading. Values read are accumulated into internal counters. Each count in the counters represents 2^(16 - 2 * prescaler) PFM pulses. This function only reads the counters registers and accumulate these values with counters stored in the driver, to get the charge, one must call sl_coulomb_counter_get_charge() or sl_coulomb_counter_get_total_charge().

Warnings

  • Some counters increment slowly, especially when counting in EM2 mode, so if this function is called in a tight loop, it is possible that it keeps reading 0 because the number of PFM pulses is never high enough to reach 2^(16 - 2 * prescaler) and because counters are cleared after being read. That can lead to some PFM cycles not being counted, thus inaccurate results.

Note

  • Outputs' modes of operation can change between two reads. If that happens, counters will be accumulated with current calibration settings, and outputs will be set in the out parameter. Subsequent reads of these outputs will be skipped until they are recalibrated.

Returns

  • 0 if successful, error code otherwise.


Definition at line 248 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_get_charge#

float sl_coulomb_counter_get_charge (sl_coulomb_counter_output_mask_t outputs_mask)

Return total charge only for selected outputs.

Parameters
[in]outputs_mask

Mask of outputs.

Return total charge that has flown through selected outputs. This is computed using values accumulated via sl_coulomb_counter_read() and calibration settings.

Returns

  • Returns total charge for selected outputs.


Definition at line 265 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_get_total_charge#

float sl_coulomb_counter_get_total_charge (void )

Return total charge.

Parameters
N/A

Return total charge for all outputs that were selected during initialization.

Returns

  • Returns total charge for selected outputs.


Definition at line 277 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_outputs_available#

sl_coulomb_counter_output_mask_t sl_coulomb_counter_outputs_available (void )

Return available outputs.

Parameters
N/A

Depending on the configuration option, this driver use different peripherals for Coulomb counting. This function returns outputs that are available on the selected peripheral.

Returns

  • Returns a mask of available outputs for the selected peripheral.


Definition at line 291 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_outputs_need_calibration#

sl_coulomb_counter_output_mask_t sl_coulomb_counter_outputs_need_calibration (void )

Return outputs that must be recalibrated.

Parameters
N/A

Some events might require an output to be recalibrated to correctly measure the charge, for instance, if a DCDC changes its operating mode.

Returns

  • Returns a mask of outputs that needs to be recalibrated.


Definition at line 304 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_calibrate_init#

sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate_init (sl_coulomb_counter_output_mask_t outputs_mask)

Setup calibration for selected outputs.

Parameters
[in]outputs_mask

A mask of outputs to be calibrated.

Calibrate, or recalibrate, selected outputs. The counter must be off for calibration to be possible.

Warnings

  • During calibration, power consumption of the system must remain stable.

Returns

  • SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS if successful, SL_COULOMB_COUNTER_CALIBRATION_ERROR otherwise.


Definition at line 324 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_calibrate_wait#

sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate_wait (void )

Wait for current step of the calibration routine to complete.

Parameters
N/A

This routine waits for the current calibration step to complete before returning. When calibrating in polling mode, this function must be called when sl_coulomb_counter_calibrate() returns SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS. When calibrating in interrupt mode, this function is not used.

Returns

  • SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS if successful, SL_COULOMB_COUNTER_CALIBRATION_ERROR otherwise.


Definition at line 341 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

sl_coulomb_counter_calibrate#

sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate (void )

Step function for calibration.

Parameters
N/A

This function is to be called repeatedly either from a loop or from interrupt handler (when STATUS_G.CCC_ISDONE is set) to iterate over the calibration process.

Warnings

  • During calibration, power consumption of the system must remain stable.

Returns

  • SL_COULOMB_COUNTER_CALIBRATION_DONE when calibration is complete; or SL_COULOMB_COUNTER_CALIBRATION_ERROR in case of error; or SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM0 or SL_COULOMB_COUNTER_CALIBRATION_PEAK_CURRENT_EM2 if the peak current must be changed; or SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS. In last three cases, sl_coulomb_counter_calibrate() must be called again to continue the calibration process.


Definition at line 365 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

Macro Definition Documentation#

SL_COULOMB_COUNTER_OUTPUT_EFP_VOA#

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOA
Value:
((sl_coulomb_counter_output_mask_t)0x01)

EFP's Output VOA.


Definition at line 60 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM0#

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM0
Value:
((sl_coulomb_counter_output_mask_t)0x02)

EFP's Output VOB in EM0 mode.


Definition at line 62 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM2#

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM2
Value:
((sl_coulomb_counter_output_mask_t)0x04)

EFP's Output VOB in EM2 mode.


Definition at line 64 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_EFP_VOC#

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOC
Value:
((sl_coulomb_counter_output_mask_t)0x08)

EFP's Output VOC.


Definition at line 66 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_ALL#

#define SL_COULOMB_COUNTER_OUTPUT_ALL
Value:
((sl_coulomb_counter_output_mask_t)0x0F)

All Outputs.


Definition at line 68 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_ALL#

#define SL_COULOMB_COUNTER_OUTPUT_ALL
Value:
((sl_coulomb_counter_output_mask_t)0x03)

All Outputs.


Definition at line 77 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_DCDC_EM0#

#define SL_COULOMB_COUNTER_OUTPUT_DCDC_EM0
Value:
((sl_coulomb_counter_output_mask_t)0x01)

DCDC's Output VOB in EM0 mode.


Definition at line 73 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_OUTPUT_DCDC_EM2#

#define SL_COULOMB_COUNTER_OUTPUT_DCDC_EM2
Value:
((sl_coulomb_counter_output_mask_t)0x02)

DCDC's Output VOB in EM2 mode.


Definition at line 75 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_INT_CALIBRATION_DONE#

#define SL_COULOMB_COUNTER_INT_CALIBRATION_DONE
Value:
0x1

Calibration done interrupt flag.


Definition at line 81 of file platform/driver/coulomb/inc/sl_coulomb_counter.h

SL_COULOMB_COUNTER_INT_COUNTER_FULL#

#define SL_COULOMB_COUNTER_INT_COUNTER_FULL
Value:
0x2

Counter full interrupt flag.


Definition at line 83 of file platform/driver/coulomb/inc/sl_coulomb_counter.h