Skip to content

Commit 823693c

Browse files
committed
drivers: sensor: pmc_tmpsns: Reduce floating-point operations
Reduce floating-point operations in the nxp_pmc_tmpsns. Provide new calculation method without floating-point operations. Signed-off-by: Zhaoxiang Jin <[email protected]>
1 parent d3d9a88 commit 823693c

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

drivers/sensor/nxp/nxp_pmc_tmpsns/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,14 @@ config NXP_PMC_TMPSNS_CALIBRATION_OTP_FUSE_INDEX
1818
TSENS_CAL is an 8-bit signed calibration constant
1919
retrieved from non-volatile memory. We need this
2020
index to read the fuse to get TSENS_CAL.
21+
22+
config NXP_PMC_TMPSNS_USE_FLOAT_CALC
23+
bool "Use float and FPU"
24+
default y
25+
help
26+
When enabled, the driver performs more floating-point
27+
calculations. If your SoC has an FPU, it is recommended
28+
to select this option. Testing has shown that enabling
29+
this option results in shorter code execution times.
30+
2131
endif

drivers/sensor/nxp/nxp_pmc_tmpsns/nxp_pmc_tmpsns.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,25 @@
1010
#include <zephyr/drivers/sensor.h>
1111
#include <zephyr/drivers/adc.h>
1212
#include <zephyr/logging/log.h>
13+
#include <zephyr/sys/util.h>
1314

1415
LOG_MODULE_REGISTER(nxp_pmc_tmpsns, CONFIG_SENSOR_LOG_LEVEL);
1516

1617
#define DT_DRV_COMPAT nxp_pmc_tmpsns
1718

19+
#if !CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
20+
/* Scale factor for 3 decimal places */
21+
#define NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR 1000
22+
/* For intermediate calculations */
23+
#define NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR_LARGE 1000000
24+
25+
#define NXP_PMC_TMPSNS_TEMP_KELVIN_TO_CELSIUS_SCALED 273150 /* 273.15 * 1000 */
26+
#define NXP_PMC_TMPSNS_TEMP_COEFFICIENT_SCALED 370980 /* 370.98 * 1000 */
27+
#define NXP_PMC_TMPSNS_VREF_BASE_OFFSET_SCALED 953360 /* 953.36 * 1000 */
28+
#define NXP_PMC_TMPSNS_VREF_SCALE_FACTOR 2048 /* Already an integer */
29+
#define NXP_PMC_TMPSNS_CALIBRATION_MASK 0xFF
30+
#endif
31+
1832
struct nxp_pmc_tmpsns_config {
1933
const struct device *adc;
2034
struct adc_sequence adc_seq;
@@ -27,14 +41,80 @@ struct nxp_pmc_tmpsns_data {
2741
float pmc_tmpsns_value;
2842
};
2943

44+
#if !CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
45+
/**
46+
* Calculate weighted average for CTAT using integer arithmetic
47+
* Result is scaled by 1000 for precision.
48+
*/
49+
static inline int32_t calculate_cm_ctat_int(const int16_t *values)
50+
{
51+
int32_t sum = (2 * values[1] - values[2] +
52+
2 * values[13] - values[12] +
53+
2 * values[6] - values[5] +
54+
2 * values[8] - values[9]);
55+
56+
return (sum * 250);
57+
}
58+
59+
/**
60+
* Calculate weighted average for temperature using integer arithmetic
61+
* Result is scaled by 1000 for precision.
62+
*/
63+
static inline int32_t calculate_cm_temp_int(const int16_t *values)
64+
{
65+
int32_t sum = (2 * values[0] - values[3] +
66+
2 * values[14] - values[11] +
67+
4 * values[7] - values[4] - values[10]);
68+
69+
return (sum * 250);
70+
}
71+
72+
/**
73+
* Calculate temperature in millidegrees Celsius using integer arithmetic.
74+
*/
75+
static int32_t get_temperature_millidegrees(struct nxp_pmc_tmpsns_data *data,
76+
const int16_t *pmc_tmpsns_value)
77+
{
78+
if (!data || !pmc_tmpsns_value) {
79+
return -EINVAL;
80+
}
81+
82+
/* Calculate temperature sensor components (scaled by 1000) */
83+
int32_t cm_ctat_scaled = calculate_cm_ctat_int(pmc_tmpsns_value);
84+
int32_t cm_temp_scaled = calculate_cm_temp_int(pmc_tmpsns_value);
85+
86+
/* Extract calibration value */
87+
int32_t calibration = (int8_t)(data->pmc_tmpsns_calibration &
88+
NXP_PMC_TMPSNS_CALIBRATION_MASK);
89+
90+
/* Calculate reference voltage with calibration */
91+
int64_t vref_numerator = (int64_t)(NXP_PMC_TMPSNS_VREF_BASE_OFFSET_SCALED +
92+
calibration * NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR) * cm_temp_scaled;
93+
int32_t cm_vref_scaled = cm_ctat_scaled + (int32_t)(vref_numerator /
94+
(NXP_PMC_TMPSNS_VREF_SCALE_FACTOR * NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR));
95+
96+
if (cm_vref_scaled == 0) {
97+
return -EINVAL;
98+
}
99+
100+
/* Calculate temperature in millidegrees Celsius */
101+
int64_t temp_ratio = ((int64_t)NXP_PMC_TMPSNS_TEMP_COEFFICIENT_SCALED *
102+
cm_temp_scaled) / cm_vref_scaled;
103+
104+
return (int32_t)temp_ratio - NXP_PMC_TMPSNS_TEMP_KELVIN_TO_CELSIUS_SCALED;
105+
}
106+
#endif
107+
30108
static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_channel chan)
31109
{
32110
uint8_t pmc_tmpsns_select[15] = {0, 1, 3, 2, 6, 7, 5, 4, 5, 7, 6, 2, 3, 1, 0};
33111
const struct nxp_pmc_tmpsns_config *config = dev->config;
34112
struct nxp_pmc_tmpsns_data *data = dev->data;
35113
uint16_t pmc_tmpsns_value[15] = {0};
114+
#if CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
36115
float cm_vref, cm_ctat, cm_temp;
37116
int8_t calibration = 0;
117+
#endif
38118
int ret;
39119

40120
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
@@ -52,6 +132,7 @@ static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_cha
52132
pmc_tmpsns_value[index] = data->buffer;
53133
}
54134

135+
#if CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
55136
cm_ctat = (float)(2 * pmc_tmpsns_value[1] - pmc_tmpsns_value[2] +
56137
2 * pmc_tmpsns_value[13] - pmc_tmpsns_value[12] +
57138
2 * pmc_tmpsns_value[6] - pmc_tmpsns_value[5] +
@@ -67,6 +148,9 @@ static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_cha
67148
cm_vref = cm_ctat + (953.36f + calibration) * cm_temp / 2048;
68149

69150
data->pmc_tmpsns_value = 370.98f * (cm_temp / cm_vref) - 273.15f;
151+
#else
152+
data->pmc_tmpsns_value = get_temperature_millidegrees(data, pmc_tmpsns_value) / 1000.0f;
153+
#endif
70154

71155
return 0;
72156
}

0 commit comments

Comments
 (0)