The initial phase of the PXROS application

The function PxInit() initials the start of the PXROS-HR according to the configuration structure. The input parameter pastes the address of the structure for each core. For more details, regarding the configuration structure, see the PXROS-HR BSP Example document [3].

The safety concept of the PXROS-HR uses the master core strategy. It means the selected master core controls the Safety ENDINIT protection mechanism and executes the write access into the registers under this protection. For correct multicore initialization of the operating system, the PxInit() function should be called first by master cores, and then by other CPUs.

The master core enters to initialization sequence as a first CPU. To pass this requirement, the other CPUs should be in some known state via a CPU synchronization.

The master core sets the MPU protection regions and enables this safety mechanism in the SYSCON register in each CPUs before the initialization sequence. This protection is applied when COMPATIBILITY mode is disabled. Otherwise, the MPU does not manage the data protection in advance and each instance of kernel sets own MPU regions during the initialization.

Default multicore initialization

The PXROS-HR requires the definition of the master core (in the file pxros/config/system_cfg.h MASTER_CORE) even for non-safety application. The master CPU establishes the environment and objects before other CPUs enter to their kernel initialization.

Start cores

The default initialization supports the CPU setup where the other cores are in HALT mode while the master core enters the PxInit(). The initialization sequence internally launches the additional CPUs at the appropriated time.

The HALT state is after reset status of the cores CPU1 and CPU2. Neither CPU cannot go back into this state during the running without the connection of a debbuger tool. Therefore, the user should not launch the non-master cores directly from the application if the CPUs are under PXROS control by default.

MPU strategies

The PXROS supports the encapsulation via MPU protection. The system or task can access to appropriate data or code with valid rights defined in the configuration. The MPU is a hardware safety mechanism, and the PXROS kernel reconfigures it during each context switch. The default initialization supports two MPU protection strategy controlled by COMPAT.SP register bit field. The PXROS initialization checks the bitfield internally and selects one of the following approaches.

The first strategy, when SP bit keeps the after reset value(compatibility enabled). The SYSCON[31-1] bit field is not safety ENDINIT protected. Any core can access to its MPU control bit SYSCON.PROTEN. Each instance of the kernel sets and enables own MPU during the PxInit(). The CPUs start without MPU protection, with full access to address space.

pxros cpu0
Fig. 1. MPU disabled during start-up
Following examples refer the case::
  • tc277-pxros-bsp-example

  • tc297-pxros-bsp-example

The second strategy, compatibility mode disabled. The safety ENDINIT protection controls access into the SYSCON[31-1] bit field. The master CPU manages the registers under the safety ENDINIT protection, and only it can access the SYSCON in this case. The master CPU enables the MPU protection for all CPUs in the PxInit function. Thus, the master core must also initialize the protection registers sets for all CPUs before the enabling. Non-master CPUs start with activated MPU protection and cannot disable it during the runtime.

The PXROS performs this mechanism where non-master CPUs does not have permission to the registers under Safety ENDINIT protection.

pxros cpu0 compat
Fig. 2. MPU enabled during start-up

The kernel checks the COMPATIBILITY mode internally and enables the MPU protection. The user should be aware that in case of compatibility disabled, the startup code and data must be accessible during BSP startup. The MPU configuration must include the text and data regions necessary for the startup routines.

Code 1. CPU0 PXROS-HR initialization with COMPAT disabled, shared_main.c
		case UC_CORE_MAIN_0:
			/* Disables the COMPAT mode for all cores */
			PxuSetCompatMode();
			/* PXROS-HR initialization and start */
			error = PxInit(InitSpecsArray, UC_NB_CORES);
			if (error != PXERR_NOERROR)
				PxPanic();

			break;
Code 2. Add startup regions, system_protection_cfg.c
...
/* Data region 7: Dynamically used by the kernel */
#define DPR7_BEGIN_CORE1            (PxUInt_t)__CRT0_CONFIG_BEGIN  /* Start address of the protected region */
#define DPR7_END_CORE1              (PxUInt_t)__CRT0_CONFIG_END  /* End address of the protected region */
#define DPR7_READ_CTRL_CORE1        1   /* 0 .. region NOT readable, 1 .. region readable */
#define DPR7_WRITE_CTRL_CORE1       1   /* 0 .. region NOT writable, 1 .. region writable */
...
/* Data region 7: Dynamically used by the kernel */
#define DPR7_BEGIN_CORE2            (PxUInt_t)__CRT0_CONFIG_BEGIN  /* Start address of the protected region */
#define DPR7_END_CORE2              (PxUInt_t)__CRT0_CONFIG_END  /* End address of the protected region */
#define DPR7_READ_CTRL_CORE2        1   /* 0 .. region NOT readable, 1 .. region readable */
#define DPR7_WRITE_CTRL_CORE2       1   /* 0 .. region NOT writable, 1 .. region writable */
...
/* system code protection ranges & permissions */
const PxCodeProtectSet_T _cpu1_sys_code_protection =
{
...
	.cpr[3].s = {(PxUInt_t)__STARTUP_BEGIN,  (PxUInt_t)__STARTUP_END,},   /* Range 3 the startup code section */
    .cpmr.cpxe.bits =
    {
        .dp0 = 1,                                                         /* the CPXE 0..2 executable */
        .dp1 = 1,
        .dp2 = 1,
		.dp3 = 1
    }
};
...
/* system code protection ranges & permissions */
const PxCodeProtectSet_T _cpu2_sys_code_protection =
{
...
	.cpr[3].s = {(PxUInt_t)__STARTUP_BEGIN,  (PxUInt_t)__STARTUP_END,},   /* Range 3 the startup code section */
    .cpmr.cpxe.bits =
    {
        .dp0 = 1,                                                         /* the CPXE 0..2 executable */
        .dp1 = 1,
        .dp2 = 1,
		.dp3 = 1
    }
};
...
Following example refers the case::
  • tc297-pxros-bsp-compat-example

Multicore initialization with selected master core

The PXROS-HR configuration file (system_cfg.h) defines the MASTER_CORE. The above chapter describes the default configuration with the CPU0. However, the specific application can start from a different core. For example, the derivative TC29x in safety application shall always enter the initialization with the lockstep CPU1. The CPU0 does not support the lockstep safety measure.

In this case, the user cannot select a different CPU as the RESET core. The TCxx booting system uses the CPU0 as the RESET core and the execution start on this core even it does not include the lockstep. The user’s application is responsible for adequately starting the safety critical application according to the safety manuals.

The AURIX SafeTlib and PXROS-HR require the start from the master core with lockstep capability. Therefore the integrator must explicitly run the CPU1 and switch CPU0 into the IDLE mode.

The PXROS-HR Utilities provides a user with specific functionality helping to manage the case in the application.

State of CPUs before the PxInit()

After the reset, the CPU0 starts in RUN mode and other cores(CPU1 and CPU2) wait in the HALT mode. When an application changes the CPU mode from HALT to RUN, the CPU cannot reach the HALT mode again(only a debbuger tool can activate this mode). The application can deactivate the CPU execution via the IDLE mode, but the PXROS-HR cannot start the CPU from this mode(only from HALT). Therefore the PXROS-HR utilities include the overwrite function providing the kernel with the capability to run core from IDLE mode.

The function "_PxInit_Start_Cores" form the "libinittcx.a" overwrites the original PXROS-HR and extend the functionality. The source code of the library with ReadMe.txt file, see in the folder "utilities\src\init-utility\".

pxros cpu1
Fig. 3. CPU1 as MASTER_CORE
Code 3. MASTER_CORE define, system_cfg.h
#define MASTER_CORE 							1
Code 4. CPU1 PXROS-HR initialization, shared_main.c
...
		case UC_CORE_MAIN_0:

			/* Checks the master core configuration, run the PxInit from
			 * master core first*/
			error = PxuStartMasterCore(InitSpecsArray, UC_NB_CORES);
			if (error != PXERR_NOERROR)
				for (;;);
			/* PXROS-HR initialization and start */
			error = PxInit(InitSpecsArray, UC_NB_CORES);
			if (error != PXERR_NOERROR)
				PxPanic();

			break;

		case UC_CORE_MAIN_1:

			/* PXROS-HR initialization and start */
			error = PxInit(InitSpecsArray, UC_NB_CORES);
...
Following example refer to the case::
  • tc297-pxros-bsp-cpu1-example

Compatibility mode disabled

The master core disables the compatibility mode and initializes the MPU for the other CPUs during PxInit().

pxros cpu1 compat
Fig. 4. CPU1 as MASTER_CORE, COMPAT mode disabled
Code 5. Add startup regions, system_protection_cfg.c
...
/* Data region 7: Dynamically used by the kernel */
#define DPR7_BEGIN_CORE2            (PxUInt_t)__CRT0_CONFIG_BEGIN  /* Start address of the protected region */
#define DPR7_END_CORE2              (PxUInt_t)__CRT0_CONFIG_END  /* End address of the protected region */
#define DPR7_READ_CTRL_CORE2        1   /* 0 .. region NOT readable, 1 .. region readable */
#define DPR7_WRITE_CTRL_CORE2       1   /* 0 .. region NOT writable, 1 .. region writable */

...

/* system code protection ranges & permissions */
const PxCodeProtectSet_T _cpu2_sys_code_protection =
{

...

	.cpr[3].s = {(PxUInt_t)__STARTUP_BEGIN,  (PxUInt_t)__STARTUP_END,},   /* Range 3 the startup code section */
    .cpmr.cpxe.bits =
    {
        .dp0 = 1,                                                         /* the CPXE 0..2 executable */
        .dp1 = 1,
        .dp2 = 1,
		.dp3 = 1
    }
};
...
Following example refer to the case::
  • tc297-pxros-bsp-cpu1-compat-example