Configuring CPU cores

Using the real-time node TIRS, you can read the CPU cores of a target system and configure the distribution between Windows and TwinCAT real time (core isolation). If cores are re-isolated, the target system must be restarted. However, this restart is triggered only if the desired distribution is not already active on the target system.

Requirements

Recommended procedure

1. Determine available cores (optional): When an online connection is established, ProduceXml on the TIRS node returns <AvailabeCPUs>, which specifies the number of cores on the target system. MaxCPUs corresponds exactly to this core count, because the available cores are distributed.
2. Set the configuration: Set MaxCPUs and Affinity to the desired distribution yourself (see the bitmask table below). Optionally, you can add CPUs for detailed parameters.
3. Apply: Add <SetOnTarget> and <RequestReboot> to a <Methods> block and write it using ConsumeXml.
Configuring CPU cores 1:

<MaxCPUs> and <Affinity> from a ProduceXml reflect the status of the project, not that of the target system. For a new project, there is only one core listed there (<Affinity>#x0000000000000001</Affinity>, <MaxCPUs>1</MaxCPUs>). These values must therefore be actively set to the desired number of cores. Simply writing back the XML as-is has no effect. The number of cores actually available is determined solely by <AvailabeCPUs>.

What each element does

Item

Effect

<MaxCPUs NonWindowsCPUs="N">TOTAL</MaxCPUs>

TOTAL is the total number of cores in the target system (<AvailabeCPUs>) that will be distributed. This does not refer to the number of cores used by real-time processes. N (NonWindowsCPUs) specifies how many of these are reserved exclusively for real-time processes. The highest N cores enabled via <Affinity> are isolated.

<Affinity>

Select which cores the real time system will use, and enable them. The value is a hexadecimal bit mask (see below). This is what actually activates the cores.

<CPUs><CPU id="i">…</CPU></CPUs>

Optional. Configures detailed parameters (LoadLimit, BaseTime, LatencyWarning) for each activated core.

<Methods><SetOnTarget>true</SetOnTarget></Methods>

Transfers the configuration to the target system.

<Methods><RequestReboot>true</RequestReboot></Methods>

Requests the restart required for isolation.

Important note

Complete sample: 3 shared cores and 1 isolated core (4-core system)

ITcSysManager2 sysMan2 = (ITcSysManager2)sysManager;
sysMan2.SetTargetNetId("192.168.1.100.1.1");

ITcSmTreeItem realtimeSettings = sysMan2.LookupTreeItem("TIRS");

// Optional: read the number of available cores on the target system
string current = realtimeSettings.ProduceXml()

// When online, the result contains e.g. <AvailabeCPUs>4</AvailabeCPUs>
// (the MaxCPUs/Affinity values in it are the project state and must be set explicitly)

// Set the configuration and apply it to the target system:
// MaxCPUs = 4 cores in total on the target, 1 of them isolated (NonWindowsCPUs="1")
// Affinity = activates all 4 cores (bits 0..3 = #x...0f)
string xmlApply = @"<TreeItem>
<RTimeSetDef>
<MaxCPUs NonWindowsCPUs=""1"">4</MaxCPUs>
<Affinity>#x000000000000000f</Affinity>
<Methods>
<SetOnTarget>true</SetOnTarget>
<RequestReboot>true</RequestReboot>
</Methods>
</RTimeSetDef>
</TreeItem>";

realtimeSettings.ConsumeXml(xmlApply);

After the restart, the application must resume at the appropriate point.

You can check in advance whether a SetOnTarget will actually result in a reconfiguration with a restart using <CpuConfigValidOnTarget> in the ProduceXml result. This value does not indicate whether the distribution matches exactly, but rather whether the configuration specified in the project is covered by the configuration already active on the target system. If the value is 1 (true), the configuration is already covered, and no changes or restart are necessary. If the value is 0 (false), a SetOnTarget would reconfigure and restart the target system. The RT cores set via <Affinity> are the ones that matter here, not the numbers in the fields for shared and isolated cores. This mechanism prevents a ConsumeXml from accidentally triggering an unnecessary restart.

Meaning of TargetCPUInfo in the ProduceXml result

Within <RTimeSetDef>, ProduceXml returns a <TargetCPUInfo> block. It describes the target system's CPU and the mapping between the project and the target system. The values come from the connected device and are therefore only included in the XML if the target system is online (accessible).

<TargetCPUInfo>
<RealTimeCPUs>2</RealTimeCPUs>
<CPUFamily>6</CPUFamily>
<CPUFrequency>1498</CPUFrequency>
<CPUType>86</CPUType>
<AvailabeCPUs>2</AvailabeCPUs>
<NumProcessors>1</NumProcessors>
<CpuConfigValidOnTarget>true</CpuConfigValidOnTarget>
<RTimeCapabilities>1</RTimeCapabilities>
</TargetCPUInfo>

Item

Meaning

<RealTimeCPUs>

 

The number of cores selected as RT-cores – that is, the cores checked in the RT-Core column of the core list in the real time settings (real-time, settings tab). If two cores are checked there, the XML will contain <RealTimeCPUs>2</RealTimeCPUs>. This corresponds to the number of bits set via <Affinity>. It is not the number of isolated cores – that is specified in the NonWindowsCPUs attribute of <MaxCPUs>.

<CPUFamily>

 

Processor family based on the manufacturer identifier. For virtually all modern Intel® processors (Core i3/i5/i7, Atom®, Xeon®), the value is 6.

<CPUFrequency>

Processor clock frequency in MHz.

<CPUType>

 

Processor architecture. 86 stands for x86/x64, which refers to a standard industrial PC. Target systems with a different architecture (e.g., Arm®-based devices) report a different value here.

<AvailabeCPUs>

Number of cores in the target system to be distributed – the only reliable value for the actual number of cores (see note above). The spelling without the second “l” is the actual name used in the XML.

<NumProcessors>

Number of physical processors (packages/sockets), not cores. In the sample above: a processor with two cores.

<CpuConfigValidOnTarget>

Indicates whether the project configuration is already covered by the distribution active on the target system – and thus whether a SetOnTarget operation would trigger a restart (see the section above).

<RTimeCapabilities>

A metric for the target system's real time capabilities. This value is not required for the core configuration via ConsumeXml.

<CPUType> and <CPUFamily> are essentially fixed identifiers for “x86 PC with a modern Intel® processor”, it is normal for them not to change when the core configuration is modified. The following are relevant: <AvailabeCPUs> (available cores), <RealTimeCPUs> (cores selected as RT cores), and <CpuConfigValidOnTarget> (whether a restart is required or not).

Affinity bitmask

<Affinity> is a hexadecimal bitmask. Bit i represents the core with id="i":

Cores used

Affinity

Core 0

#x0000000000000001

Core 0 to 1

#x0000000000000003

Core 0 to 2

#x0000000000000007

Core 0 to 3

#x000000000000000f

Core 0 to 5

#x000000000000003f

Core 0 to 7

#x00000000000000ff

Configuring detailed parameters for each core

ITcSmTreeItem realtimeSettings = systemManager.LookupTreeItem("TIRS");

string xml = @"<TreeItem>
<RTimeSetDef>
<MaxCPUs>3</MaxCPUs>
<Affinity>#x0000000000000007</Affinity>
<CPUs>
<CPU id=""0"">
<LoadLimit>10</LoadLimit>
<BaseTime>10000</BaseTime>
<LatencyWarning>200</LatencyWarning>
</CPU>
<CPU id=""1"">
<LoadLimit>20</LoadLimit>
<BaseTime>5000</BaseTime>
<LatencyWarning>500</LatencyWarning>
</CPU>
<CPU id=""2"">
<LoadLimit>30</LoadLimit>
<BaseTime>3333</BaseTime>
<LatencyWarning>1000</LatencyWarning>
</CPU>
</CPUs>
</RTimeSetDef>
</TreeItem>";

realtimeSettings.ConsumeXml(xml);

<Affinity>#x0000000000000007</Affinity> enables cores 0 through 2, corresponding to the three <CPU> entries. Without the <Methods> block, this remains merely a project setting. To transfer the data to the target system, add <SetOnTarget> and <RequestReboot> .

Setting the task CPU affinity

ITcSmTreeItem tasks = systemManager.LookupTreeItem("TIRT");
ITcSmTreeItem task1 = tasks.CreateChild("TaskA", 1);

task1.ConsumeXml(@"<TreeItem>
<TaskDef>
<CpuAffinity>#x0000000000000001</CpuAffinity>
</TaskDef>
</TreeItem>");

The affinity is a hexadecimal bitmask. Core 0 corresponds to #x0000000000000001 , Core 1 corresponds to #x0000000000000002 , Core 2 corresponds to #x0000000000000004, and so on.