From 4beed975130f93d23980cc42e0c06373f003a2b7 Mon Sep 17 00:00:00 2001 From: Josiitaa RL Date: Wed, 27 Mar 2024 17:21:25 +0530 Subject: [PATCH 1/3] VTM Integration with PDK BootApp --- packages/ti/boot/sbl/build/boot_app.mk | 11 +- .../boot/sbl/example/boot_app/boot_app_main.c | 70 ++- .../ti/boot/sbl/example/boot_app/vtm/vtm.c | 442 ++++++++++++++++++ .../ti/boot/sbl/example/boot_app/vtm/vtm.h | 66 +++ .../sbl/example/boot_app/vtm/vtm_example.c | 438 +++++++++++++++++ 5 files changed, 1024 insertions(+), 3 deletions(-) create mode 100644 packages/ti/boot/sbl/example/boot_app/vtm/vtm.c create mode 100644 packages/ti/boot/sbl/example/boot_app/vtm/vtm.h create mode 100644 packages/ti/boot/sbl/example/boot_app/vtm/vtm_example.c diff --git a/packages/ti/boot/sbl/build/boot_app.mk b/packages/ti/boot/sbl/build/boot_app.mk index c2606d46..ba30b945 100644 --- a/packages/ti/boot/sbl/build/boot_app.mk +++ b/packages/ti/boot/sbl/build/boot_app.mk @@ -51,21 +51,26 @@ ifeq ($(BOOTMODE), mmcsd) CFLAGS_LOCAL_COMMON += -DBOOT_MMCSD ifeq ($(BOARD),$(filter $(BOARD), j784s4_evm)) CFLAGS_LOCAL_COMMON += -DBIST_TASK_ENABLED + CFLAGS_LOCAL_COMMON += -DVTM_TASK_ENABLED #CFLAGS_LOCAL_COMMON += INCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/bist INCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/bist/soc/$(SOC) + + INCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/vtm # SDL Include Files SDL_INSTALL_PATH=$(PDK_INSTALL_PATH)/../../sdl INCDIR += $(SDL_INSTALL_PATH)/ INCDIR += $(SDL_INSTALL_PATH)/src/sdl + INCDIR += $(SDL_INSTALL_PATH)/src/ip INCDIR += $(SDL_INSTALL_PATH)/include INCDIR += $(SDL_INSTALL_PATH)/include/soc/$(SOC) - + # SDL Source File Paths SRCDIR += $(SDL_INSTALL_PATH)/test/osal/src SRCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/bist SRCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/bist/soc/$(SOC) - + + SRCDIR += $(PDK_SBL_COMP_PATH)/example/boot_app/vtm # SDL Integration EXT_LIB_LIST_COMMON += $(SDL_INSTALL_PATH)/binary/osal/lib/$(SOC)/r5f/$(BUILD_PROFILE)/sdl_osal.$(LIBEXT) EXT_LIB_LIST_COMMON += $(SDL_INSTALL_PATH)/binary/src/ip/lib/$(SOC)/r5f/$(BUILD_PROFILE)/sdl_ip.$(LIBEXT) @@ -77,6 +82,8 @@ ifeq ($(BOOTMODE), mmcsd) SRCS_COMMON += lbist_utils.c lbist_defs.c SRCS_COMMON += pbist_utils.c pbist_defs.c SRCS_COMMON += power_seq.c armv8_power_utils.c + + SRCS_COMMON += vtm.c vtm_example.c endif endif ifeq ($(BOOTMODE), ospi) diff --git a/packages/ti/boot/sbl/example/boot_app/boot_app_main.c b/packages/ti/boot/sbl/example/boot_app/boot_app_main.c index 73231700..1f654ad8 100644 --- a/packages/ti/boot/sbl/example/boot_app/boot_app_main.c +++ b/packages/ti/boot/sbl/example/boot_app/boot_app_main.c @@ -85,6 +85,9 @@ #include "bist.h" #include "test/osal/osal_interface.h" #endif +#if defined(VTM_TASK_ENABLED) +#include "vtm.h" +#endif /* ========================================================================== */ /* Macros & Typedefs */ /* ========================================================================== */ @@ -95,10 +98,14 @@ #define BOOT_TASK_PRIORITY (2) #if defined(BIST_TASK_ENABLED) -#define BIST_TASK_PRIORITY (3) +#define BIST_TASK_PRIORITY (4) #define BIST_TASK_STACKSIZE (16U * 1024U) #endif +#if defined(VTM_TASK_ENABLED) +#define VTM_TASK_PRIORITY (3) +#define VTM_TASK_STACKSIZE (10U * 1024U) +#endif /* uncomment the following for debug logs */ // #define UART_PRINT_DEBUG @@ -115,6 +122,9 @@ static void BootApp_TaskFxn(void* a0, void* a1); #if defined(BIST_TASK_ENABLED) static void BistApp_TaskFxn(void* a0, void* a1); #endif +#if defined(VTM_TASK_ENABLED) +static void VtmApp_TaskFxn(void* a0, void* a1); +#endif static uint32_t Boot_App(); static void BootApp_AppSetup(); static int32_t BootApp_RequestStageCores(uint8_t stageNum); @@ -144,6 +154,14 @@ static uint64_t gtimeBistAppStart, gtimeBistAppFinish; static SemaphoreP_Handle gBistTaskCompletedSem = NULL; #endif +#if defined(VTM_TASK_ENABLED) +static uint8_t gVtm_TaskStack[VTM_TASK_STACKSIZE] __attribute__((aligned(32))); +TaskP_Handle gVtmTask; +static uint64_t gtimeVtmAppStart, gtimeVtmAppFinish; +/* Semaphore to indicate VTM Task completion */ +static SemaphoreP_Handle gVtmTaskCompletedSem = NULL; +#endif + int32_t main(void) { Board_initCfg boardCfg; @@ -201,6 +219,31 @@ int32_t main(void) OS_stop(); } #endif + +#if defined(VTM_TASK_ENABLED) + /* initializing the semaphores*/ + SemaphoreP_Params VtmsemParams; + SemaphoreP_Params_init(&VtmsemParams); + gVtmTaskCompletedSem = SemaphoreP_create(0, &VtmsemParams); + if(NULL == gVtmTaskCompletedSem) + { + UART_printf("\n Semaphore create failed\r\n"); + } + + /* Initialize the task params */ + TaskP_Params VtmTaskParams; + TaskP_Params_init(&VtmTaskParams); + VtmTaskParams.priority = VTM_TASK_PRIORITY; + VtmTaskParams.stack = gVtm_TaskStack; + VtmTaskParams.stacksize = sizeof (gVtm_TaskStack); + + gVtmTask = TaskP_create(&VtmApp_TaskFxn, &VtmTaskParams); + if (NULL == gVtmTask) + { + UART_printf("\nVTM Task creation failed\r\n"); + OS_stop(); + } +#endif OS_start(); /* does not return */ return(0); @@ -211,6 +254,10 @@ static void BootApp_TaskFxn(void* a0, void* a1) #if defined(BIST_TASK_ENABLED) /* Wait for the BIST task completion */ SemaphoreP_pend(gBistTaskCompletedSem, SemaphoreP_WAIT_FOREVER); +#endif +#if defined(VTM_TASK_ENABLED) + /* Wait for the VTM task completion */ + SemaphoreP_pend(gVtmTaskCompletedSem, SemaphoreP_WAIT_FOREVER); #endif gtimeBootAppStart = BootApp_GetTimeInMicroSec(CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM)); @@ -244,6 +291,27 @@ static void BistApp_TaskFxn(void* a0, void* a1) } #endif +#if defined(VTM_TASK_ENABLED) +static void VtmApp_TaskFxn(void* a0, void* a1) +{ + /* Initialize the SDL osal */ + SDL_TEST_osalInit(); + + gtimeVtmAppStart = BootApp_GetTimeInMicroSec(CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM)); + + vtm_example_app(); + + gtimeVtmAppFinish = BootApp_GetTimeInMicroSec(CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM)); + + UART_printf("\nVTM Task started at %d usecs and finished at %d usecs\r\n", (uint32_t)gtimeVtmAppStart, (uint32_t)gtimeVtmAppFinish); + + /* Post semaphore after VTM task completion so other tasks could start execution */ + SemaphoreP_post(gVtmTaskCompletedSem); + + return; +} +#endif + uint32_t Boot_App() { uint32_t retVal; diff --git a/packages/ti/boot/sbl/example/boot_app/vtm/vtm.c b/packages/ti/boot/sbl/example/boot_app/vtm/vtm.c new file mode 100644 index 00000000..90d096e2 --- /dev/null +++ b/packages/ti/boot/sbl/example/boot_app/vtm/vtm.c @@ -0,0 +1,442 @@ +/* + * VTM Example Application + * + * Voltage and Thermal Monitor (VTM) Example Application + * + * Copyright (c) 2024 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file vtm.c + * + * \brief This file contains functions that provide functions + * for the Voltage and Thermal Monitor (VTM) application. + */ +/* For Timer functions */ +#include + +#include "vtm.h" +#include "sdl_esm.h" +#include +#include +#include + + +#define USE_CASES_RUN (2) +#define USE_CASES (2) +#define START_USE_CASE (0) +#define MAX_ESM_EVENTS_LOGGED (20) +#define SDLR_WKUP_ESM0_ESM_LVL_EVENT_WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0 (8U) +#define SDLR_WKUP_ESM0_ESM_LVL_EVENT_WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0 (9U) +#define APP_ARG (1) + +/* #define DEBUG */ + +static uint32_t totalEventsLogged = 0; +static uint32_t totalHiEventsLogged = 0; +static uint32_t totalLoEventsLogged = 0; +static int32_t thresholdsReset = 0; +int32_t apparg = APP_ARG; +/* ESM event log entry */ +typedef struct +{ + SDL_ESM_Inst esmInstance; + SDL_ESM_IntType intType; + uint32_t grpChannel; + uint32_t index; + uint32_t intSrc; + uint8_t useCaseNum; +} VTM_Example_log_entry_t; +static int32_t deactivateTrigger(SDL_ESM_Inst esmInstType, + SDL_ESM_IntType esmIntType, + uint32_t intEsmSrc); + +static VTM_Example_log_entry_t esmEventLog[MAX_ESM_EVENTS_LOGGED]; + + +/* State variable for each test case indicating input event trigger + * has been completed */ +volatile uint32_t vtmEventInputTrig[USE_CASES] = {USE_CASE_STATUS_NOT_RUN, + USE_CASE_STATUS_NOT_RUN}; + +/* State variable for each test case indicating the ISR for the test case + * has been completed */ +volatile uint32_t vtmOutputResult[USE_CASES] = {USE_CASE_STATUS_NOT_RUN, + USE_CASE_STATUS_NOT_RUN}; + +volatile uint8_t currTestCase = START_USE_CASE; + +static const char *printTestCaseStepResult(uint32_t result); +void vtm_example_test_app_runner(void); +void VTM_test_printSummary(void); +int32_t VTM_ESM_init (void); + +/* Initialization structure for WKUP ESM instance */ +static SDL_ESM_config VTM_esmInitConfig_WKUP = +{ + .esmErrorConfig = {0u, 0u}, /* Self test error config */ + .enableBitmap = {0xffffffffu, 0x00180003u, 0xffffffffu, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + }, + /**< All events enable: except clkstop events for unused clocks */ + .priorityBitmap = {0xfffffcffu, 0x00180003u, 0xffffffffu, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + }, + /**< All events high priority: except clkstop events for unused clocks, + * and make VTM WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0 and + * WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0 events low priority */ + .errorpinBitmap = {0xfffffcffu, 0x00180003u, 0xffffffffu, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, + }, + /**< All events high priority: except clkstop for unused clocks + * and make VTM WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0 and + * WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0 events not output to pin */ +}; +static const char *printEsmIntType(SDL_ESM_IntType esmIntType) +{ + char *pStr; + + switch(esmIntType) + { + case SDL_ESM_INT_TYPE_HI: + pStr = "High Priority ESM event"; + break; + case SDL_ESM_INT_TYPE_LO: + pStr = "Low Priority ESM event"; + break; + case SDL_ESM_INT_TYPE_CFG: + pStr = "Config ESM event"; + break; + default: + pStr = NULL; + break; + } + + return pStr; +} + + + + +int32_t SDL_ESM_applicationCallbackFunction(SDL_ESM_Inst esmInstType, + SDL_ESM_IntType esmIntType, + uint32_t grpChannel, + uint32_t index, + uint32_t intSrc, + void *arg) +{ + /* Log the event */ + esmEventLog[totalEventsLogged].useCaseNum = currTestCase; + esmEventLog[totalEventsLogged].esmInstance = esmInstType; + esmEventLog[totalEventsLogged].intType = esmIntType; + esmEventLog[totalEventsLogged].grpChannel = grpChannel; + esmEventLog[totalEventsLogged].index = index; + esmEventLog[totalEventsLogged].intSrc = intSrc; + + totalEventsLogged++; + if (esmIntType == SDL_ESM_INT_TYPE_HI) { + totalHiEventsLogged++; + } else if (esmIntType == SDL_ESM_INT_TYPE_LO) { + totalLoEventsLogged++; + } + + /* Any additional customer-specific actions to address ESM event + * can be added here */ + + deactivateTrigger(esmInstType, esmIntType, intSrc); + + /* Print information to screen */ + UART_printf("\n ESM Call back function called : instType 0x%x, intType 0x%x, " \ + "grpChannel 0x%x, index 0x%x, intSrc 0x%x \n", + esmInstType, esmIntType, grpChannel, index, intSrc); + UART_printf(" Take action \n"); + + UART_printf(" ESM instance #%d, ESM interrupt type = %s\n", + esmInstType, printEsmIntType(esmIntType)); + + vtmOutputResult[currTestCase]= USE_CASE_STATUS_COMPLETED_SUCCESS; + + return SDL_PASS; +} + +/********************************************************************* +* @fn VTM_ESM_init +* +* @brief Initializes Board, Timers, and ESM module +* +* @param None +* +* @return 0 : Success; < 0 for failures +*/ +int32_t VTM_ESM_init (void) +{ + int32_t retValue=0; + int32_t result; + /* Initialize WKUP ESM module */ + result = SDL_ESM_init(SDL_ESM_INST_WKUP_ESM0, &VTM_esmInitConfig_WKUP, SDL_ESM_applicationCallbackFunction, &apparg); + if (result != SDL_PASS) { + /* print error and quit */ + UART_printf("VTM_ESM_init: Error initializing WKUP ESM: result = %d\n", result); + + retValue = -1; + } else { + UART_printf("\nVTM_ESM_init: Init WKUP ESM complete \n"); + } + return retValue; +} + +static int32_t deactivateTrigger(SDL_ESM_Inst esmInstType, + SDL_ESM_IntType esmIntType, + uint32_t intEsmSrc) +{ + int32_t retVal = 0; + + if ((esmInstType == SDL_ESM_INST_WKUP_ESM0) && (esmIntType == SDL_ESM_INT_TYPE_LO)) { + /* UC-1: Low Priority interrupt on WKUP ESM - + * VTM greater than THR1 */ + if (intEsmSrc == + SDLR_WKUP_ESM0_ESM_LVL_EVENT_WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0) + { + if (currTestCase == 0) + { + if (thresholdsReset == 0) + { + /* Simulate thresholds as if temperature is going to be reduced + * below lt_Thr0 */ + vtm_setNormalThresholds(); + + thresholdsReset = 1; + } + SDL_VTM_IntrruptGtThr1(); + } else if (currTestCase == 1) + { + if (thresholdsReset == 0) + { + /* Simulate thresholds as if temperature continues to increase + * toward gt_Thr2 */ + vtm_setThresholdsForCriticalTrigger(); + + thresholdsReset = 1; + } + SDL_VTM_IntrruptGtThr1(); + } + } else if (intEsmSrc == + SDLR_WKUP_ESM0_ESM_LVL_EVENT_WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0) + { + SDL_VTM_IntrruptLtThr0(); + + thresholdsReset = 0; + if (currTestCase == 0) { + /* At end of this test case, clear the Pin that was left on + * throughout the test case*/ + Osal_delay(4); + } + } + } else if ((esmInstType == SDL_ESM_INST_WKUP_ESM0) && + (esmIntType == SDL_ESM_INT_TYPE_HI)) { + + if (currTestCase == 1) { + /* UC-2 High Priority interrupt on WKUP ESM - + * VTM greater than THR2 with clearing + * of MCU_SAFETY_ERRORn pin */ + if (thresholdsReset == 1) + { + /* Simulate thresholds as if temperature is going to be reduced + * below lt_Thr0 */ + vtm_setNormalThresholds(); + + thresholdsReset = 2; + } + if (currTestCase == 1) { + SDL_ESM_resetErrPin(SDL_WKUP_ESM0_CFG_BASE); + } + SDL_VTM_IntrruptGtThr2(); + } else { + retVal = -1; + } + } else { + UART_printf("ERR: Unexpected ESM Instance %d and ESM Interrupt Type %d \n", + esmInstType, esmIntType); + retVal = -1; + } + + return (retVal); +} + +/********************************************************************* +* @fn VTM_app_printSummary +* +* @brief Print summary of all the test cases run +* +* @param None +* +* @return None +*/ +void VTM_test_printSummary(void) +{ + int32_t i; + + UART_printf("\n\n"); + UART_printf("ESM Example Application summary\n"); + UART_printf("-------------------------------\n"); + UART_printf("Completed %d Test Cases\n", currTestCase); + UART_printf("Received %d High Priority Interrupts\n", totalHiEventsLogged); + UART_printf("Received %d Low Priority Interrupts\n", totalLoEventsLogged); + + UART_printf("\nTest Case Event Log\n"); + UART_printf("------------------\n"); + for (i = 0; i < totalEventsLogged; i++) { + UART_printf("\nTest Case %d: ESM Call back function called : grpChannel 0x%x, " \ + "index 0x%x, intSrc 0x%x \n", + esmEventLog[i].useCaseNum, + esmEventLog[i].grpChannel, + esmEventLog[i].index, + esmEventLog[i].intSrc); + UART_printf(" ESM instance #%d, ESM interrupt type = %s\n", + esmEventLog[i].esmInstance, + printEsmIntType(esmEventLog[i].intType)); + + } +} + + + +/***************************************************************************** + * This is the main function for the Voltage and Thermal Monitor (VTM) example + * application. + * It runs through 2 test cases to demonstrate usage of the VTM modules + * for receiving errors and controlling the error pin. + */ +void vtm_example_app(void) +{ + int32_t testErrCount = 0; + int32_t retValue; + uint8_t i; + + /* Initialize the ESM instances and handlers */ + retValue = VTM_ESM_init(); + + if (retValue < 0) { + /* print and exit */ + UART_printf("\nERR: VTM_ESM_init failed"); + testErrCount++; + } + + UART_printf("\n VTM_ESM_init complete"); + + /* Trigger each Test Case */ + for (i = START_USE_CASE; i < 2; i++) { + retValue = vtm_runTestCaseTrigger(i); + + if (retValue != 0) { + UART_printf("\nERR: Use Case Trigger for Use Case %d failed \n", + retValue); + break; + } + + while((vtmEventInputTrig[i] == USE_CASE_STATUS_NOT_RUN) || + (vtmOutputResult[i] == USE_CASE_STATUS_NOT_RUN)) + { +#ifdef DEBUG + UART_printf("InputTrig = %d, OutputResult = %d, ClearResult = %d\n", + vtmEventInputTrig[i], + vtmOutputResult[i]); +#endif + } + UART_printf("\n Use Case %d completed: Input Event Trigger = %s, \n", + i, + printTestCaseStepResult(vtmEventInputTrig[i])); + currTestCase++; + } + + /* Check results of all the tests */ + for (i = 0; i < 2; i++) { + if ((vtmEventInputTrig[i] != USE_CASE_STATUS_COMPLETED_SUCCESS) || + (vtmOutputResult[i] != USE_CASE_STATUS_COMPLETED_SUCCESS)) { + testErrCount++; + } + } + + /* Print results and logs of the Test Cases */ + VTM_test_printSummary(); + UART_printf("\n VTM Example Application: Complete"); + + if (testErrCount == 0) + { + UART_printf("\n All Use cases have passed. \n"); + } + else + { + UART_printf("\n VTM Example app failed. \n"); + } + return; +} + +static const char *printTestCaseStepResult(uint32_t result) +{ + char *pStr; + + switch(result) + { + case USE_CASE_STATUS_NOT_RUN: + pStr = "Step Not yet run"; + break; + case USE_CASE_STATUS_COMPLETED_SUCCESS: + pStr = "Step completed successfully"; + break; + case USE_CASE_STATUS_COMPLETED_FAILURE: + pStr = "Step completed with failure"; + break; + default: + pStr = NULL; + break; + } + + return pStr; +} +/* Nothing past this point */ \ No newline at end of file diff --git a/packages/ti/boot/sbl/example/boot_app/vtm/vtm.h b/packages/ti/boot/sbl/example/boot_app/vtm/vtm.h new file mode 100644 index 00000000..45bc5ce9 --- /dev/null +++ b/packages/ti/boot/sbl/example/boot_app/vtm/vtm.h @@ -0,0 +1,66 @@ +/* + * VTM Example Application + * + * Voltage and Thermal Monitor (VTM) Example Application + * + * Copyright (c) 2024 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file vtm.h + * + * \brief This file contains functions that provide functions + * for the Voltage and Thermal Monitor (VTM) application. + */ + + +#ifndef __VTM__ +#define __VTM__ + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ +/* Function prototypes */ +void vtm_example_app(void); + +int32_t vtm_runTestCaseTrigger(uint8_t useCaseId); +int32_t vtm_setNormalThresholds(void); +int32_t vtm_setThresholdsForCriticalTrigger(void); +int32_t vtm_printCurrentThresholds(void); + +void SDL_VTM_IntrruptLtThr0(void); +void SDL_VTM_IntrruptGtThr1(void); +void SDL_VTM_IntrruptGtThr2(void); + +#define USE_CASE_STATUS_NOT_RUN (0u) +#define USE_CASE_STATUS_COMPLETED_SUCCESS (1u) +#define USE_CASE_STATUS_COMPLETED_FAILURE (2u) + +#endif /* __VTM__ */ \ No newline at end of file diff --git a/packages/ti/boot/sbl/example/boot_app/vtm/vtm_example.c b/packages/ti/boot/sbl/example/boot_app/vtm/vtm_example.c new file mode 100644 index 00000000..1f44d5c8 --- /dev/null +++ b/packages/ti/boot/sbl/example/boot_app/vtm/vtm_example.c @@ -0,0 +1,438 @@ +/* + * VTM Example Application + * + * Voltage and Thermal Monitor (VTM) Example Application + * + * Copyright (c) 2024 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file vtm_example.c + * + * \brief This file contains functions that provide input event triggers + * for the Voltage and Thermal Monitor (VTM) application. + */ + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ + +#include +#include +#include +#include "vtm.h" +#include +#include +#include +#include +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +#define LT_THR0_DEFAULT (95000) +#define GT_THR1_DEFAULT (105000) +#define GT_THR2_DEFAULT (115000) + +/* ========================================================================== */ +/* Structure Declarations */ +/* ========================================================================== */ + +/* None */ + +/* ========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +static int32_t vtmTriggerTh(int32_t lt_thr0_offset, + int32_t gt_thr1_offset, + int32_t gt_thr2_offset); +static int32_t SDL_VTM_config(void); +static void setAllVTMTempThr(SDL_VTM_adc_code lt_thr0_adc_code, + SDL_VTM_adc_code gt_thr1_adc_code, + SDL_VTM_adc_code gt_thr2_adc_code); + +/* ========================================================================== */ +/* Global Variables */ +/* ========================================================================== */ + +/* Completion of Use Case from Input trigger perspective updates these flags */ +extern volatile uint32_t vtmEventInputTrig[2]; +/* Current Use case being run */ +extern volatile uint8_t currTestCase; +uint32_t pStatus; +SDL_ESM_Inst currEsmInstance; + + +/* ========================================================================== */ +/* External Variables */ +/* ========================================================================== */ + +/* None */ + +/* ========================================================================== */ +/* Function Definitions */ +/* ========================================================================== */ + +/* +* This function modifies all the VTM thresholds in a single function to ensure +* appropriate number of ESM events are triggered by the change in thresholds. +*/ +static void setAllVTMTempThr(SDL_VTM_adc_code lt_thr0_adc_code, + SDL_VTM_adc_code gt_thr1_adc_code, + SDL_VTM_adc_code gt_thr2_adc_code) +{ + + SDL_VTM_tsThrVal thr_val; + SDL_VTM_intrCtrl ctrl; + SDL_VTM_configTs cfgTs; + thr_val.thrValidMap = SDL_VTM_GT_TH1_VALID | \ + SDL_VTM_GT_TH2_VALID | \ + SDL_VTM_LT_TH0_VALID; + thr_val.gtTh2En = TRUE; + thr_val.gtTh2 = gt_thr2_adc_code; + thr_val.gtTh1En = TRUE; + thr_val.gtTh1 = gt_thr1_adc_code; + thr_val.ltTh0En = TRUE; + thr_val.ltTh0 = lt_thr0_adc_code; + cfgTs.thr_val = thr_val; + cfgTs.tsCtrl_cfg.valid_map = 0; + cfgTs.tsCtrl_cfg.maxt_outrg_alert_en = 0; + cfgTs.tsCtrl_cfg.tsReset = 0; + cfgTs.tsCtrl_cfg.adc_stat = 0; + cfgTs.tsCtrl_cfg.mode = 0; + cfgTs.configTsCtrl = SDL_VTM_VD_CONFIG_CTRL_SET_THR; + + ctrl = SDL_VTM_VD_GT_THR2_INTR_EN_SET | \ + SDL_VTM_VD_GT_THR1_INTR_EN_SET | \ + SDL_VTM_VD_LT_THR0_INTR_EN_CLR; + + SDL_VTM_configVd cfgVd; + cfgVd.configVdCtrl = SDL_VTM_VD_CONFIG_CTRL_EVT_SEL; + cfgVd.vd_temp_evts = SDL_VTM_VD_EVT_SELECT_TEMP_SENSOR_0; + SDL_VTM_tsGlobal_cfg tsGlobalCfg; + tsGlobalCfg.validMap = 0; + tsGlobalCfg.clkSel = 0; + tsGlobalCfg.clkDiv = 0; + tsGlobalCfg.any_maxt_outrg_alert_en = 0; + tsGlobalCfg.maxt_outrg_alert_thr0 = 0; + tsGlobalCfg.maxt_outrg_alert_thr = 0; + tsGlobalCfg.samplesPerCnt = 0; + cfgVd.tsGlobal_cfg = tsGlobalCfg; + /* Set the temperature thresholds */ + SDL_VTM_initTs(SDL_VTM_INSTANCE_TS_0 , &cfgTs); + + /* enable the threshold interrupts */ + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + + /* enable the tracking of temperature events on this VD */ + SDL_VTM_initVd(SDL_VTM_INSTANCE_VD_DOMAIN_1, &cfgVd); +} + +/* +* This function reads the current temperature in the VTM module +* and then modifies the VTM thresholds to cause events to trigger. +* Note that in a typical system, the thresholds would be kept the static, and +* changes in temperature would cause the events to occur. +*/ +static int32_t vtmTriggerTh(int32_t lt_thr0_offset, + int32_t gt_thr1_offset, + int32_t gt_thr2_offset) +{ + int32_t retVal = 0; + int32_t temp_milli_degrees_read; + SDL_VTM_InstTs insTs = SDL_VTM_INSTANCE_TS_0; + SDL_VTM_adc_code adc_code_read; + SDL_VTM_adc_code adc_code_lt_thr0 = 0, adc_code_gt_thr1 = 0, adc_code_gt_thr2 = 0; + int32_t gt_thr2_val, gt_thr1_val, lt_thr0_val; + SDL_VTM_intrCtrl ctrl; + SDL_VTM_Stat_val statusVal; + SDL_VTM_Stat_read_ctrl readCtrl; + SDL_VTM_configTs cfgTs; + readCtrl = SDL_VTM_TS_READ_DATA_OUT_VAL; + + /* Set temp sensor for continuous mode */ + cfgTs.configTsCtrl = SDL_VTM_VD_CONFIG_CTRL_SET_CTL; + cfgTs.tsCtrl_cfg.valid_map = SDL_VTM_TS_CTRL_MODE_VALID; + cfgTs.tsCtrl_cfg.mode = SDL_VTM_TS_CTRL_CONTINUOUS_MODE; + SDL_VTM_initTs(SDL_VTM_INSTANCE_TS_0 , &cfgTs); + + /* Get current temperature value */ + SDL_VTM_getSensorStatus(insTs, &readCtrl, &statusVal); + adc_code_read = statusVal.data_out; + (void) SDL_VTM_tsConvADCToTemp (adc_code_read, insTs, \ + &temp_milli_degrees_read); +#ifdef DEBUG + UART_printf ("sensor id : %d \n" \ + "adc_code : %d \n" \ + "temp in milli degree celcius : %d \n", \ + insTs, adc_code_read, temp_milli_degrees_read); +#endif + + /* Disable interrupts while changing thresholds */ + ctrl = (SDL_VTM_VD_GT_THR2_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR2_INTR_RAW_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_RAW_CLR | \ + SDL_VTM_VD_LT_THR0_INTR_EN_CLR | \ + SDL_VTM_VD_LT_THR0_INTR_RAW_CLR); + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + + /* Change all 3 thresholds relative to the current temperature */ + lt_thr0_val = temp_milli_degrees_read + lt_thr0_offset; + gt_thr1_val = temp_milli_degrees_read + gt_thr1_offset; + gt_thr2_val = temp_milli_degrees_read + gt_thr2_offset; + + SDL_VTM_tsConvTempToAdc(lt_thr0_val, insTs, &adc_code_lt_thr0); + SDL_VTM_tsConvTempToAdc(gt_thr1_val, insTs, &adc_code_gt_thr1); + SDL_VTM_tsConvTempToAdc(gt_thr2_val, insTs, &adc_code_gt_thr2); + +#ifdef DEBUG + UART_printf ("vtmTriggerTh: Setting lt_thr0_val temp to " \ + "%d millidegrees Celsius, and adc_code_lt_thr0 = %d\n", + lt_thr0_val, + adc_code_lt_thr0); + UART_printf ("vtmTriggerTh: Setting gt_thr1_val temp to " \ + "%d millidegrees Celsius, and adc_code_gt_thr1 = %d\n", + gt_thr1_val, + adc_code_gt_thr1); + UART_printf ("vtmTriggerTh: Setting gt_thr2_val temp to " \ + "%d millidegrees Celsius, and adc_code_gt_thr2 = %d\n", + gt_thr2_val, + adc_code_gt_thr2); +#endif + + setAllVTMTempThr(adc_code_lt_thr0, adc_code_gt_thr1, adc_code_gt_thr2); + +#ifdef DEBUG + UART_printf("Finished VTM threshold setting\n"); +#endif + return (retVal); +} + +static int32_t SDL_VTM_config(void) +{ + int32_t retVal = 0; +#ifdef DEBUG + UART_printf("SDL_VTM_config: starting test with threshold change\n"); +#endif + retVal = vtmTriggerTh(-4000, -2000, 5000); + + return (retVal); +} + +/* +* This function clears VTM THR0 interrupt (Less Than Temp event) +* for VTM input events to the ESM. +* It resets the VTM module to look for high temperature events again. +*/ +void SDL_VTM_IntrruptLtThr0(void) +{ + SDL_VTM_intrCtrl ctrl; + + /* Ack the interrupt, by clearing the pending bit */ + ctrl = (SDL_VTM_VD_LT_THR0_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_EN_SET | \ + SDL_VTM_VD_GT_THR2_INTR_EN_SET | \ + SDL_VTM_VD_LT_THR0_INTR_RAW_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_RAW_CLR | \ + SDL_VTM_VD_GT_THR2_INTR_RAW_CLR); + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + /* Print output ESM event to the screen */ + UART_printf ("\n Got ltThr0 interrupt through ESM module\n"); + UART_printf ("\n System at a temperature below the threshold of lt_thr0 \n" + " System running at a safe temperature \n"); +} + +/* +* This function clears VTM THR1 interrupts for VTM input event to the ESM. +*/ +void SDL_VTM_IntrruptGtThr1(void) +{ + SDL_VTM_intrCtrl ctrl; + /* + - disable the gt1 interrupt + - clear the gt1 interrupt + - clear the lt0 interrupt + - enable the lt0 intterupt + */ + ctrl = (SDL_VTM_VD_GT_THR1_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_RAW_CLR | \ + SDL_VTM_VD_LT_THR0_INTR_EN_SET | \ + SDL_VTM_VD_LT_THR0_INTR_RAW_CLR); + + /* Ack and Re-enable the LT_THR0 interrupt to let system know if cooling + * took place */ + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + + /* Print output ESM event to the screen */ + UART_printf ("\n Got gtThr1 interrupt through ESM module\n"); + UART_printf ("\n Crossed early warning threshold of gt_thr1 \n" + " System should take action to implement system cooling \n"); +} + +/* +* This function clears VTM THR2 interrupts for VTM input event to the ESM. +*/ +void SDL_VTM_IntrruptGtThr2(void) +{ + SDL_VTM_intrCtrl ctrl; + /* Ack the interrupt, by clearing the pending bit */ + ctrl = (SDL_VTM_VD_GT_THR2_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR2_INTR_RAW_CLR); + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + + /* Print output ESM event to the screen */ + UART_printf ("\n Got gtThr2 interrupt through ESM module\n"); + UART_printf ("\n Crossed critical threshold of gt_thr2 \n" + " System should take critical action to implement system cooling \n"); +} + + +int32_t vtm_setThresholdsForCriticalTrigger(void) +{ + int32_t retVal = 0; +#ifdef DEBUG + UART_printf("vtm_setThresholdsForCriticalTrigger: setting thresholds " \ + "to trigger high priority thermal event.\n"); +#endif + retVal = vtmTriggerTh(-12000, -8000, -3000); + + return (retVal); +} + +/* +* This function resets the VTM thresholds back to some typical default +* values. +*/ +int32_t vtm_setNormalThresholds(void) +{ + int32_t retVal = 0; + SDL_VTM_InstTs insTs = SDL_VTM_INSTANCE_TS_0; + SDL_VTM_adc_code adc_code_lt_thr0 = 0, adc_code_gt_thr1 = 0, adc_code_gt_thr2 = 0; + int32_t gt_thr2_val, gt_thr1_val, lt_thr0_val; + SDL_VTM_intrCtrl ctrl; + +#ifdef DEBUG + UART_printf("Start changing to normal VTM threshold setting\n"); +#endif + + /* Disable interrupts while changing thresholds */ + ctrl = (SDL_VTM_VD_GT_THR2_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR2_INTR_RAW_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_EN_CLR | \ + SDL_VTM_VD_GT_THR1_INTR_EN_CLR | \ + SDL_VTM_VD_LT_THR0_INTR_EN_CLR | \ + SDL_VTM_VD_LT_THR0_INTR_RAW_CLR); + + SDL_VTM_intrCntrl(SDL_VTM_INSTANCE_VD_DOMAIN_1, ctrl); + + /* Set to default values */ + lt_thr0_val = LT_THR0_DEFAULT; + gt_thr1_val = GT_THR1_DEFAULT; + gt_thr2_val = GT_THR2_DEFAULT; + + SDL_VTM_tsConvTempToAdc(lt_thr0_val, insTs, &adc_code_lt_thr0); + SDL_VTM_tsConvTempToAdc(gt_thr1_val, insTs, &adc_code_gt_thr1); + SDL_VTM_tsConvTempToAdc(gt_thr2_val, insTs, &adc_code_gt_thr2); + +#ifdef DEBUG + UART_printf ("vtm_setNormalThresholds: Setting lt_thr0_val temp to %d " \ + "millidegrees Celsius, and adc_code_lt_thr0 = %d\n", + lt_thr0_val, + adc_code_lt_thr0); + UART_printf ("vtm_setNormalThresholds: Setting gt_thr1_val temp to %d " \ + "millidegrees Celsius, and adc_code_gt_thr1 = %d\n", + gt_thr1_val, + adc_code_gt_thr1); + UART_printf ("vtm_setNormalThresholds: Setting gt_thr2_val temp to %d " \ + "millidegrees Celsius, and adc_code_gt_thr2 = %d\n", + gt_thr2_val, + adc_code_gt_thr2); +#endif + + setAllVTMTempThr(adc_code_lt_thr0, adc_code_gt_thr1, adc_code_gt_thr2); + +#ifdef DEBUG + UART_printf("Finished normal VTM threshold setting\n"); +#endif + + return (retVal); +} + +/* USE CASE FUNCTIONS */ + +/* +* This function initiates the input trigger event for each use case +*/ +int32_t vtm_runTestCaseTrigger(uint8_t useCaseId) +{ + int32_t retVal = 0; + UART_printf("\nStarting Use Case %d \n", useCaseId); + switch(useCaseId) + { + case 0: + /* UC-1: Low Priority interrupt on WKUP ESM - + * VTM less than THR1 */ + currEsmInstance = SDL_ESM_INST_WKUP_ESM0; + retVal = SDL_VTM_config(); + if (retVal == 0) { + UART_printf("case 0 success\n"); + vtmEventInputTrig[useCaseId] = USE_CASE_STATUS_COMPLETED_SUCCESS; + } else{ + UART_printf("case 0 failure\n"); + vtmEventInputTrig[useCaseId] = USE_CASE_STATUS_COMPLETED_FAILURE; + } + break; + + case 1: + /* UC-2: High Priority interrupt on WKUP ESM - + * VTM greater than THR2 with clearing + * of MCU_SAFETY_ERRORn pin */ + + /* Start the Pin Control and Measurement Timer */ + currEsmInstance = SDL_ESM_INST_WKUP_ESM0; + retVal = SDL_VTM_config(); + if (retVal == 0) { + vtmEventInputTrig[useCaseId] = USE_CASE_STATUS_COMPLETED_SUCCESS; + } else { + vtmEventInputTrig[useCaseId] = USE_CASE_STATUS_COMPLETED_FAILURE; + } + break; + + default: + UART_printf("ERR: Invalid Test Case ID %d \n", useCaseId); + retVal = -1; + break; + } + + return (retVal); +} + +/* Nothing past this point */ \ No newline at end of file -- 2.34.1