1 /*
2 * Copyright 2020-2023 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 */
TMPSNS_Init(TMPSNS_Type * base,const tmpsns_config_t * config)47 void TMPSNS_Init(TMPSNS_Type *base, const tmpsns_config_t *config)
48 {
49 assert(NULL != config);
50
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 /* Reset Tempsensor first. */
60 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
61 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
62 #else
63 controlVal = base->CTRL1;
64 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
65
66 controlVal |= (TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK);
67 controlVal &= (~(TMPSNS_CTRL1_START_MASK | TMPSNS_CTRL1_FINISH_IE_MASK | TMPSNS_CTRL1_LOW_TEMP_IE_MASK |
68 TMPSNS_CTRL1_HIGH_TEMP_IE_MASK | TMPSNS_CTRL1_PANIC_TEMP_IE_MASK | TMPSNS_CTRL1_FREQ_MASK));
69
70 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
71 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
72 #else
73 base->CTRL1 = controlVal;
74 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
75
76 /* Set alarm temperature */
77 TMPSNS_SetTempAlarm(base, config->highAlarmTemp, kTEMPMON_HighAlarmMode);
78 TMPSNS_SetTempAlarm(base, config->panicAlarmTemp, kTEMPMON_PanicAlarmMode);
79 TMPSNS_SetTempAlarm(base, config->lowAlarmTemp, kTEMPMON_LowAlarmMode);
80
81 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
82 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
83 #else
84 controlVal = base->CTRL1;
85 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
86
87 /* Enable finish interrupt status */
88 controlVal |= TMPSNS_CTRL1_FINISH_IE_MASK;
89
90 if (config->measureMode == kTEMPSENSOR_SingleMode)
91 {
92 controlVal |= TMPSNS_CTRL1_FREQ(0x00U);
93 }
94 else if (config->measureMode == kTEMPSENSOR_ContinuousMode)
95 {
96 controlVal |= TMPSNS_CTRL1_FREQ(config->frequency);
97 }
98 else
99 {
100 ; /* Intentional empty for MISRA C-2012 rule 15.7*/
101 }
102
103 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
104 uint32_t statusVal;
105
106 /* Power up the temperature sensor */
107 controlVal &= (~(TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK));
108
109 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
110
111 /* Read STATUS0 value */
112 statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
113
114 /* Clear interrupt status flags. */
115 TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0),
116 (statusVal | TMPSNS_STATUS0_HIGH_TEMP_MASK | TMPSNS_STATUS0_LOW_TEMP_MASK |
117 TMPSNS_STATUS0_PANIC_TEMP_MASK | TMPSNS_STATUS0_FINISH_MASK));
118 #else
119 base->CTRL1 = controlVal;
120
121 /* Power up the temperature sensor */
122 base->CTRL1 &= (~(TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK));
123
124 /* Clear interrupt status flags. */
125 base->STATUS0 = (TMPSNS_STATUS0_HIGH_TEMP_MASK | TMPSNS_STATUS0_LOW_TEMP_MASK | TMPSNS_STATUS0_PANIC_TEMP_MASK |
126 TMPSNS_STATUS0_FINISH_MASK);
127 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
128 }
129
130 /*!
131 * brief Deinitializes the TMPSNS module.
132 *
133 * param base TMPSNS base pointer
134 */
TMPSNS_Deinit(TMPSNS_Type * base)135 void TMPSNS_Deinit(TMPSNS_Type *base)
136 {
137 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
138 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), TMPSNS_CTRL1_PWD_MASK);
139 #else
140 base->CTRL1 |= TMPSNS_CTRL1_PWD_MASK;
141 #endif
142 }
143
144 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
145 /*!
146 * brief AI interface write access.
147 *
148 * param base TMPSNS base pointer
149 */
TMPSNS_AIWriteAccess(uint32_t address,uint32_t data)150 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data)
151 {
152 /* AI bridge setting: AIRWB and ADDR
153 Write: 0x00
154 Address: offset from base address
155 */
156 ANADIG_MISC->VDDLPSR_AI_CTRL = (0x00UL << 16) | (address & 0xFFFFU);
157 /* Write data into related register through AI bridge */
158 ANADIG_MISC->VDDLPSR_AI_WDATA = data;
159 /* AI toggle */
160 ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
161 }
162
163 /*!
164 * brief AI interface read access.
165 *
166 * param base TMPSNS base pointer
167 */
TMPSNS_AIReadAccess(uint32_t address)168 static uint32_t TMPSNS_AIReadAccess(uint32_t address)
169 {
170 uint32_t ret;
171
172 /* AI bridge setting: AIRWB and ADDR
173 Read: 0x01
174 Address: offset from base address
175 */
176 ANADIG_MISC->VDDLPSR_AI_CTRL = (0x01UL << 16) | (address & 0xFFFFU);
177 /* AI toggle */
178 ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
179 /* Read data from related register through AI bridge */
180 ret = ANADIG_MISC->VDDLPSR_AI_RDATA_TMPSNS;
181
182 return ret;
183 }
184 #endif /* FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
185
186 /*!
187 * brief Gets the default configuration structure.
188 *
189 * This function initializes the TMPSNS configuration structure to a default value. The default
190 * values are:
191 * tempmonConfig->frequency = 0x00U;
192 * tempmonConfig->highAlarmTemp = 25U;
193 * tempmonConfig->panicAlarmTemp = 80U;
194 * tempmonConfig->lowAlarmTemp = 20U;
195 *
196 * param config Pointer to a configuration structure.
197 */
TMPSNS_GetDefaultConfig(tmpsns_config_t * config)198 void TMPSNS_GetDefaultConfig(tmpsns_config_t *config)
199 {
200 assert(config);
201
202 /* Initializes the configure structure to zero. */
203 (void)memset(config, 0, sizeof(*config));
204
205 /* Default measurement mode */
206 config->measureMode = kTEMPSENSOR_SingleMode;
207 /* Default measure frequency */
208 config->frequency = 0x00U;
209 /* Default high alarm temperature */
210 config->highAlarmTemp = 25;
211 /* Default panic alarm temperature */
212 config->panicAlarmTemp = 80;
213 /* Default low alarm temperature */
214 config->lowAlarmTemp = 5;
215 }
216
217 /*!
218 * @brief start the temperature measurement process.
219 *
220 * @param base TMPSNS base pointer.
221 */
TMPSNS_StartMeasure(TMPSNS_Type * base)222 void TMPSNS_StartMeasure(TMPSNS_Type *base)
223 {
224 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
225 uint32_t controlVal;
226 /* Read CTRL1 value*/
227 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
228 /* Start measurement */
229 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal | TMPSNS_CTRL1_SET_START_MASK);
230 #else
231 base->CTRL1 |= TMPSNS_CTRL1_SET_START_MASK;
232 #endif
233 }
234
235 /*!
236 * @brief stop the measurement process.
237 *
238 * @param base TMPSNS base pointer
239 */
TMPSNS_StopMeasure(TMPSNS_Type * base)240 void TMPSNS_StopMeasure(TMPSNS_Type *base)
241 {
242 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
243 uint32_t controlVal;
244 /* Read CTRL1 value*/
245 controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
246 /* Start measurement */
247 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal & (~TMPSNS_CTRL1_SET_START_MASK));
248 #else
249 base->CTRL1 &= ~TMPSNS_CTRL1_SET_START_MASK;
250 #endif
251 }
252
253 /*!
254 * brief Get current temperature with the fused temperature calibration data.
255 *
256 * param base TMPSNS base pointer
257 * return current temperature with degrees Celsius.
258 */
TMPSNS_GetCurrentTemperature(TMPSNS_Type * base)259 float TMPSNS_GetCurrentTemperature(TMPSNS_Type *base)
260 {
261 uint32_t measureTempVal;
262 float actualTempVal;
263
264 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
265 /* Waiting for measurement finished */
266 while (0U == (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_FINISH_MASK))
267 {
268 }
269 /* Ready to read measured temperature value */
270 measureTempVal = (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_TEMP_VAL_MASK) >>
271 TMPSNS_STATUS0_TEMP_VAL_SHIFT;
272 #else
273 /* Waiting for measurement finished */
274 while (0U == (base->STATUS0 & TMPSNS_STATUS0_FINISH_MASK))
275 {
276 }
277 /* Ready to read measured temperature value */
278 measureTempVal = (base->STATUS0 & TMPSNS_STATUS0_TEMP_VAL_MASK) >> TMPSNS_STATUS0_TEMP_VAL_SHIFT;
279 #endif
280
281 /* Calculate actual temperature */
282 actualTempVal =
283 (-s_Ts21 - sqrtf(s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c - (float)measureTempVal))) / (2.0f * s_Ts22);
284
285 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
286 uint32_t statusVal;
287 /* Read STATUS0 value */
288 statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
289 /* Clear the FINISH flag */
290 TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0), statusVal | TMPSNS_STATUS0_FINISH_MASK);
291 #else
292 /* Clear the FINISH flag */
293 base->STATUS0 |= TMPSNS_STATUS0_FINISH_MASK;
294 #endif
295
296 return actualTempVal;
297 }
298
299 /*!
300 * brief Set the temperature count (raw sensor output) that will generate an alarm interrupt.
301 *
302 * param base TMPSNS base pointer
303 * param tempVal The alarm temperature with degrees Celsius
304 * param alarmMode The alarm mode.
305 */
TMPSNS_SetTempAlarm(TMPSNS_Type * base,int32_t tempVal,tmpsns_alarm_mode_t alarmMode)306 void TMPSNS_SetTempAlarm(TMPSNS_Type *base, int32_t tempVal, tmpsns_alarm_mode_t alarmMode)
307 {
308 float temp;
309 int32_t tempCodeVal;
310 uint32_t tempRegVal;
311
312 /* Calculate alarm temperature code value */;
313 temp = (-2.0f * s_Ts22 * (float)tempVal - s_Ts21) * (-2.0f * s_Ts22 * (float)tempVal - s_Ts21);
314 temp = (temp - (s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c))) / (4.0f * s_Ts22);
315 tempCodeVal = (int32_t)temp;
316
317 switch (alarmMode)
318 {
319 case kTEMPMON_HighAlarmMode:
320 /* Clear alarm value and set a new high alarm temperature code value */
321 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
322 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
323 tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
324 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0), tempRegVal);
325 #else
326 tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
327 base->RANGE0 = tempRegVal;
328 #endif
329 /* Enable high temperature interrupt */
330 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_HighTempInterruptStatusEnable);
331 break;
332
333 case kTEMPMON_PanicAlarmMode:
334 /* Clear panic alarm value and set a new panic alarm temperature code value */
335 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
336 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE1));
337 tempRegVal = (tempRegVal & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
338 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE1), tempRegVal);
339 #else
340 tempRegVal =
341 (base->RANGE1 & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
342 base->RANGE1 = tempRegVal;
343 #endif
344 /* Enable panic temperature interrupt */
345 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_PanicTempInterruptStatusEnable);
346 break;
347
348 case kTEMPMON_LowAlarmMode:
349 /* Clear low alarm value and set a new low alarm temperature code value */
350 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
351 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
352 tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
353 TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0_SET), tempRegVal);
354 #else
355 tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
356 base->RANGE0 = tempRegVal;
357 #endif
358 /* Enable low temperature interrupt */
359 TMPSNS_EnableInterrupt(base, kTEMPSENSOR_LowTempInterruptStatusEnable);
360 break;
361
362 default:
363 assert(false);
364 break;
365 }
366 }
367
368 /*!
369 * brief Enable interrupt status.
370 *
371 * param base TMPSNS base pointer
372 * param mask The interrupts to enable from tmpsns_interrupt_status_enable_t.
373 */
TMPSNS_EnableInterrupt(TMPSNS_Type * base,uint32_t mask)374 void TMPSNS_EnableInterrupt(TMPSNS_Type *base, uint32_t mask)
375 {
376 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
377 uint32_t tempRegVal;
378 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
379 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal | mask);
380 #else
381 base->CTRL1 |= mask;
382 #endif
383 }
384
385 /*!
386 * brief Disable interrupt status.
387 *
388 * param base TMPSNS base pointer
389 * param mask The interrupts to disable from tmpsns_interrupt_status_enable_t.
390 */
TMPSNS_DisableInterrupt(TMPSNS_Type * base,uint32_t mask)391 void TMPSNS_DisableInterrupt(TMPSNS_Type *base, uint32_t mask)
392 {
393 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
394 uint32_t tempRegVal;
395 tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
396 TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal & (~mask));
397 #else
398 base->CTRL1 &= ~mask;
399 #endif
400 }
401