Coulomb Counter API

Description

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, only EFP's DCDC are supported by this driver. The Coulomb counter driver provides an abstraction on top of the EFP 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_status_t err;
float charge;
if (err != SL_STATUS_OK) {
/* handle error */
}
/* get outputs that need to be calibrated */
/* Apply EM0 peak current configuration */
/* Apply EM2 peak current configuration */
/*
* wait for hardware to notify that operation is complete. When using
* interrupts, one can wait on the interrupt flag instead.
*/
}
}
/* handle error */
}
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 */
}

Functions

sl_status_t sl_coulomb_counter_int_enable (uint8_t flag)
 Enable interrupt.
 
sl_status_t sl_coulomb_counter_int_disable (uint8_t flag)
 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 sl_coulomb_counter_int_clear (uint8_t flag)
 Clear interrupt flag.
 
sl_status_t sl_coulomb_counter_init (void)
 Initialize Coulomb counter peripheral.
 
sl_status_t sl_coulomb_counter_start (void)
 Start counting coulombs.
 
sl_status_t sl_coulomb_counter_stop (void)
 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 sl_coulomb_counter_get_total_charge (void)
 Return total charge.
 
sl_coulomb_counter_output_mask_t sl_coulomb_counter_outputs_available (void)
 Return available outputs.
 
sl_coulomb_counter_output_mask_t sl_coulomb_counter_outputs_need_calibration (void)
 Return outputs that must be recalibrated.
 
sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate_init (sl_coulomb_counter_output_mask_t outputs_mask)
 Setup calibration for selected outputs.
 
sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate_wait (void)
 Wait for current step of the calibration routine to complete.
 
sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate (void)
 Step function for calibration.
 

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_INT_CALIBRATION_DONE   0x1
 Calibration done interrupt flag.
 
#define SL_COULOMB_COUNTER_INT_COUNTER_FULL   0x2
 Counter full interrupt flag.
 

Typedefs

typedef uint32_t sl_coulomb_counter_output_mask_t
 Bitmask of outputs to operate on.
 

Enumerations

enum  sl_coulomb_counter_prescaler_t {
  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_t {
  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_status_t {
  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.
 

Function Documentation

◆ sl_coulomb_counter_int_enable()

sl_status_t sl_coulomb_counter_int_enable ( uint8_t  flag)

Enable interrupt.

Parameters
[in]flagInterrupt flag to be enabled.
Returns
0 if successful, error code otherwise.

◆ sl_coulomb_counter_int_disable()

sl_status_t sl_coulomb_counter_int_disable ( uint8_t  flag)

Disable interrupt.

Parameters
[in]flagInterrupt flag to be disabled.
Returns
0 if successful, error code otherwise.

◆ 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]flagInterrupt flag to be checked.
[out]is_setBoolean with result.
Returns
0 if successful, error code otherwise.

◆ sl_coulomb_counter_int_clear()

sl_status_t sl_coulomb_counter_int_clear ( uint8_t  flag)

Clear interrupt flag.

Parameters
[in]flagInterrupt flag to be checked.
Returns
0 if successful, error code otherwise.

◆ sl_coulomb_counter_init()

sl_status_t sl_coulomb_counter_init ( void  )

Initialize Coulomb counter peripheral.

Returns
0 if successful, error code otherwise.

◆ sl_coulomb_counter_start()

sl_status_t sl_coulomb_counter_start ( void  )

Start counting coulombs.

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.

◆ sl_coulomb_counter_stop()

sl_status_t sl_coulomb_counter_stop ( void  )

Stop counting coulombs.

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.

◆ sl_coulomb_counter_read()

sl_status_t sl_coulomb_counter_read ( sl_coulomb_counter_output_mask_t outputs_need_calibration_mask)

Read coulomb counters.

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().

Warning
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.
Parameters
[out]outputs_need_calibration_maskWill contain mask of outputs that need to be recalibrated.
Returns
0 if successful, error code otherwise.

◆ 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_maskMask 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.

◆ sl_coulomb_counter_get_total_charge()

float sl_coulomb_counter_get_total_charge ( void  )

Return total charge.

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

Returns
Returns total charge for selected outputs.

◆ sl_coulomb_counter_outputs_available()

sl_coulomb_counter_output_mask_t sl_coulomb_counter_outputs_available ( void  )

Return available outputs.

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.

◆ 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.

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.

◆ 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.

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

Warning
During calibration, power consumption of the system must remain stable.
Parameters
[in]outputs_maskA mask of outputs to be calibrated.
Returns
SL_COULOMB_COUNTER_CALIBRATION_IN_PROGRESS if successful, SL_COULOMB_COUNTER_CALIBRATION_ERROR otherwise.

◆ 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.

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.

◆ sl_coulomb_counter_calibrate()

sl_coulomb_counter_calibration_status_t sl_coulomb_counter_calibrate ( void  )

Step function for calibration.

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.

Warning
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.

Macro Definition Documentation

◆ SL_COULOMB_COUNTER_OUTPUT_EFP_VOA

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOA   ((sl_coulomb_counter_output_mask_t)0x01)

EFP's Output VOA.

◆ SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM0

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM0   ((sl_coulomb_counter_output_mask_t)0x02)

EFP's Output VOB in EM0 mode.

◆ SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM2

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOB_EM2   ((sl_coulomb_counter_output_mask_t)0x04)

EFP's Output VOB in EM2 mode.

◆ SL_COULOMB_COUNTER_OUTPUT_EFP_VOC

#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOC   ((sl_coulomb_counter_output_mask_t)0x08)

EFP's Output VOC.

◆ SL_COULOMB_COUNTER_OUTPUT_ALL

#define SL_COULOMB_COUNTER_OUTPUT_ALL   ((sl_coulomb_counter_output_mask_t)0x0F)

All Outputs.

◆ SL_COULOMB_COUNTER_INT_CALIBRATION_DONE

#define SL_COULOMB_COUNTER_INT_CALIBRATION_DONE   0x1

Calibration done interrupt flag.

◆ SL_COULOMB_COUNTER_INT_COUNTER_FULL

#define SL_COULOMB_COUNTER_INT_COUNTER_FULL   0x2

Counter full interrupt flag.

Typedef Documentation

◆ sl_coulomb_counter_output_mask_t

Bitmask of outputs to operate on.

Enumeration Type Documentation

◆ 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.

◆ 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%.

◆ 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.