3.2.1 DIAG_CORTEX_M0

The DIAG_CORE_M0p module is designed to verify the correct functionality of the Cortex M0 processor through a set of C function calls.

The DIAG_CORE_M0p software test API is mapped to the following safety mechanisms:

Table 3-2. 
FunctionDiagnostic MechanismUse CaseElapse Time(μs)~
DIAG_CORE_M0p_STL_Init() NONEPOST / OnDemand32.6
DIAG_CORE_M0p_STL() ARM S/W Test Library (STL)POST / OnDemand121.1
DIAG_CORE_M0p_get_STL_Last_Executed()NONEPOST / OnDemand5.0

Exception Handling

Core diagnostic related exception code added in stl_exception.c file. If System integrator is using their own exception handler, then code needs to be added in the exception handler. And exception handler must be registered in vector table.

// Macro
#define STL_MPU_CTRL      0xE000ED94
// Global Variable
int STL_exceptions;
int STL_exc_result;
int STL_exc_MPU;
uint32_t STL_IPSR_golden_value = 0;
// NMI Interrupt
if (STL_exceptions == 1)
    {
        STL_exceptions = 0;
        uint32_t control_flow_value = 0x5A7F10CE;

        /* rotate result right of 1 bit */
        STL_exc_result = (STL_exc_result << 1) | (STL_exc_result >> (32 - 1));

        /* add control flow value to result */
        STL_exc_result += control_flow_value;
// Hard Fault exception
if (STL_exceptions == 1)
    {
        STL_exceptions = 0;
        uint32_t control_flow_value = 0xE1538952;

        /* rotate result right of 1 bit */
        STL_exc_result = (STL_exc_result << 1) | (STL_exc_result >> (32 - 1));

        /* add control flow value to result */
        STL_exc_result += control_flow_value;
    }
    elseif  (STL_exc_MPU == 1)
    {
        /* disable mpu */
        uint32_t* stl_mpu_ctrl_p = (uint32_t*) STL_MPU_CTRL;
        *stl_mpu_ctrl_p = 0x0;
        STL_exc_MPU = 0;

        /* Init control flow value */
        uint32_t control_flow_value = 0x5A7816BC;

        /* rotate result right of 1 bit */
        STL_exc_result = (STL_exc_result << 1) | (STL_exc_result >> (32 - 1));

        /* add control flow value to result */
        STL_exc_result += control_flow_value;
    }

//SV Exception

if (STL_exceptions == 1)
    {
        STL_exceptions = 0;
        uint32_t control_flow_value = 0x12FCAA37;

        /* rotate result right of 1 bit */
        STL_exc_result = (STL_exc_result << 1) | (STL_exc_result >> (32 - 1));
        /* add control flow value to result */
        STL_exc_result += control_flow_value;
    }

//PendSV Exception

if (STL_exceptions == 1)
    {
            STL_exceptions = 0;
            uint32_t control_flow_value = 0x4576960A;

            /* rotate result right of 1 bit */
            STL_exc_result = (STL_exc_result << 1) | (STL_exc_result >> (32 - 1));

            /* add control flow value to result */
            STL_exc_result += control_flow_value;
    }

Configuring the Diagnostic

SAFE Systick can be configured as illustrated to supported to support all diagnostics:

Run-time Pre-requisites

NVMCTRL_Initialize();

CLOCK_Initialize();

Using the Diagnostic for DIAG_CONTEXT_OOR

#include "definitions.h"

uint8_t __attribute__((section(".persist"))) last_test;

DIAG_TEST_STATUS DIAG_CORE_CM0_Example() 
{   
    DIAG_TEST_STATUS ret_value = DIAG_TEST_NOT_EXECUTED;

    //The DIAG_CORE_M0p_STL_Init function is only called once,
    //should be outside of the main loop.  
    //Calls to DIAG_CORE_M0p_STL will run a different test 
    //each time (repeating after 21 tests).
    DIAG_CORE_M0p_STL_Init(DIAG_CONTEXT_OOR);
                      
    ret_value = DIAG_TEST_FAILED;
    
    if ( DIAG_TEST_PASSED == DIAG_CORE_M0p_STL(DIAG_CONTEXT_OOR) )
    {               
        ret_value = DIAG_TEST_PASSED;
    }

    last_test = DIAG_CORE_M0p_get_STL_Last_Executed();     // optional   
       
    return ret_value; 
}

Using the Diagnostic for DIAG_CONTEXT_OL

#include "definitions.h"

uint8_t __attribute__((section(".persist"))) last_test;

DIAG_TEST_STATUS DIAG_CORE_CM0_Example() 
{   
    DIAG_TEST_STATUS ret_value = DIAG_TEST_NOT_EXECUTED;

    DIAG_CORE_M0p_STL_Init(DIAG_CONTEXT_OL);

    /* disable IRQ  */
    __disable_irq();
                      
    ret_value = DIAG_TEST_FAILED;
    
    if ( DIAG_TEST_PASSED == DIAG_CORE_M0p_STL(DIAG_CONTEXT_OL) )
    {               
        ret_value = DIAG_TEST_PASSED;
    }

    last_test = DIAG_CORE_M0p_get_STL_Last_Executed();     // optional   
     
    /* renable IRQ interrupts */
    __enable_irq(); 
 
    return ret_value; 
}