Part Number: SAFETI_DIAG_LIB
Hello everyone,
I am trying to use the SafeTI DiagLib with the Hercules TMS270LS1224 Launchpad, and for the moment, I am facing some issues, that lead me to ask for some help.
Here is the aim: I would like to have a function that I will call at each complete sequence of my main application in a while() loop. That functino would be a target_self_test() which executes each required tests for the application, based on the SafeTI Diaglib API.
So something like this (n.b. All the calls for the sl functions, ESM callback etc... copy-paste from the example SL_TMS570LS1227_NoOS):
error_t target_selftest(void) { volatile boolean retVal; uint8 error_happened = 0; /* Init SL ESM for SL callback requirement */ SL_ESM_Init(ESM_ApplicationCallback); /* Self Test for VIM Module */ retVal = SL_SelfTest_VIM(VIM_SOFTWARE_TEST); // Fail if (true == retVal) { char tmps[] = "Test VIM_SOFTWARE_TEST successfully passed\n"; sciSend(scilinREG, sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test VIM_SOFTWARE_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; } retVal = SL_SelfTest_VIM(VIM_SRAM_PARITY_TEST); //INCREMENT_PASS_FAIL_COUNTER(ST_PASS, retVal); if (true == retVal) { char tmps[] = "Test VIM_SRAM_PARITY_TEST successfully passed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test VIM_SRAM_PARITY_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; } /* Self Test for SPI as GIO */ retVal = SL_SelfTest_SPI(SPI_ANALOG_LOOPBACK_TEST, SL_SPI3); if (true == retVal) { char tmps[] = "Test SPI_ANALOG_LOOPBACK_TEST successfully passed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test SPI_ANALOG_LOOPBACK_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; } /* Self Test for GIO */ retVal = SL_SelfTest_GIO(GIO_ANALOG_LOOPBACK_TEST, SL_GIOPORTB, 1); if (true == retVal) { char tmps[] = "Test GIO_ANALOG_LOOPBACK_TEST successfully passed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test GIO_ANALOG_LOOPBACK_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; } /* Self Test for MIBSPI as GIO */ retVal = SL_SelfTest_SPI(SPI_ANALOG_LOOPBACK_TEST, SL_SPI3); // Fail //INCREMENT_PASS_FAIL_COUNTER(ST_PASS, retVal); if (true == retVal) { char tmps[] = "Test SPI_ANALOG_LOOPBACK_TEST successfully passed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test SPI_ANALOG_LOOPBACK_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; } /* Self Test for SPI as GIO */ retVal = SL_SelfTest_LIN(LIN_ANALOG_LOOPBACK_TEST, SL_LIN2); // Fail //INCREMENT_PASS_FAIL_COUNTER(ST_PASS, retVal); if (true == retVal) { char tmps[] = "Test LIN_ANALOG_LOOPBACK_TEST successfully passed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); } else { char tmps[] = "Test LIN_ANALOG_LOOPBACK_TEST Failed\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); error_happened = 1; if (1 == error_happened) { char tmps[] = "Target selftests failed.\n"; sciSend(scilinREG,sizeof(tmps), (unsigned char *)tmps); while(1); } return (error_t) retVal; } /* Main app */ int main(void) { /* USER CODE BEGIN (3) */ uint8_t temps[] = "Init done\n"; error_t ret_value = APP_OK; /** Modules init */ /* Init GIO for LED */ gioInit(); /* Init SCI/LIN */ sciInit(); /* Init RTI */ rtiInit(); /* Init MIBSPI for Switch */ mibspiInit(); /* IRQ Allowed */ _enable_IRQ(); /* Call self test routine before starting IRQ and app*/ ret_value = target_selftest(); /* Start RTI Counter Block 0, 500ms */ rtiStartCounter(rtiCOUNTER_BLOCK0); /* Start RTI Counter Block 1, 5ms */ rtiStartCounter(rtiCOUNTER_BLOCK1); /* Enable RTI Compare 0 & 1 interrupt notification */ rtiEnableNotification(rtiNOTIFICATION_COMPARE0); rtiEnableNotification(rtiNOTIFICATION_COMPARE1); /* Call app_init */ ret_value = app_init(); /** Modules init finished **/ sciSend(scilinREG, sizeof(temps), (unsigned char *)temps); /* App */ while(APP_OK == ret_value) { app_main(); ret_value = target_selftest(); } /* USER CODE END */ return 0; }
This is just to give an idea of what I would like to do of course.
Now the issue:
As you can see, two tests are failing, VIM_SOFTWARE, LIN_ANALOG_LOOPBACK_TEST (for SL_LIN2 and SL_SPI3). Let's just forget about the LIN_ANALOG_LOOPBACK_TEST for the moment because I haven't explored it yet. So why the VIM_SOFTWARE doesn't work ? Well, it seems that the test it waiting for a variable to be changed via interrup. This appears on the sl_selftest.c where the test is applied as:
#if defined(_TMS570LS31x_) || defined(_TMS570LS12x_) || defined(_TMS570LS07x_) || defined(_TMS570LS09x_) || defined(_RM48x_) || defined(_RM46x_) || defined(_RM44x_) || defined(_RM42x_) || defined(_TMS570LS04x_) /* cause interrupt (SRAM_RADECODE_DIAGNOSTICS interrupt in this case) - storing retval to avoid misra-c violation */ tmp = SL_SelfTest_SRAM(SRAM_RADECODE_DIAGNOSTICS, TRUE, &failInfoTCMRAM); tmp = tmp; /* to avoid compiler warning */ #endif /* check if the ISR called */ if(vimTestFlag) { retVal = TRUE; /*Test passed*/ } /* Clear global flag */ vimTestFlag = FALSE; /* Clear test type */ SL_FLAG_CLEAR(testType); break;
There, vimTestFlag is never changed to anything else than false. And when I look into the selftestRam, it seems that the SRAM_RADECODE_DIAGNOSTICS should provide the needed interrupt to change this variable (in the function ESM_ApplicationCallback):
#if defined(_TMS570LS31x_) || defined(_TMS570LS12x_) || defined(_TMS570LS07x_) || defined(_TMS570LS09x_) || defined(_RM48x_) || defined(_RM46x_) || defined(_RM44x_) || defined(_RM42x_) || defined(_TMS570LS04x_) || defined(_TMS570LC43x_) || defined(_RM57Lx_) case SRAM_RADECODE_DIAGNOSTICS: retVal = TRUE; #if (FUNCTION_PROFILING_ENABLED != 0) SL_Record_Errorcreationtick(testType); #endif /*flag is set to indicate the current test which is ongoing and These flags are used in the sl_esm.c so as to mask the esm callback*/ (void)SL_FLAG_SET(SRAM_RADECODE_DIAGNOSTICS); #if defined(_TMS570LS31x_) || defined(_TMS570LS12x_) || defined(_TMS570LS07x_) || defined(_TMS570LS09x_) || defined(_RM48x_) || defined(_RM46x_) || defined(_RM44x_) || defined(_RM42x_) || defined(_TMS570LS04x_) _SL_SelfTest_SRAM_RAD(sl_tcram1REG, sram_stResult); /* Note : nERROR pin gets Activated but it is not cleared here but in next _SL_HoldNClear_nError * that is called after few lines with in this function. If User needs can uncomment below Line.*/ //_SL_HoldNClear_nError() if (ST_PASS == *sram_stResult) { sl_esmREG->SR1[1] = (uint32)(1U << ESM_G2ERR_B0TCM_UNCORR); sl_esmREG->SSR2 = (uint32)(1U << ESM_G2ERR_B0TCM_UNCORR); /*flag is set to indicate the current test which is ongoing and These flags are used in the sl_esm.c so as to mask the esm callback*/ (void)SL_FLAG_SET(SRAM_RADECODE_DIAGNOSTICS); _SL_SelfTest_SRAM_RAD(sl_tcram2REG, sram_stResult); _SL_HoldNClear_nError(); /* Clear nError */ if (ST_PASS == *sram_stResult) { sl_esmREG->SR1[1] = (uint32)(1U << ESM_G2ERR_B1TCM_UNCORR); sl_esmREG->SSR2 = (uint32)(1U << ESM_G2ERR_B1TCM_UNCORR); } } #endif #if defined(_TMS570LC43x_) || defined(_RM57Lx_) _SL_SelfTest_SRAM_RAD(sl_l2ramwREG, sram_stResult); _SL_HoldNClear_nError(); /* Clear nError */ #endif /*clear the flags which indicate tests ongoing*/ SL_FLAG_CLEAR(SRAM_RADECODE_DIAGNOSTICS); break; #endif
Ok so at this point, I faced the fact that I must have parameterized something in the wrong way, classic. Let's go to the doc. The SafeTI Diaglib documentation does not provide anything specific concerning the VIM_SOFTWARE_TEST. Only that you need to use SL_SelfTest_VIM. M'okay..
But, the Safety Manual underlines the fact that a special boot up sequence might be done to work in a perfect context. So I checked the Standard Initialization Sequence for Hercules Microcontrollers. Of course, I realized that my startup code (in sys_startup.c) was not providing all the required points there.
By checking my Halcogen (and, as I was there, comparing it with the halcogen project from the example provided with the diaglib), I realized that a lot of things where missing (all the CPU selftest at the boot time (So CCM check, STC check, etc etc..., but also the mapping between ESM interruption -low interrupt- which is then managed by the VIM).
Ok, now my global conf should be ok. Based on what there were in the example (which, actually do not even work on my launchpad).
After bringing all of this, I have a wonderful startup code which blocks. It blocks while waiting for CPU selftest there (when checking CCMSR reg). And by the, Code Composer Studio let me confirm that CCMKEYR is well written as 0x06u, so it is done as a Supervisor mode:
/* Run a diagnostic check on the CCM-R4F module */ /* This step ensures that the CCM-R4F can actually indicate an error */ /* Configure CCM in self-test mode */ CCMKEYR = 0x6U; /* Wait for CCM self-test to complete */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */ while ((CCMSR & 0x100U) != 0x100U) { }/* Wait */
So... What should I do now ? In sum:
* The launchpad does not start if I enable all the self test, or let say at least the CPU self test, at boot time.
* The VIM_SOFTWARE_TEST always return as failing because the RADECODE ram test does not seems to trigg the callback changing the good value
What am I missing ???
Thanks a lot for helping me !