1 /*
2 * Copyright 2020-2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_tempsensor.h"
10 #include "math.h"
11
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15
16 /* Component ID definition, used by tools. */
17 #ifndef FSL_COMPONENT_ID
18 #define FSL_COMPONENT_ID "platform.drivers.tempsensor"
19 #endif
20
21 /*******************************************************************************
22 * Prototypes
23 ******************************************************************************/
24 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
25 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data);
26 static uint32_t TMPSNS_AIReadAccess(uint32_t address);
27 #endif
28
29 /*******************************************************************************
30 * Variables
31 ******************************************************************************/
32 const static float s_Ts20 = 133.6f;
33 const static float s_Ts21 = -5.39f;
34 const static float s_Ts21_2 = 29.0521f; /*!< It means (s_Ts21* s_Ts21) */
35 const static float s_Ts22 = 0.002f;
36 static float s_Ts25c;
37
38 /*******************************************************************************
39 * Code
40 ******************************************************************************/
41 /*!
42 * brief Initializes the TMPSNS module.
43 *
44 * param base TMPSNS base pointer
45 * param config Pointer to configuration structure.
46 */
47
TMPSNS_Init(TMPSNS_Type * base,const tmpsns_config_t * config)48 void TMPSNS_Init(TMPSNS_Type *base, const tmpsns_config_t *config)
49 {
50 assert(NULL != config);
51 uint32_t controlVal = 0x00U;
52 uint32_t temp;
53
54 temp =
55 (ANADIG_TEMPSENSOR_TEMPSNS_OTP_TRIM_VALUE_TEMPSNS_TEMP_VAL_MASK & ANADIG_TEMPSENSOR->TEMPSNS_OTP_TRIM_VALUE) >>
56 10;
57 s_Ts25c = (float)temp;
58
59 if (config->measureMode == kTEMPSENSOR_SingleMode)
60 {
61 controlVal = TMPSNS_CTRL1_FREQ(0x00U);
62 }
63 else if (config->measureMode == kTEMPSENSOR_ContinuousMode)
64 {
65 controlVal = TMPSNS_CTRL1_FREQ(config->frequency);
66 }
67 else
68 {
69 ; /* Intentional empty for MISRA C-2012 rule 15.7*/
70 }
71
72 /* Enable finish interrupt status */
73 controlVal |= TMPSNS_CTRL1_FINISH_IE_MASK;
74 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
75 /* Power up the temperature sensor */
76 controlVal &= ~TMPSNS_CTRL1_PWD_MASK;
77 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
78 #else
79 base->CTRL1 |= controlVal;
80 /* Power up the temperature sensor */
81 base->CTRL1 &= ~TMPSNS_CTRL1_PWD_MASK;
82 #endif
83
84 /* Set alarm temperature */
85 TMPSNS_SetTempAlarm(base, config->highAlarmTemp, kTEMPMON_HighAlarmMode);
86 TMPSNS_SetTempAlarm(base, config->panicAlarmTemp, kTEMPMON_PanicAlarmMode);
87 TMPSNS_SetTempAlarm(base, config->lowAlarmTemp, kTEMPMON_LowAlarmMode);
88 }
89
90 /*!
91 * brief Deinitializes the TMPSNS module.
92 *
93 * param base TMPSNS base pointer
94 */
TMPSNS_Deinit(TMPSNS_Type * base)95 void TMPSNS_Deinit(TMPSNS_Type *base)
96 {
97 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
98 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), TMPSNS_CTRL1_PWD_MASK);
99 #else
100 base->CTRL1 |= TMPSNS_CTRL1_PWD_MASK;
101 #endif
102 }
103
104 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
105 /*!
106 * brief AI interface write access.
107 *
108 * param base TMPSNS base pointer
109 */
TMPSNS_AIWriteAccess(uint32_t address,uint32_t data)110 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data)
111 {
112 /* AI bridge setting: AIRWB and ADDR
113 Write: 0x00
114 Address: offset from base address
115 */
116 ANADIG_MISC->VDDLPSR_AI_CTRL = (0x00UL << 16) | (address & 0xFFFFU);
117 /* Write data into related register through AI bridge */
118 ANADIG_MISC->VDDLPSR_AI_WDATA = data;
119 /* AI toggle */
120 ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
121 }
122
123 /*!
124 * brief AI interface read access.
125 *
126 * param base TMPSNS base pointer
127 */
TMPSNS_AIReadAccess(uint32_t address)128 static uint32_t TMPSNS_AIReadAccess(uint32_t address)
129 {
130 uint32_t ret;
131
132 /* AI bridge setting: AIRWB and ADDR
133 Read: 0x01
134 Address: offset from base address
135 */
136 ANADIG_MISC->VDDLPSR_AI_CTRL = (0x01UL << 16) | (address & 0xFFFFU);
137 /* AI toggle */
138 ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
139 /* Read data from related register through AI bridge */
140 ret = ANADIG_MISC->VDDLPSR_AI_RDATA_TMPSNS;
141
142 return ret;
143 }
144 #endif /* FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
145
146 /*!
147 * brief Gets the default configuration structure.
148 *
149 * This function initializes the TMPSNS configuration structure to a default value. The default
150 * values are:
151 * tempmonConfig->frequency = 0x00U;
152 * tempmonConfig->highAlarmTemp = 25U;
153 * tempmonConfig->panicAlarmTemp = 80U;
154 * tempmonConfig->lowAlarmTemp = 20U;
155 *
156 * param config Pointer to a configuration structure.
157 */
TMPSNS_GetDefaultConfig(tmpsns_config_t * config)158 void TMPSNS_GetDefaultConfig(tmpsns_config_t *config)
159 {
160 assert(config);
161
162 /* Initializes the configure structure to zero. */
163 (void)memset(config, 0, sizeof(*config));
164
165 /* Default measurement mode */
166 config->measureMode = kTEMPSENSOR_SingleMode;
167 /* Default measure frequency */
168 config->frequency = 0x00U;
169 /* Default high alarm temperature */
170 config->highAlarmTemp = 25;
171 /* Default panic alarm temperature */
172 config->panicAlarmTemp = 80;
173 /* Default low alarm temperature */
174 config->lowAlarmTemp = 5;
175 }
176
177 /*!
178 * @brief start the temperature measurement process.
179 *
180 * @param base TMPSNS base pointer.
181 */
TMPSNS_StartMeasure(TMPSNS_Type * base)182 void TMPSNS_StartMeasure(TMPSNS_Type *base)
183 {
184 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
185 uint32_t controlVal;
186 /* Read CTRL1 value*/
187 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
188 /* Start measurement */
189 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal | TMPSNS_CTRL1_SET_START_MASK);
190 #else
191 base->CTRL1 |= TMPSNS_CTRL1_SET_START_MASK;
192 #endif
193 }
194
195 /*!
196 * @brief stop the measurement process.
197 *
198 * @param base TMPSNS base pointer
199 */
TMPSNS_StopMeasure(TMPSNS_Type * base)200 void TMPSNS_StopMeasure(TMPSNS_Type *base)
201 {
202 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
203 uint32_t controlVal;
204 /* Read CTRL1 value*/
205 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
206 /* Start measurement */
207 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal & (~TMPSNS_CTRL1_SET_START_MASK));
208 #else
209 base->CTRL1 &= ~TMPSNS_CTRL1_SET_START_MASK;
210 #endif
211 }
212
213 /*!
214 * brief Get current temperature with the fused temperature calibration data.
215 *
216 * param base TMPSNS base pointer
217 * return current temperature with degrees Celsius.
218 */
TMPSNS_GetCurrentTemperature(TMPSNS_Type * base)219 float TMPSNS_GetCurrentTemperature(TMPSNS_Type *base)
220 {
221 uint32_t measureTempVal;
222 float actualTempVal;
223
224 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
225 /* Waiting for measurement finished */
226 while (0U == (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_FINISH_MASK))
227 {
228 }
229 /* Ready to read measured temperature value */
230 measureTempVal = (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_TEMP_VAL_MASK) >>
231 TMPSNS_STATUS0_TEMP_VAL_SHIFT;
232 #else
233 /* Waiting for measurement finished */
234 while (0U == (base->STATUS0 & TMPSNS_STATUS0_FINISH_MASK))
235 {
236 }
237 /* Ready to read measured temperature value */
238 measureTempVal = (base->STATUS0 & TMPSNS_STATUS0_TEMP_VAL_MASK) >> TMPSNS_STATUS0_TEMP_VAL_SHIFT;
239 #endif
240
241 /* Calculate actual temperature */
242 actualTempVal =
243 (-s_Ts21 - sqrtf(s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c - (float)measureTempVal))) / (2.0f * s_Ts22);
244
245 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
246 uint32_t statusVal;
247 /* Read STATUS0 value */
248 statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
249 /* Clear the FINISH flag */
250 TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0), statusVal | TMPSNS_STATUS0_FINISH_MASK);
251 #else
252 /* Clear the FINISH flag */
253 base->STATUS0 |= TMPSNS_STATUS0_FINISH_MASK;
254 #endif
255
256 return actualTempVal;
257 }
258
259 /*!
260 * brief Set the temperature count (raw sensor output) that will generate an alarm interrupt.
261 *
262 * param base TMPSNS base pointer
263 * param tempVal The alarm temperature with degrees Celsius
264 * param alarmMode The alarm mode.
265 */
TMPSNS_SetTempAlarm(TMPSNS_Type * base,int32_t tempVal,tmpsns_alarm_mode_t alarmMode)266 void TMPSNS_SetTempAlarm(TMPSNS_Type *base, int32_t tempVal, tmpsns_alarm_mode_t alarmMode)
267 {
268 float temp;
269 int32_t tempCodeVal;
270 uint32_t tempRegVal;
271
272 /* Calculate alarm temperature code value */;
273 temp = (-2.0f * s_Ts22 * (float)tempVal - s_Ts21) * (-2.0f * s_Ts22 * (float)tempVal - s_Ts21);
274 temp = (temp - (s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c))) / (4.0f * s_Ts22);
275 tempCodeVal = (int32_t)temp;
276
277 switch (alarmMode)
278 {
279 case kTEMPMON_HighAlarmMode:
280 /* Clear alarm value and set a new high alarm temperature code value */
281 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
282 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
283 tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
284 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0), tempRegVal);
285 #else
286 tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
287 base->RANGE0 = tempRegVal;
288 #endif
289 /* Enable high temperature interrupt */
290 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_HighTempInterruptStatusEnable);
291 break;
292
293 case kTEMPMON_PanicAlarmMode:
294 /* Clear panic alarm value and set a new panic alarm temperature code value */
295 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
296 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE1));
297 tempRegVal = (tempRegVal & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
298 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE1), tempRegVal);
299 #else
300 tempRegVal =
301 (base->RANGE1 & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
302 base->RANGE1 = tempRegVal;
303 #endif
304 /* Enable panic temperature interrupt */
305 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_PanicTempInterruptStatusEnable);
306 break;
307
308 case kTEMPMON_LowAlarmMode:
309 /* Clear low alarm value and set a new low alarm temperature code value */
310 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
311 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
312 tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
313 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0_SET), tempRegVal);
314 #else
315 tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
316 base->RANGE0 = tempRegVal;
317 #endif
318 /* Enable low temperature interrupt */
319 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_LowTempInterruptStatusEnable);
320 break;
321
322 default:
323 assert(false);
324 break;
325 }
326 }
327
328 /*!
329 * brief Enable interrupt status.
330 *
331 * param base TMPSNS base pointer
332 * param mask The interrupts to enable from tmpsns_interrupt_status_enable_t.
333 */
TMPSNS_EnableInterrupt(TMPSNS_Type * base,uint32_t mask)334 void TMPSNS_EnableInterrupt(TMPSNS_Type *base, uint32_t mask)
335 {
336 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
337 uint32_t tempRegVal;
338 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
339 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal | mask);
340 #else
341 base->CTRL1 |= mask;
342 #endif
343 }
344
345 /*!
346 * brief Disable interrupt status.
347 *
348 * param base TMPSNS base pointer
349 * param mask The interrupts to disable from tmpsns_interrupt_status_enable_t.
350 */
TMPSNS_DisableInterrupt(TMPSNS_Type * base,uint32_t mask)351 void TMPSNS_DisableInterrupt(TMPSNS_Type *base, uint32_t mask)
352 {
353 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
354 uint32_t tempRegVal;
355 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
356 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal & (~mask));
357 #else
358 base->CTRL1 &= ~mask;
359 #endif
360 }
361