1 /* 2 * Copyright (c) 2020-2024, Texas Instruments Incorporated 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of Texas Instruments Incorporated nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /*!**************************************************************************** 33 * @file Temperature.h 34 * 35 * @brief Temperature driver 36 * 37 * @anchor ti_drivers_Temperature_Overview 38 * # Overview # 39 * The Temperature driver provides services related to measuring and reacting 40 * to the current temperature of the chip and changes to it. 41 * 42 * The two main services provided are: 43 * - Getting the current temperature 44 * - Providing notification callbacks when the temperature changes 45 * 46 * @anchor ti_drivers_Temperature_Usage 47 * # Usage # 48 * 49 * ## Initialisation # 50 * Unlike most drivers, there is only a single instance of the temperature 51 * driver that is always available once #Temperature_init() is called. 52 * #Temperature_init() should be called once before using other Temperature 53 * driver APIs. It is not called automatically via SysConfig generated code. 54 * Subsequent #Temperature_init() calls will have no effect. 55 * 56 * ## Getting the Current Temperature # 57 * The most basic function of the driver is to provide the current temperature 58 * and return it. It is encoded as a signed integer in degrees C. 59 * 60 * ## Notifications # 61 * The other major function of the Temperature driver is to notify the 62 * application when the temperature changes and crosses an application-defined 63 * threshold. 64 * 65 * There are three default usecases for this: 66 * - High threshold. 67 * The application will receive a notification callback when 68 * currentTemperature >= thresholdHigh. 69 * - Low threshold. 70 * The application will receive a notification callback when 71 * currentTemperature <= thresholdLow. 72 * - Range threshold. 73 * The application will receive a notification callback when 74 * currentTemperature >= thresholdHigh || currentTemperature <= 75 * thresholdLow. This setup addresses usecases 76 * where a notification is required when the temperature changes by a 77 * certain amount regardless of whether it is up or down. Adjusting 78 * clock offsets based on temperature is a good example of this. 79 * 80 * ### Registering Notifications 81 * There are three functions that register a notification for the application: 82 * - #Temperature_registerNotifyHigh() 83 * - #Temperature_registerNotifyLow() 84 * - #Temperature_registerNotifyRange() 85 * 86 * Multiple notifications may be registered. The different parts of the 87 * application and drivers that need to respond to a temperature change do not 88 * need to know of one another. 89 * Each notification must have its own #Temperature_NotifyObj and must be 90 * registered individually. 91 * 92 * ### Notification Callbacks 93 * Once the chip temperature crosses the smallest high threshold or largest 94 * low threshold amongst the registered notifications, the driver will 95 * iterate over the entire list of registered notification and check which 96 * ones have triggered. Notifications that have triggered are removed from 97 * the list of registered notifications and thus are no longer registered. 98 * Their callback function is then invoked. 99 * 100 * If an application wishes to re-register a notification that just triggered 101 * and was unregistered, it may register it again from within the notification 102 * callback or another context. 103 * 104 * It is possible to determine whether the high or low threshold triggered 105 * the notification callback as follows: 106 * - currentTemperature <= thresholdTemperature: Low threshold triggered 107 * - currentTemperature >= thresholdTemperature: High threshold triggered 108 * This information is only reasonably useful when registering a notification 109 * with both a high and low threshold using #Temperature_registerNotifyRange(). 110 * Even then, the expected basic usecase only cares about the current 111 * temperature and adding an offset to it when registering the notification 112 * again. 113 * 114 * ### Unregistering Notifications 115 * Registered notifications are unregistered in two ways: 116 * - Automatically when a notification triggers 117 * - By calling #Temperature_unregisterNotify() 118 * 119 * Unregistered notifications may be registered again at any time. 120 * 121 * # Measured vs True Temperature 122 * While the driver aims to supply and act on an accurate absolute temperature, 123 * there will be differences between the measured vs the true temperature due 124 * to inherent variances in the manufacturing process. The nature of these 125 * differences varies by device family. 126 * 127 * Examples of such differences: 128 * - A constant per-chip offset between the measured and the true 129 * temperature 130 * - An temperature dependent per-chip offset between the measured and the 131 * true temperature 132 * - A variance in the measured temperature when measuring multiple times 133 * at the same chip temperature 134 * 135 * It is strongly recommended to read the device-specific Temperature driver 136 * documentation for details of the temperature sensor characteristics and 137 * how they might affect choices of threshold values. 138 * 139 * @anchor ti_drivers_Temperature_Synopsis 140 * # Synopsis # 141 * @anchor ti_drivers_Temperature_Synopsis_Code 142 * @code 143 * #include <ti/drivers/Temperature.h> 144 * 145 * #define WINDOW_DELTA 10 146 * 147 * Temperature_init(); 148 * 149 * currentTemperature = Temperature_getTemperature(); 150 * 151 * result = Temperature_registerNotifyRange(¬ifyObject, 152 * currentTemperature + WINDOW_DELTA, 153 * currentTemperature - WINDOW_DELTA, 154 * myNotifyFxn, 155 * clientArg); 156 * @endcode 157 * 158 * @anchor ti_drivers_Temperature_Examples 159 * # Examples # 160 * 161 * ## Register a High Threshold Notification # 162 * 163 * @code 164 * 165 * // The notification will trigger when the temperature reaches 40 C 166 * #define THRESHOLD_CUTOFF 40 167 * 168 * #include <ti/drivers/Temperature.h> 169 * 170 * void thresholdNotifyFxn(int16_t currentTemperature, 171 * int16_t thresholdTemperature, 172 * uintptr_t clientArg, 173 * Temperature_NotifyObj *notifyObject) { 174 * // Post a semaphore, set a flag, or otherwise act upon the temperature 175 * // change. 176 * } 177 * 178 * ... 179 * 180 * // Initialize the Temperature driver and register a notification. 181 * 182 * Temperature_init(); 183 * 184 * int_fast16_t status = Temperature_registerNotifyHigh(notifyObject, 185 * THRESHOLD_CUTOFF, 186 * thresholdNotifyFxn, 187 * NULL); 188 * 189 * if (status != Temperature_STATUS_SUCCESS) { 190 * // Handle error 191 * } 192 * 193 * @endcode 194 * 195 * ## Register a Range Threshold Notification and Re-register in Callback # 196 * 197 * @code 198 * 199 * #define THRESHOLD_DELTA 5 200 * 201 * #include <ti/drivers/Temperature.h> 202 * 203 * 204 * void deltaNotificationFxn(int16_t currentTemperature, 205 * int16_t thresholdTemperature, 206 * uintptr_t clientArg, 207 * Temperature_NotifyObj *notifyObject) { 208 * int_fast16_t status; 209 * 210 * status = Temperature_registerNotifyRange(notifyObject, 211 * currentTemperature + THRESHOLD_DELTA, 212 * currentTemperature - THRESHOLD_DELTA, 213 * deltaNotificationFxn, 214 * NULL); 215 * 216 * if (status != Temperature_STATUS_SUCCESS) { 217 * while(1); 218 * } 219 * } 220 * 221 * ... 222 * 223 * // Initialize the Temperature driver and register a notification. 224 * 225 * Temperature_init(); 226 * 227 * int16_t currentTemperature = Temperature_getTemperature(); 228 * 229 * int_fast16_t status = Temperature_registerNotifyRange(notifyObject, 230 * currentTemperature + THRESHOLD_DELTA, 231 * currentTemperature - THRESHOLD_DELTA, 232 * deltaNotificationFxn, 233 * NULL); 234 * @endcode 235 */ 236 237 #ifndef ti_drivers_Temperature__include 238 #define ti_drivers_Temperature__include 239 240 #include <stdbool.h> 241 #include <stddef.h> 242 #include <stdint.h> 243 244 #include <ti/drivers/utils/List.h> 245 246 #ifdef __cplusplus 247 extern "C" { 248 #endif 249 250 /*! 251 * Common Temperature status code reservation offset. 252 * Temperature driver implementations should offset status codes with 253 * Temperature_STATUS_RESERVED growing negatively. 254 * 255 * Example implementation specific status codes: 256 * @code 257 * #define TemperatureXYZ_STATUS_ERROR0 Temperature_STATUS_RESERVED - 0 258 * #define TemperatureXYZ_STATUS_ERROR1 Temperature_STATUS_RESERVED - 1 259 * #define TemperatureXYZ_STATUS_ERROR2 Temperature_STATUS_RESERVED - 2 260 * @endcode 261 */ 262 #define Temperature_STATUS_RESERVED (-32) 263 264 /*! 265 * @brief Successful status code. 266 * 267 * Functions return Temperature_STATUS_SUCCESS if the function was executed 268 * successfully. 269 */ 270 #define Temperature_STATUS_SUCCESS (0) 271 272 /*! 273 * @brief Generic error status code. 274 * 275 * Functions return Temperature_STATUS_ERROR if the function was not executed 276 * successfully. 277 */ 278 #define Temperature_STATUS_ERROR (-1) 279 280 /* @cond 281 * 282 * Type declaration for the notification object made separately from the 283 * struct definition because of the circular dependency between 284 * #Temperature_NotifyFxn() and #Temperature_NotifyObj. 285 */ 286 typedef struct Temperature_NotifyObj Temperature_NotifyObj; 287 /* @endcond */ 288 289 /*! 290 * @brief Function prototype for a notification callback. 291 * 292 * @param [in] currentTemperature Current chip temperature 293 * 294 * @param [in] thresholdTemperature Temperature threshold that caused 295 * this notification callback. 296 * 297 * @param [in] clientArg Argument provided by the application 298 * during registration. 299 * 300 * @param [in/out] notifyObject The notification object that was 301 * registered previously. This pointer 302 * may be used to register the 303 * notification again with updated 304 * inputs from within the notification 305 * callback. 306 */ 307 typedef void (*Temperature_NotifyFxn)(int16_t currentTemperature, 308 int16_t thresholdTemperature, 309 uintptr_t clientArg, 310 Temperature_NotifyObj *notifyObject); 311 312 /*! 313 * @brief Temperature notify object structure. 314 * 315 * This structure specification is for internal use. Notification clients must 316 * pre-allocate a notify object when registering for a notification; 317 * #Temperature_registerNotifyHigh(), #Temperature_registerNotifyLow(), 318 * or #Temperature_registerNotifyRange() will take care initializing the 319 * internal elements appropriately. 320 */ 321 struct Temperature_NotifyObj 322 { 323 List_Elem link; /*!< For placing on the notify list */ 324 Temperature_NotifyFxn notifyFxn; /*!< Application callback function */ 325 int16_t thresholdHigh; /*!< High threshold in degrees C */ 326 int16_t thresholdLow; /*!< Low threshold in degrees C */ 327 uintptr_t clientArg; /*!< Application provided arg */ 328 bool isRegistered; /*!< Is the notification active */ 329 }; 330 331 /*! 332 * @brief This function initializes the Temperature driver. 333 * 334 * This function initializes the internal state of the Temperature driver. 335 * It must be called before calling any other Temperature functions. Calling 336 * this function multiple times will only have an effect the first time. 337 * 338 * @note This function should be called manually before using the temperature API. 339 * It will not be called automatically via SysConfig generated code. 340 */ 341 void Temperature_init(void); 342 343 /*! 344 * @brief Gets the current temperature in degrees C. 345 * 346 * @return Current temperature in degrees C 347 */ 348 int16_t Temperature_getTemperature(void); 349 350 /*! 351 * @brief Registers a notification with a high threshold. 352 * 353 * This function registers a Temperature notification with a high threshold. 354 * Once the chip temperature rises above @c thresholdHigh, @c notifyFxn is 355 * called and the notification is automatically unregistered. 356 * 357 * @param notifyObject Structure to be initialized. After returning, 358 * it will contain the data necessary to issue a 359 * notification callback. The memory of the 360 * structure must persist while the notification 361 * is registered. 362 * 363 * @param [in] thresholdHigh Threshold temperature in degrees C 364 * 365 * @param [in] notifyFxn Callback function that is called once the 366 * chip temperature rises above 367 * @c thresholdHigh. 368 * 369 * @param [in] clientArg Application-specified argument 370 * 371 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 372 * registered. 373 * @retval #Temperature_STATUS_ERROR There was an error during registration. 374 * 375 * @pre Temperature_init() called 376 */ 377 int_fast16_t Temperature_registerNotifyHigh(Temperature_NotifyObj *notifyObject, 378 int16_t thresholdHigh, 379 Temperature_NotifyFxn notifyFxn, 380 uintptr_t clientArg); 381 382 /*! 383 * @brief Registers a notification with a low threshold. 384 * 385 * This function registers a Temperature notification with a low threshold. 386 * Once the chip temperature falls below @c thresholdLow, @c notifyFxn is 387 * called and the notification is automatically unregistered. 388 * 389 * @param notifyObject Structure to be initialized. After returning, 390 * it will contain the data necessary to issue a 391 * notification callback. The memory of the 392 * structure must persist while the notification 393 * is registered. 394 * 395 * @param [in] thresholdLow Threshold temperature in degrees C 396 * 397 * @param [in] notifyFxn Callback function that is called once the 398 * chip temperature falls below 399 * @c thresholdLow. 400 * 401 * @param [in] clientArg Application-specified argument 402 * 403 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 404 * registered. 405 * @retval #Temperature_STATUS_ERROR There was an error during registration. 406 * 407 * @pre Temperature_init() called 408 */ 409 int_fast16_t Temperature_registerNotifyLow(Temperature_NotifyObj *notifyObject, 410 int16_t thresholdLow, 411 Temperature_NotifyFxn notifyFxn, 412 uintptr_t clientArg); 413 414 /*! 415 * @brief Registers a notification with both a high and low threshold. 416 * 417 * This function registers a Temperature notification with a high and low 418 * threshold. Once the chip temperature rises above @c thresholdHigh or 419 * falls below @c thresholdLow, @c notifyFxn is called and the notification is 420 * automatically unregistered. 421 * 422 * @param notifyObject Structure to be initialized. After returning, 423 * it will contain the data necessary to issue a 424 * notification callback. The memory of the 425 * structure must persist while the notification 426 * is registered. 427 * 428 * @param [in] thresholdHigh High threshold temperature in degrees C 429 * 430 * @param [in] thresholdLow Low threshold temperature in degrees C 431 * 432 * @param [in] notifyFxn Callback function that is called once the 433 * chip temperature falls below 434 * @c thresholdLow, or rises above 435 * @c thresholdHigh. 436 * 437 * @param [in] clientArg Application-specified argument 438 * 439 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 440 * registered 441 * @retval #Temperature_STATUS_ERROR There was an error during registration 442 * 443 * @pre Temperature_init() called 444 */ 445 int_fast16_t Temperature_registerNotifyRange(Temperature_NotifyObj *notifyObject, 446 int16_t thresholdHigh, 447 int16_t thresholdLow, 448 Temperature_NotifyFxn notifyFxn, 449 uintptr_t clientArg); 450 451 /*! 452 * @brief Unregisters a currently registered notification. 453 * 454 * This function unregisters a currently registered notification. It should not 455 * be called on a @c notifyObject that is not currently registered. 456 * 457 * @param notifyObject Notification to unregister. 458 * 459 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 460 * unregistered. 461 * @retval #Temperature_STATUS_ERROR There was an error during 462 * unregistration. 463 * 464 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 465 * #Temperature_registerNotifyLow(), or #Temperature_registerNotifyRange() 466 */ 467 int_fast16_t Temperature_unregisterNotify(Temperature_NotifyObj *notifyObject); 468 469 /*! 470 * @brief Get the high threshold of a notification. 471 * 472 * This function should not be called on a @c notifyObject registered with 473 * #Temperature_registerNotifyLow(). The high threshold value returned in 474 * that case will be a device-specific invalid temperature. 475 * 476 * @param notifyObject Notification to get the high threshold of. 477 * 478 * @return High threshold in degrees C. 479 * 480 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 481 * or #Temperature_registerNotifyRange() 482 */ 483 int16_t Temperature_getThresholdHigh(Temperature_NotifyObj *notifyObject); 484 485 /*! 486 * @brief Get the low threshold of a notification. 487 * 488 * This function should not be called on a @c notifyObject registered with 489 * #Temperature_registerNotifyHigh(). The low threshold value returned in 490 * that case will be a device-specific invalid temperature. 491 * 492 * @param notifyObject Notification to get the low threshold of. 493 * 494 * @return Low threshold in degrees C. 495 * 496 * @pre Register @c notifyObject with #Temperature_registerNotifyLow(), 497 * or #Temperature_registerNotifyRange() 498 */ 499 int16_t Temperature_getThresholdLow(Temperature_NotifyObj *notifyObject); 500 501 /*! 502 * @brief Get the high and low threshold of a notification. 503 * 504 * This function should not be called on a @c notifyObject registered with 505 * #Temperature_registerNotifyLow() or #Temperature_registerNotifyHigh(). 506 * The unconfigured threshold value returned in that case will be a 507 * device-specific invalid temperature. 508 * 509 * @param notifyObject Notification to get the high and low threshold of. 510 * 511 * @param [out] thresholdHigh High threshold value in degrees C written back 512 * by this function. 513 * 514 * @param [out] thresholdLow Low threshold value in degrees C written back 515 * by this function. 516 * 517 * @pre Register @c notifyObject with #Temperature_registerNotifyRange() 518 */ 519 void Temperature_getThresholdRange(Temperature_NotifyObj *notifyObject, int16_t *thresholdHigh, int16_t *thresholdLow); 520 521 /*! 522 * @brief Get the application-provided clientArg of a notification. 523 * 524 * @param notifyObject Notification to get the clientArg of. 525 * 526 * @return The clientArg provided during registration. 527 * 528 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 529 * #Temperature_registerNotifyLow(), or #Temperature_registerNotifyRange() 530 */ 531 uintptr_t Temperature_getClientArg(Temperature_NotifyObj *notifyObject); 532 533 /*! 534 * @brief Get the notifyFxn provided during registration. 535 * 536 * @param notifyObject Notification to get the notifyFxn of. 537 * 538 * @return The notifyFxn provided during registration 539 * 540 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 541 * #Temperature_registerNotifyLow(), or #Temperature_registerNotifyRange() 542 */ 543 Temperature_NotifyFxn Temperature_getNotifyFxn(Temperature_NotifyObj *notifyObject); 544 545 #ifdef __cplusplus 546 } 547 #endif 548 549 #endif /* ti_drivers_Temperature__include */ 550