map/das-dn/third_party/AdsLib/RTimeAccess.cpp
2024-12-09 09:41:04 +08:00

122 lines
4.2 KiB
C++

// SPDX-License-Identifier: MIT
/**
Copyright (c) 2021 - 2022 Beckhoff Automation GmbH & Co. KG
*/
#include "RTimeAccess.h"
#include "AdsLib.h"
#include "Log.h"
#include <iostream>
#include <limits>
namespace Beckhoff
{
namespace Ads
{
static std::ostream& operator<<(std::ostream& os, const RTimeCpuLatency& info)
{
return os << std::dec << info.current << " " << info.maximum << " " << info.limit;
}
std::ostream& operator<<(std::ostream& os, const RTimeCpuSettings& info)
{
return os << std::dec <<
"nWinCPUs: " << info.nWinCPUs << '\n' <<
"nNonWinCPUs: " << info.nNonWinCPUs << '\n' <<
"dwAffinityMask: 0x" << std::hex << info.affinityMask << '\n' <<
"nRtCpus: " << std::dec << info.nRtCpus << '\n' <<
"nCpuType: 0x" << std::hex << info.nCpuType << '\n' <<
"nCpuFamily: 0x" << info.nCpuFamily << '\n' <<
"nCpuFreq: " << std::dec << info.nCpuFreq << '\n'
;
}
RTimeAccess::RTimeAccess(const std::string& gw, const AmsNetId netid, const uint16_t port)
: device(gw, netid, port ? port : 200)
{}
RTimeCpuSettings RTimeAccess::ReadCpuSettings() const
{
struct RTimeCpuSettings settings;
uint32_t bytesRead;
const auto status = device.ReadReqEx2(ADSSRVID_READDEVICEINFO,
RTIME_CPU_SETTINGS,
sizeof(settings),
&settings,
&bytesRead);
if (ADSERR_NOERR != status) {
LOG_ERROR(__FUNCTION__ << "(): failed with: 0x" << std::hex << status << '\n');
throw AdsException(status);
}
return settings;
}
long RTimeAccess::SetSharedCores(const uint32_t sharedCores) const
{
const auto oldSettings = ReadCpuSettings();
if (sharedCores == std::numeric_limits<uint32_t>::max()) {
// 0xffffffff means RESET -> no isolated cores, all shared.
if (0 == oldSettings.nNonWinCPUs) {
std::cout << "Requested shared core configuration already active, no change applied.\n";
return ADSERR_DEVICE_EXISTS;
}
} else {
// All other values mean limit the number of shared cores -> use remaining cores as isolated.
if (sharedCores == oldSettings.nWinCPUs) {
std::cout << "Requested shared core configuration already active, no change applied.\n";
return ADSERR_DEVICE_EXISTS;
}
}
// We have to apply changes to the current core configuration. For this we
// have to talk to a different AdsDevice, the system service. Now, it is handy
// that ADS doesn't really implement "connections" so we can just use the AMS
// port of our RTimeAccess object, but adust the target AmsPort.
const AmsAddr systemService { device.m_Addr.netId, 10000 };
return AdsSyncWriteReqEx(device.GetLocalPort(),
&systemService,
SYSTEMSERVICE_SETNUMPROC,
0,
sizeof(sharedCores),
&sharedCores);
}
long RTimeAccess::ShowLatency(const uint32_t indexOffset, const uint32_t cpuId) const
{
struct RTimeCpuLatency info;
uint32_t bytesRead;
const auto status = device.ReadWriteReqEx2(
ADSSRVID_READDEVICEINFO,
indexOffset,
sizeof(info), &info,
sizeof(cpuId), &cpuId,
&bytesRead
);
if (ADSERR_NOERR != status) {
LOG_ERROR(__FUNCTION__ << "(" << std::dec << cpuId << "): failed with: 0x" << std::hex << status << '\n');
return status;
}
std::cout << std::dec << cpuId << ": " << info << '\n';
return 0;
}
long RTimeAccess::ShowLatency(const uint32_t indexOffset) const
{
const auto info = ReadCpuSettings();
std::cout << "RTimeCpuSettings:\n" << info;
for (uint8_t cpuId = 0; cpuId < 8 * sizeof(info.affinityMask); ++cpuId) {
static_assert((8 * sizeof(info.affinityMask) < std::numeric_limits<decltype(cpuId)>::max()),
"cpuId is to small for affinityMask");
if (info.affinityMask & (1ULL << cpuId)) {
ShowLatency(indexOffset, cpuId);
}
}
return 0;
}
}
}