How to use Init utility

Using routines from Init utility library

The routine _PxInit_Start_Cores() in the library supporting different startup variants provides an extension of the PXROS-HR kernel routine.

To replace the default kernel routine with the one from the library means to include the Init utility library before the PXROS-HR kernel library in the build command.

_MASTER_CORE_ setting

The first modification consists of changing the _MASTER_CORE_ define to the desired core.

Code 1. Example of setting _MASTER_CORE_ = 1
/* Definition which core initializes MPU system on other cores due to
 * Safety EndInit protection that shall be handled only by ONE core!!
 */
#define _MASTER_CORE_               1

Switching to non-zero _MASTER_CORE_

To start PXROS-HR system from non-zero _MASTER_CORE_ instead of the core 0 requires activation of the _MASTER_CORE_ being in its HALT mode.

The example achieves that by calling the PxuStartMasterCore() routine from Init utility library. A part of the routine is to move the reset core to an IDLE state waiting for its re-activation from the _MASTER_CORE_ later on.

Code 2. Example of activating the core 1 (MASTER_CORE) in shared_main()
void shared_main (void)
{
    uint32_t coreId = bsp_uc_core_GetCurrentCore();
    PxError_t error;

    ...

    if (coreId == UC_RESET_CORE)
    {
        /* Checks the master core configuration, activates master core */
        error = PxuStartMasterCore(InitSpecsArray, PXROS_CORE_COUNT);
        if (error != PXERR_NOERROR)
            for (;;);
    }

    /* Start the PXROS-HR kernel instance on current core */
    error = PxInit(InitSpecsArray, PXROS_CORE_COUNT);
    if (error != PXERR_NOERROR)
        PxPanic();

    /* We should never come back to here */
    for(;;);
}

Disabling the MPU compatibility mode

The MPU compatibility is active after the reset in AURIX architecture to keep backward compatibility with legacy SW running on older TriCore architecture. However, the advice is to disable the compatibility mode to enhance safety robustness by adding another level of protection to critical registers. There are three options for disabling the compatibility mode after the reset.

  1. The user implements a routine to disable the MPU-COMPAT bit.

  2. The user calls the PxuSetCompatMode() routine from Init utility library.

  3. The user calls the PxInitializeBeforePxInit() PXROS-HR API routine while having the Init utility library part of the project. The Init utility library contains a code registering the PxuSetCompatMode() routine to run within PxInitializeBeforePxInit() function.

The application adds an explicit call of PxuSetCompatMode() routine from Init utility library disabling the MPU compatibility mode before the PxInit() on the _MASTER_CORE_.

Code 3. Disabling MPU compatibility mode by calling 'PxuSetCompatMode()' in shared_main()
void shared_main (void)
{
    uint32_t coreId = bsp_uc_core_GetCurrentCore();
    PxError_t error;

    ...

    if (coreId == _MASTER_CORE_)
    {
        /* Disables the COMPAT mode for all cores */
        PxuSetCompatMode();
    }

    /* Start the PXROS-HR kernel instance on current core */
    error = PxInit(InitSpecsArray, PXROS_CORE_COUNT);
    if (error != PXERR_NOERROR)
        PxPanic();

    /* We should never come back to here */
    for(;;);
}
Code 4. Disabling MPU compatibility mode by calling 'PxInitializeBeforePxInit()' in shared_main()
void shared_main (void)
{
    uint32_t coreId = bsp_uc_core_GetCurrentCore();
    PxError_t error;

    ...

    if (coreId == _MASTER_CORE_)
    {
        /* Calls all functions entered into the __PxInitializeTable.
         * PxuSetCompatMode() is part of this table, therefore it disables the
         * COMPAT mode for all cores */
        PxInitializeBeforePxInit();
    }

    /* Start the PXROS-HR kernel instance on current core */
    error = PxInit(InitSpecsArray, PXROS_CORE_COUNT);
    if (error != PXERR_NOERROR)
        PxPanic();

    /* we should never come back to here */
    for(;;);
}

MPU configuration with MPU compatibility OFF

In case of a disabled MPU compatibility, the MPU regions in the PXROS-HR init structure must cover all access needs (including both data and code) of the startup and application code running before PxInit() function call. The reason is that the _MASTER_CORE_ activates MPU protection for all cores even they are still in HALT mode. Once they start, they run under MPU protection from the very first instruction of the crt0 startup code.

Example configuration

One possible way of covering the startup and application code before PxInit() is to provide a lower and upper bound of the memory used by assigning CRT0_CONFIG_BEGIN and CRT0_CONFIG_END symbols that will be referenced in the MPU settings.

The number of Data Protection Regions differs on tc2xx and tc3xx. However, the kernel uses the last MPU region dynamically during the run-time. Therefore, it is possible to use it for such startup memory protection. Once PxInit() is reached, the kernel changes its value according to its needs. The following MPU configuration shows how to achieve covering of the data needed by the startup code by setting the last MPU region for inactive cores.

Code 5. Add Read permissions to system on tc3xx
/* Read permissions for the data regions used by
 * interrupts.
 */
#define _SYSTEM_DATA_READ_PERMISSIONS                           \
{                                                               \
    .dp0 = 0,                /* RO data */                      \
    .dp1 = 0,                /* CSA */                          \
    .dp2 = 0,                /* RW data */                      \
    .dp3 = 0,                /* peripherals */                  \
    .dp4 = READ_PERMITTED,   /* System stack */                 \
    .dp5 = 0,                                                   \
    .dp6 = 0,                                                   \
    .dp7 = 0,                                                   \
    .dp8 = READ_PERMITTED   /* Dynamic region for startup */    \
}
Code 6. Add Write permissions to system on tc3xx
/* Write permissions for the data regions used by
 * interrupts.
 */
#define _SYSTEM_DATA_WRITE_PERMISSIONS                          \
{                                                               \
    .dp0 = 0,                /* RO data */                      \
    .dp1 = 0,                /* CSA */                          \
    .dp2 = 0,                /* RW data */                      \
    .dp3 = 0,                /* peripherals */                  \
    .dp4 = WRITE_PERMITTED,  /* System stack */                 \
    .dp5 = 0,                                                   \
    .dp6 = 0,                                                   \
    .dp7 = 0,                                                   \
    .dp8 = WRITE_PERMITTED   /* Dynamic region for startup */   \
}
Code 7. MPU settings for system and kernel data on tc3xx
extern PxUInt_t __CRT0_CONFIG_BEGIN[];
extern PxUInt_t __CRT0_CONFIG_END[];

...

/* MPU SETTINGS FOR SYSTEM AND KERNEL DATA */
const PxDataProtectSetInit_T _cpu0_sys_and_kernel_data_protection =
{
    /* MPU Data Regions */
    .dpr[0].s = {(PxUInt_t) PxTricSystemRodataLowerBound,
                 (PxUInt_t) PxTricSystemRodataUpperBound
    },
    .dpr[1].s = {(PxUInt_t) __CSA_BEGIN_CPU0_,
                 (PxUInt_t) __CSA_END_CPU0_
    },
    .dpr[2].s = {(PxUInt_t) PxTricSystemDataLowerBound_CPU0_,
                 (PxUInt_t) PxTricSystemDataUpperBound_CPU0_
    },
    .dpr[3].s = {(PxUInt_t) PERIPHERAL_MEM_BASE,
                 (PxUInt_t) PERIPHERAL_MEM_END
    },
    .dpr[4].s = {(PxUInt_t) PXROS_SYSTEM_STACK_BEGIN_CPU0_,
                 (PxUInt_t) PXROS_SYSTEM_STACK_CPU0_
    },
    .dpr[5].s = {(PxUInt_t) 0, (PxUInt_t) 0 },
    .dpr[6].s = {(PxUInt_t) 0, (PxUInt_t) 0 },
    .dpr[7].s = {(PxUInt_t) 0, (PxUInt_t) 0 },
    .dpr[8].s = {(PxUInt_t) __CRT0_CONFIG_BEGIN,
                 (PxUInt_t) __CRT0_CONFIG_END
    },

    /* MPU Data Permissions for the system... */
    .dpmr_system.dpre.bits = _SYSTEM_DATA_READ_PERMISSIONS,
    .dpmr_system.dpwe.bits = _SYSTEM_DATA_WRITE_PERMISSIONS,
    /* ... and kernel */
    .dpmr_kernel.dpre.bits = _KERNEL_DATA_READ_PERMISSIONS,
    .dpmr_kernel.dpwe.bits = _KERNEL_DATA_WRITE_PERMISSIONS
};