1 /* 2 * Copyright (c) 2020, 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. Subsequent #Temperature_init() calls will have no effect. 54 * 55 * ## Getting the Current Temperature # 56 * The most basic function of the driver is to provide the current temperature 57 * and return it. It is encoded as a signed integer in degrees C. 58 * 59 * ## Notifications # 60 * The other major function of the Temperature driver is to notify the 61 * application when the temperature changes and crosses an application-defined 62 * threshold. 63 * 64 * There are three default usecases for this: 65 * - High threshold. 66 * The application will receive a notification callback when 67 * currentTemperature >= thresholdHigh. 68 * - Low threshold. 69 * The application will receive a notification callback when 70 * currentTemperature <= thresholdLow. 71 * - Range threshold. 72 * The application will receive a notification callback when 73 * currentTemperature >= thresholdHigh || currentTemperature <= 74 * thresholdLow. This setup addresses usecases 75 * where a notification is required when the temperature changes by a 76 * certain amount regardless of whether it is up or down. Adjusting 77 * clock offsets based on temperature is a good example of this. 78 * 79 * ### Registering Notifications 80 * There are three functions that register a notification for the application: 81 * - #Temperature_registerNotifyHigh() 82 * - #Temperature_registerNotifyLow() 83 * - #Temperature_registerNotifyRange() 84 * 85 * Multiple notifications may be registered. The different parts of the 86 * application and drivers that need to respond to a temperature change do not 87 * need to know of one another. 88 * Each notification must have its own #Temperature_NotifyObj and must be 89 * registered individually. 90 * 91 * ### Notification Callbacks 92 * Once the chip temperature crosses the smallest high threshold or largest 93 * low threshold amongst the registered notifications, the driver will 94 * iterate over the entire list of registered notification and check which 95 * ones have triggered. Notifications that have triggered are removed from 96 * the list of registered notifications and thus are no longer registered. 97 * Their callback function is then invoked. 98 * 99 * If an application wishes to reregister a notification that just triggered 100 * and was unregistered, it may register it again from within the notification 101 * callback or another context. 102 * 103 * It is possible to determine whether the high or low threshold triggered 104 * the notification callback as follows: 105 * - currentTemperature <= thresholdTemperature: Low threshold triggered 106 * - currentTemperature >= thresholdTemperature: High threshold triggered 107 * This information is only reasonably useful when registering a notification 108 * with both a high and low threshold using #Temperature_registerNotifyRange(). 109 * Even then, the expected basic usecase only cares about the current 110 * temperature and adding an offset to it when registering the notification 111 * again. 112 * 113 * ### Unregistering Notifications 114 * Registered notifications are unregistered in two ways: 115 * - Automatically when a notification triggers 116 * - By calling #Temperature_unregisterNotify() 117 * 118 * Unregistered notifications may be registered again at any time. 119 * 120 * # Measured vs True Temperature 121 * While the driver aims to supply and act on an accurate absolute temperature, 122 * there will be differences between the measured vs the true temperature due 123 * to inherent variances in the manufacturing process. The nature of these 124 * differences varies by device family. 125 * 126 * Examples of such differences: 127 * - A constant per-chip offset between the measured and the true 128 * temperature 129 * - An temperature dependent per-chip offset between the measured and the 130 * true temperature 131 * - A variance in the measured temperature when measuring multiple times 132 * at the same chip temperature 133 * 134 * It is strongly recommended to read the device-specific Temperature driver 135 * documentation for details of the temperature sensor characteristics and 136 * how they might affect choices of threshold values. 137 * 138 * @anchor ti_drivers_Temperature_Synopsis 139 * # Synopsis # 140 * @anchor ti_drivers_Temperature_Synopsis_Code 141 * @code 142 * #include <ti/drivers/Temperature.h> 143 * 144 * #define WINDOW_DELTA 10 145 * 146 * Temperature_init(); 147 * 148 * currentTemperature = Temperature_getTemperature(); 149 * 150 * result = Temperature_registerNotifyRange(¬ifyObject, 151 * currentTemperature + WINDOW_DELTA, 152 * currentTemperature - WINDOW_DELTA, 153 * myNotifyFxn, 154 * clientArg); 155 * @endcode 156 * 157 * @anchor ti_drivers_Temperature_Examples 158 * # Examples # 159 * 160 * ## Register a High Threshold Notification # 161 * 162 * @code 163 * 164 * // The notification will trigger when the temperature reaches 40 C 165 * #define THRESHOLD_CUTOFF 40 166 * 167 * #include <ti/drivers/Temperature.h> 168 * 169 * void thresholdNotifyFxn(int16_t currentTemperature, 170 * int16_t thresholdTemperature, 171 * uintptr_t clientArg, 172 * Temperature_NotifyObj *notifyObject) { 173 * // Post a semaphore, set a flag, or otherwise act upon the temperature 174 * // change. 175 * } 176 * 177 * ... 178 * 179 * // Initialize the Temperature driver and register a notification. 180 * 181 * Temperature_init(); 182 * 183 * int_fast16_t status = Temperature_registerNotifyHigh(notifyObject, 184 * THRESHOLD_CUTOFF, 185 * thresholdNotifyFxn, 186 * NULL); 187 * 188 * if (status != Temperature_STATUS_SUCCESS) { 189 * // Handle error 190 * } 191 * 192 * @endcode 193 * 194 * ## Register a Range Threshold Notification and Reregister in Callback # 195 * 196 * @code 197 * 198 * #define THRESHOLD_DELTA 5 199 * 200 * #include <ti/drivers/Temperature.h> 201 * 202 * 203 * void deltaNotificationFxn(int16_t currentTemperature, 204 * int16_t thresholdTemperature, 205 * uintptr_t clientArg, 206 * Temperature_NotifyObj *notifyObject) { 207 * int_fast16_t status; 208 * 209 * status = Temperature_registerNotifyRange(notifyObject, 210 * currentTemperature + THRESHOLD_DELTA, 211 * currentTemperature - THRESHOLD_DELTA, 212 * deltaNotificationFxn, 213 * NULL); 214 * 215 * if (status != Temperature_STATUS_SUCCESS) { 216 * while(1); 217 * } 218 * } 219 * 220 * ... 221 * 222 * // Initialize the Temperature driver and register a notification. 223 * 224 * Temperature_init(); 225 * 226 * int16_t currentTemperature = Temperature_getTemperature(); 227 * 228 * int_fast16_t status = Temperature_registerNotifyRange(notifyObject, 229 * currentTemperature + THRESHOLD_DELTA, 230 * currentTemperature - THRESHOLD_DELTA, 231 * deltaNotificationFxn, 232 * NULL); 233 * @endcode 234 */ 235 236 #ifndef ti_drivers_Temperature__include 237 #define ti_drivers_Temperature__include 238 239 #include <stdbool.h> 240 #include <stddef.h> 241 #include <stdint.h> 242 243 #include <ti/drivers/utils/List.h> 244 245 #ifdef __cplusplus 246 extern "C" { 247 #endif 248 249 /*! 250 * Common Temperature status code reservation offset. 251 * Temperature driver implementations should offset status codes with 252 * Temperature_STATUS_RESERVED growing negatively. 253 * 254 * Example implementation specific status codes: 255 * @code 256 * #define TemperatureXYZ_STATUS_ERROR0 Temperature_STATUS_RESERVED - 0 257 * #define TemperatureXYZ_STATUS_ERROR1 Temperature_STATUS_RESERVED - 1 258 * #define TemperatureXYZ_STATUS_ERROR2 Temperature_STATUS_RESERVED - 2 259 * @endcode 260 */ 261 #define Temperature_STATUS_RESERVED (-32) 262 263 /*! 264 * @brief Successful status code. 265 * 266 * Functions return Temperature_STATUS_SUCCESS if the function was executed 267 * successfully. 268 */ 269 #define Temperature_STATUS_SUCCESS (0) 270 271 /*! 272 * @brief Generic error status code. 273 * 274 * Functions return Temperature_STATUS_ERROR if the function was not executed 275 * successfully. 276 */ 277 #define Temperature_STATUS_ERROR (-1) 278 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 List_Elem link; /*!< For placing on the notify list */ 323 Temperature_NotifyFxn notifyFxn; /*!< Application callback function */ 324 int16_t thresholdHigh; /*!< High threshold in degrees C */ 325 int16_t thresholdLow; /*!< Low threshold in degrees C */ 326 uintptr_t clientArg; /*!< Application provided arg */ 327 bool isRegistered; /*!< Is the notification active */ 328 }; 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 void Temperature_init(); 339 340 /*! 341 * @brief Gets the current temperature in degrees C. 342 * 343 * @return Current temperature in degrees C 344 */ 345 int16_t Temperature_getTemperature(void); 346 347 /*! 348 * @brief Registers a notification with a high threshold. 349 * 350 * This function registers a Temperature notification with a high threshold. 351 * Once the chip temperature rises above @c thresholdHigh, @c notifyFxn is 352 * called and the notification is automatically unregistered. 353 * 354 * @param notifyObject Structure to be initialized. After returning, 355 * it will contain the data necessary to issue a 356 * notification callback. The memory of the 357 * structure must persist while the notification 358 * is registered. 359 * 360 * @param [in] thresholdHigh Threshold temperature in degrees C 361 * 362 * @param [in] notifyFxn Callback function that is called once the 363 * chip temperature rises above 364 * @c thresholdHigh. 365 * 366 * @param [in] clientArg Application-specified argument 367 * 368 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 369 * registered. 370 * @retval #Temperature_STATUS_ERROR There was an error during registration. 371 * 372 * @pre Temperature_init() called 373 */ 374 int_fast16_t Temperature_registerNotifyHigh(Temperature_NotifyObj *notifyObject, 375 int16_t thresholdHigh, 376 Temperature_NotifyFxn notifyFxn, 377 uintptr_t clientArg); 378 379 /*! 380 * @brief Registers a notification with a low threshold. 381 * 382 * This function registers a Temperature notification with a low threshold. 383 * Once the chip temperature falls below @c thresholdLow, @c notifyFxn is 384 * called and the notification is automatically unregistered. 385 * 386 * @param notifyObject Structure to be initialized. After returning, 387 * it will contain the data necessary to issue a 388 * notification callback. The memory of the 389 * structure must persist while the notification 390 * is registered. 391 * 392 * @param [in] thresholdLow Threshold temperature in degrees C 393 * 394 * @param [in] notifyFxn Callback function that is called once the 395 * chip temperature falls below 396 * @c thresholdLow. 397 * 398 * @param [in] clientArg Application-specified argument 399 * 400 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 401 * registered. 402 * @retval #Temperature_STATUS_ERROR There was an error during registration. 403 * 404 * @pre Temperature_init() called 405 */ 406 int_fast16_t Temperature_registerNotifyLow(Temperature_NotifyObj *notifyObject, 407 int16_t thresholdLow, 408 Temperature_NotifyFxn notifyFxn, 409 uintptr_t clientArg); 410 411 /*! 412 * @brief Registers a notification with both a high and low threshold. 413 * 414 * This function registers a Temperature notification with a high and low 415 * threshold. Once the chip temperature rises above @c thresholdHigh or 416 * falls below @c thresholdLow, @c notifyFxn is called and the notification is 417 * automatically unregistered. 418 * 419 * @param notifyObject Structure to be initialized. After returning, 420 * it will contain the data necessary to issue a 421 * notification callback. The memory of the 422 * structure must persist while the notification 423 * is registered. 424 * 425 * @param [in] thresholdHigh High threshold temperature in degrees C 426 * 427 * @param [in] thresholdLow Low threshold temperature in degrees C 428 * 429 * @param [in] notifyFxn Callback function that is called once the 430 * chip temperature falls below 431 * @c thresholdLow, or rises above 432 * @c thresholdHigh. 433 * 434 * @param [in] clientArg Application-specified argument 435 * 436 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 437 * registered 438 * @retval #Temperature_STATUS_ERROR There was an error during registration 439 * 440 * @pre Temperature_init() called 441 */ 442 int_fast16_t Temperature_registerNotifyRange(Temperature_NotifyObj *notifyObject, 443 int16_t thresholdHigh, 444 int16_t thresholdLow, 445 Temperature_NotifyFxn notifyFxn, 446 uintptr_t clientArg); 447 448 449 /*! 450 * @brief Unregisters a currently registered notification. 451 * 452 * This function unregisters a currently registered notification. It should not 453 * be called on a @c notifyObject that is not currently registered. 454 * 455 * @param notifyObject Notification to unregister. 456 * 457 * @retval #Temperature_STATUS_SUCCESS The notification was successfully 458 * unregistered. 459 * @retval #Temperature_STATUS_ERROR There was an error during 460 * unregistration. 461 * 462 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 463 * #Temperature_registerNotifyLow(), or #Temperature_registerNotifyRange() 464 */ 465 int_fast16_t Temperature_unregisterNotify(Temperature_NotifyObj *notifyObject); 466 467 /*! 468 * @brief Get the high threshold of a notification. 469 * 470 * This function should not be called on a @c notifyObject registered with 471 * #Temperature_registerNotifyLow(). The high threshold value returned in 472 * that case will be a device-specific invalid temperature. 473 * 474 * @param notifyObject Notification to get the high threshold of. 475 * 476 * @return High threshold in degrees C. 477 * 478 * @pre Register @c notifyObject with #Temperature_registerNotifyHigh(), 479 * or #Temperature_registerNotifyRange() 480 */ 481 int16_t Temperature_getThresholdHigh(Temperature_NotifyObj *notifyObject); 482 483 /*! 484 * @brief Get the low threshold of a notification. 485 * 486 * This function should not be called on a @c notifyObject registered with 487 * #Temperature_registerNotifyHigh(). The low threshold value returned in 488 * that case will be a device-specific invalid temperature. 489 * 490 * @param notifyObject Notification to get the low threshold of. 491 * 492 * @return Low threshold in degrees C. 493 * 494 * @pre Register @c notifyObject with #Temperature_registerNotifyLow(), 495 * or #Temperature_registerNotifyRange() 496 */ 497 int16_t Temperature_getThresholdLow(Temperature_NotifyObj *notifyObject); 498 499 /*! 500 * @brief Get the high and low threshold of a notification. 501 * 502 * This function should not be called on a @c notifyObject registered with 503 * #Temperature_registerNotifyLow() or #Temperature_registerNotifyHigh(). 504 * The unconfigured threshold value returned in that case will be a 505 * device-specific invalid temperature. 506 * 507 * @param notifyObject Notification to get the high and low threshold of. 508 * 509 * @param [out] thresholdHigh High threshold value in degrees C written back 510 * by this function. 511 * 512 * @param [out] thresholdLow Low threshold value in degrees C written back 513 * by this function. 514 * 515 * @pre Register @c notifyObject with #Temperature_registerNotifyRange() 516 */ 517 void Temperature_getThresholdRange(Temperature_NotifyObj *notifyObject, 518 int16_t *thresholdHigh, 519 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 546 #ifdef __cplusplus 547 } 548 #endif 549 550 #endif /* ti_drivers_Temperature__include */ 551