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#
Coulomb counter prescaler enum.
Coulomb counter threshold for counter full interrupt enum.
Coulomb counter calibration status enum.
Typedefs#
Bitmask of outputs to operate on.
Functions#
Enable interrupt.
Disable interrupt.
Check if interrupt flag is set.
Clear interrupt flag.
Initialize Coulomb counter peripheral.
Start counting coulombs.
Stop counting coulombs.
Read coulomb counters.
Return total charge only for selected outputs.
Return total charge.
Return available outputs.
Return outputs that must be recalibrated.
Setup calibration for selected outputs.
Wait for current step of the calibration routine to complete.
Step function for calibration.
Macros#
EFP's Output VOA.
EFP's Output VOB in EM0 mode.
EFP's Output VOB in EM2 mode.
EFP's Output VOC.
All Outputs.
All Outputs.
DCDC's Output VOB in EM0 mode.
DCDC's Output VOB in EM2 mode.
Calibration done interrupt flag.
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. |
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%. |
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. |
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.
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.
[in] | flag | Interrupt flag to be enabled. |
Returns
0 if successful, error code otherwise.
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.
[in] | flag | Interrupt flag to be disabled. |
Returns
0 if successful, error code otherwise.
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.
[in] | flag | Interrupt flag to be checked. |
[out] | is_set | Boolean with result. |
Returns
0 if successful, error code otherwise.
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.
[in] | flag | Interrupt flag to be checked. |
Returns
0 if successful, error code otherwise.
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.
N/A |
Returns
0 if successful, error code otherwise.
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.
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.
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.
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.
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.
[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.
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.
[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.
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.
N/A |
Return total charge for all outputs that were selected during initialization.
Returns
Returns total charge for selected outputs.
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.
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.
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.
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.
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.
[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.
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.
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.
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.
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.
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_VOAValue:
((sl_coulomb_counter_output_mask_t)0x01)
EFP's Output VOA.
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_EM0Value:
((sl_coulomb_counter_output_mask_t)0x02)
EFP's Output VOB in EM0 mode.
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_EM2Value:
((sl_coulomb_counter_output_mask_t)0x04)
EFP's Output VOB in EM2 mode.
64
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_OUTPUT_EFP_VOC#
#define SL_COULOMB_COUNTER_OUTPUT_EFP_VOCValue:
((sl_coulomb_counter_output_mask_t)0x08)
EFP's Output VOC.
66
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_OUTPUT_ALL#
#define SL_COULOMB_COUNTER_OUTPUT_ALLValue:
((sl_coulomb_counter_output_mask_t)0x0F)
All Outputs.
68
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_OUTPUT_ALL#
#define SL_COULOMB_COUNTER_OUTPUT_ALLValue:
((sl_coulomb_counter_output_mask_t)0x03)
All Outputs.
77
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_OUTPUT_DCDC_EM0#
#define SL_COULOMB_COUNTER_OUTPUT_DCDC_EM0Value:
((sl_coulomb_counter_output_mask_t)0x01)
DCDC's Output VOB in EM0 mode.
73
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_OUTPUT_DCDC_EM2#
#define SL_COULOMB_COUNTER_OUTPUT_DCDC_EM2Value:
((sl_coulomb_counter_output_mask_t)0x02)
DCDC's Output VOB in EM2 mode.
75
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_INT_CALIBRATION_DONE#
#define SL_COULOMB_COUNTER_INT_CALIBRATION_DONEValue:
0x1
Calibration done interrupt flag.
81
of file platform/driver/coulomb/inc/sl_coulomb_counter.h
SL_COULOMB_COUNTER_INT_COUNTER_FULL#
#define SL_COULOMB_COUNTER_INT_COUNTER_FULLValue:
0x2
Counter full interrupt flag.
83
of file platform/driver/coulomb/inc/sl_coulomb_counter.h