[hal, wpilib] Rewrite CAN APIs (#7798)

This commit is contained in:
Thad House
2025-02-25 19:07:01 -08:00
committed by GitHub
parent b39744b562
commit baa20fa239
107 changed files with 1447 additions and 1379 deletions

View File

@@ -15,12 +15,13 @@
using namespace frc;
CAN::CAN(int deviceId) : CAN{kTeamManufacturer, deviceId, kTeamDeviceType} {}
CAN::CAN(int busId, int deviceId)
: CAN{busId, deviceId, kTeamManufacturer, kTeamDeviceType} {}
CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
CAN::CAN(int busId, int deviceId, int deviceManufacturer, int deviceType) {
int32_t status = 0;
m_handle = HAL_InitializeCAN(
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
busId, static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
static_cast<HAL_CANDeviceType>(deviceType), &status);
FRC_CheckErrorStatus(status, "device id {} mfg {} type {}", deviceId,
deviceManufacturer, deviceType);
@@ -30,41 +31,41 @@ CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
"");
}
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
void CAN::WritePacket(int apiId, const HAL_CANMessage& message) {
int32_t status = 0;
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
FRC_CheckErrorStatus(status, "WritePacket");
}
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
void CAN::WritePacketRepeating(int apiId, const HAL_CANMessage& message,
int repeatMs) {
int32_t status = 0;
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
FRC_CheckErrorStatus(status, "WritePacketRepeating");
}
void CAN::WriteRTRFrame(int length, int apiId) {
void CAN::WriteRTRFrame(int apiId, const HAL_CANMessage& message) {
int32_t status = 0;
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
FRC_CheckErrorStatus(status, "WriteRTRFrame");
}
int CAN::WritePacketNoError(const uint8_t* data, int length, int apiId) {
int CAN::WritePacketNoError(int apiId, const HAL_CANMessage& message) {
int32_t status = 0;
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
HAL_WriteCANPacket(m_handle, apiId, &message, &status);
return status;
}
int CAN::WritePacketRepeatingNoError(const uint8_t* data, int length, int apiId,
int CAN::WritePacketRepeatingNoError(int apiId, const HAL_CANMessage& message,
int repeatMs) {
int32_t status = 0;
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
HAL_WriteCANPacketRepeating(m_handle, apiId, &message, repeatMs, &status);
return status;
}
int CAN::WriteRTRFrameNoError(int length, int apiId) {
int CAN::WriteRTRFrameNoError(int apiId, const HAL_CANMessage& message) {
int32_t status = 0;
HAL_WriteCANRTRFrame(m_handle, length, apiId, &status);
HAL_WriteCANRTRFrame(m_handle, apiId, &message, &status);
return status;
}
@@ -74,10 +75,9 @@ void CAN::StopPacketRepeating(int apiId) {
FRC_CheckErrorStatus(status, "StopPacketRepeating");
}
bool CAN::ReadPacketNew(int apiId, CANData* data) {
bool CAN::ReadPacketNew(int apiId, HAL_CANReceiveMessage* data) {
int32_t status = 0;
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
HAL_ReadCANPacketNew(m_handle, apiId, data, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
@@ -89,10 +89,9 @@ bool CAN::ReadPacketNew(int apiId, CANData* data) {
}
}
bool CAN::ReadPacketLatest(int apiId, CANData* data) {
bool CAN::ReadPacketLatest(int apiId, HAL_CANReceiveMessage* data) {
int32_t status = 0;
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
HAL_ReadCANPacketLatest(m_handle, apiId, data, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
@@ -104,10 +103,10 @@ bool CAN::ReadPacketLatest(int apiId, CANData* data) {
}
}
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs,
HAL_CANReceiveMessage* data) {
int32_t status = 0;
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
&data->timestamp, timeoutMs, &status);
HAL_ReadCANPacketTimeout(m_handle, apiId, data, timeoutMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
@@ -119,7 +118,3 @@ bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
return true;
}
}
uint64_t CAN::GetTimestampBaseTime() {
return HAL_GetCANPacketBaseTime();
}

View File

@@ -14,8 +14,8 @@
using namespace frc;
Compressor::Compressor(int module, PneumaticsModuleType moduleType)
: m_module{PneumaticsBase::GetForType(module, moduleType)},
Compressor::Compressor(int busId, int module, PneumaticsModuleType moduleType)
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
m_moduleType{moduleType} {
if (!m_module->ReserveCompressor()) {
throw FRC_MakeError(err::ResourceAlreadyAllocated, "{}", module);
@@ -27,8 +27,9 @@ Compressor::Compressor(int module, PneumaticsModuleType moduleType)
wpi::SendableRegistry::Add(this, "Compressor", module);
}
Compressor::Compressor(PneumaticsModuleType moduleType)
: Compressor{PneumaticsBase::GetDefaultForType(moduleType), moduleType} {}
Compressor::Compressor(int busId, PneumaticsModuleType moduleType)
: Compressor{busId, PneumaticsBase::GetDefaultForType(moduleType),
moduleType} {}
Compressor::~Compressor() {
if (m_module) {

View File

@@ -16,9 +16,10 @@
using namespace frc;
DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
DoubleSolenoid::DoubleSolenoid(int busId, int module,
PneumaticsModuleType moduleType,
int forwardChannel, int reverseChannel)
: m_module{PneumaticsBase::GetForType(module, moduleType)},
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
m_forwardChannel{forwardChannel},
m_reverseChannel{reverseChannel} {
if (!m_module->CheckSolenoidChannel(m_forwardChannel)) {
@@ -56,10 +57,10 @@ DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType,
m_module->GetModuleNumber(), m_forwardChannel);
}
DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType,
DoubleSolenoid::DoubleSolenoid(int busId, PneumaticsModuleType moduleType,
int forwardChannel, int reverseChannel)
: DoubleSolenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
forwardChannel, reverseChannel} {}
: DoubleSolenoid{busId, PneumaticsBase::GetDefaultForType(moduleType),
moduleType, forwardChannel, reverseChannel} {}
DoubleSolenoid::~DoubleSolenoid() {
if (m_module) {

View File

@@ -10,6 +10,7 @@
#include <string>
#include <fmt/format.h>
#include <hal/Ports.h>
#include <hal/REVPH.h>
#include <hal/UsageReporting.h>
#include <wpi/NullDeleter.h>
@@ -39,26 +40,31 @@ units::volt_t PSIToVolts(units::pounds_per_square_inch_t pressure,
}
wpi::mutex PneumaticHub::m_handleLock;
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>
PneumaticHub::m_handleMap = nullptr;
std::unique_ptr<wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>
PneumaticHub::m_handleMaps = nullptr;
// Always called under lock, so we can avoid the double lock from the magic
// static
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int module) {
if (!m_handleMap) {
m_handleMap = std::make_unique<
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>>();
std::weak_ptr<PneumaticHub::DataStore>& PneumaticHub::GetDataStore(int busId,
int module) {
int32_t numBuses = HAL_GetNumCanBuses();
FRC_AssertMessage(busId >= 0 && busId < numBuses,
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
if (!m_handleMaps) {
m_handleMaps = std::make_unique<
wpi::DenseMap<int, std::weak_ptr<PneumaticHub::DataStore>>[]>(numBuses);
}
return (*m_handleMap)[module];
return m_handleMaps[busId][module];
}
class PneumaticHub::DataStore {
public:
explicit DataStore(int module, const char* stackTrace) {
explicit DataStore(int busId, int module, const char* stackTrace) {
int32_t status = 0;
HAL_REVPHHandle handle = HAL_InitializeREVPH(module, stackTrace, &status);
HAL_REVPHHandle handle =
HAL_InitializeREVPH(busId, module, stackTrace, &status);
FRC_CheckErrorStatus(status, "Module {}", module);
m_moduleObject = PneumaticHub{handle, module};
m_moduleObject = PneumaticHub{busId, handle, module};
m_moduleObject.m_dataStore =
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
@@ -105,27 +111,28 @@ class PneumaticHub::DataStore {
uint32_t m_reservedMask{0};
bool m_compressorReserved{false};
wpi::mutex m_reservedLock;
PneumaticHub m_moduleObject{HAL_kInvalidHandle, 0};
PneumaticHub m_moduleObject{0, HAL_kInvalidHandle, 0};
std::array<units::millisecond_t, 16> m_oneShotDurMs{0_ms};
};
PneumaticHub::PneumaticHub()
: PneumaticHub{SensorUtil::GetDefaultREVPHModule()} {}
PneumaticHub::PneumaticHub(int busId)
: PneumaticHub{busId, SensorUtil::GetDefaultREVPHModule()} {}
PneumaticHub::PneumaticHub(int module) {
PneumaticHub::PneumaticHub(int busId, int module) {
std::string stackTrace = wpi::GetStackTrace(1);
std::scoped_lock lock(m_handleLock);
auto& res = GetDataStore(module);
auto& res = GetDataStore(busId, module);
m_dataStore = res.lock();
if (!m_dataStore) {
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
m_dataStore =
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
res = m_dataStore;
}
m_handle = m_dataStore->m_moduleObject.m_handle;
m_module = module;
}
PneumaticHub::PneumaticHub(HAL_REVPHHandle handle, int module)
PneumaticHub::PneumaticHub(int /* busId */, HAL_REVPHHandle handle, int module)
: m_handle{handle}, m_module{module} {}
bool PneumaticHub::GetCompressor() const {
@@ -446,13 +453,14 @@ void PneumaticHub::ReportUsage(std::string_view device, std::string_view data) {
HAL_ReportUsage(fmt::format("PH[{}]/{}", m_module, device), data);
}
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int module) {
std::shared_ptr<PneumaticsBase> PneumaticHub::GetForModule(int busId,
int module) {
std::string stackTrace = wpi::GetStackTrace(1);
std::scoped_lock lock(m_handleLock);
auto& res = GetDataStore(module);
auto& res = GetDataStore(busId, module);
std::shared_ptr<DataStore> dataStore = res.lock();
if (!dataStore) {
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
res = dataStore;
}

View File

@@ -29,11 +29,11 @@ static_assert(
HAL_REVPHCompressorConfigType::HAL_REVPHCompressorConfigType_kHybrid);
std::shared_ptr<PneumaticsBase> PneumaticsBase::GetForType(
int module, PneumaticsModuleType moduleType) {
int busId, int module, PneumaticsModuleType moduleType) {
if (moduleType == PneumaticsModuleType::CTREPCM) {
return PneumaticsControlModule::GetForModule(module);
return PneumaticsControlModule::GetForModule(busId, module);
} else if (moduleType == PneumaticsModuleType::REVPH) {
return PneumaticHub::GetForModule(module);
return PneumaticHub::GetForModule(busId, module);
}
throw FRC_MakeError(err::InvalidParameter, "{}",
static_cast<int>(moduleType));

View File

@@ -9,6 +9,7 @@
#include <fmt/format.h>
#include <hal/CTREPCM.h>
#include <hal/Ports.h>
#include <hal/UsageReporting.h>
#include <wpi/NullDeleter.h>
#include <wpi/StackTrace.h>
@@ -23,28 +24,32 @@ using namespace frc;
wpi::mutex PneumaticsControlModule::m_handleLock;
std::unique_ptr<
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>>
PneumaticsControlModule::m_handleMap = nullptr;
wpi::DenseMap<int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>
PneumaticsControlModule::m_handleMaps = nullptr;
// Always called under lock, so we can avoid the double lock from the magic
// static
std::weak_ptr<PneumaticsControlModule::DataStore>&
PneumaticsControlModule::GetDataStore(int module) {
if (!m_handleMap) {
m_handleMap = std::make_unique<wpi::DenseMap<
int, std::weak_ptr<PneumaticsControlModule::DataStore>>>();
PneumaticsControlModule::GetDataStore(int busId, int module) {
int32_t numBuses = HAL_GetNumCanBuses();
FRC_AssertMessage(busId >= 0 && busId < numBuses,
"Bus {} out of range. Must be [0-{}).", busId, numBuses);
if (!m_handleMaps) {
m_handleMaps = std::make_unique<wpi::DenseMap<
int, std::weak_ptr<PneumaticsControlModule::DataStore>>[]>(numBuses);
}
return (*m_handleMap)[module];
return m_handleMaps[busId][module];
}
class PneumaticsControlModule::DataStore {
public:
explicit DataStore(int module, const char* stackTrace) {
explicit DataStore(int busId, int module, const char* stackTrace) {
int32_t status = 0;
HAL_CTREPCMHandle handle =
HAL_InitializeCTREPCM(module, stackTrace, &status);
HAL_InitializeCTREPCM(busId, module, stackTrace, &status);
FRC_CheckErrorStatus(status, "Module {}", module);
m_moduleObject = PneumaticsControlModule{handle, module};
m_moduleObject = PneumaticsControlModule{busId, handle, module};
m_moduleObject.m_dataStore =
std::shared_ptr<DataStore>{this, wpi::NullDeleter<DataStore>()};
}
@@ -59,26 +64,28 @@ class PneumaticsControlModule::DataStore {
uint32_t m_reservedMask{0};
bool m_compressorReserved{false};
wpi::mutex m_reservedLock;
PneumaticsControlModule m_moduleObject{HAL_kInvalidHandle, 0};
PneumaticsControlModule m_moduleObject{0, HAL_kInvalidHandle, 0};
};
PneumaticsControlModule::PneumaticsControlModule()
: PneumaticsControlModule{SensorUtil::GetDefaultCTREPCMModule()} {}
PneumaticsControlModule::PneumaticsControlModule(int busId)
: PneumaticsControlModule{busId, SensorUtil::GetDefaultCTREPCMModule()} {}
PneumaticsControlModule::PneumaticsControlModule(int module) {
PneumaticsControlModule::PneumaticsControlModule(int busId, int module) {
std::string stackTrace = wpi::GetStackTrace(1);
std::scoped_lock lock(m_handleLock);
auto& res = GetDataStore(module);
auto& res = GetDataStore(busId, module);
m_dataStore = res.lock();
if (!m_dataStore) {
m_dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
m_dataStore =
std::make_shared<DataStore>(busId, module, stackTrace.c_str());
res = m_dataStore;
}
m_handle = m_dataStore->m_moduleObject.m_handle;
m_module = module;
}
PneumaticsControlModule::PneumaticsControlModule(HAL_CTREPCMHandle handle,
PneumaticsControlModule::PneumaticsControlModule(int /* busId */,
HAL_CTREPCMHandle handle,
int module)
: m_handle{handle}, m_module{module} {}
@@ -297,13 +304,13 @@ void PneumaticsControlModule::ReportUsage(std::string_view device,
}
std::shared_ptr<PneumaticsBase> PneumaticsControlModule::GetForModule(
int module) {
int busId, int module) {
std::string stackTrace = wpi::GetStackTrace(1);
std::scoped_lock lock(m_handleLock);
auto& res = GetDataStore(module);
auto& res = GetDataStore(busId, module);
std::shared_ptr<DataStore> dataStore = res.lock();
if (!dataStore) {
dataStore = std::make_shared<DataStore>(module, stackTrace.c_str());
dataStore = std::make_shared<DataStore>(busId, module, stackTrace.c_str());
res = dataStore;
}

View File

@@ -27,12 +27,12 @@ static_assert(frc::PowerDistribution::kDefaultModule ==
using namespace frc;
PowerDistribution::PowerDistribution() {
PowerDistribution::PowerDistribution(int busId) {
auto stack = wpi::GetStackTrace(1);
int32_t status = 0;
m_handle = HAL_InitializePowerDistribution(
kDefaultModule,
busId, kDefaultModule,
HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic,
stack.c_str(), &status);
FRC_CheckErrorStatus(status, "Module {}", kDefaultModule);
@@ -48,13 +48,14 @@ PowerDistribution::PowerDistribution() {
wpi::SendableRegistry::Add(this, "PowerDistribution", m_module);
}
PowerDistribution::PowerDistribution(int module, ModuleType moduleType) {
PowerDistribution::PowerDistribution(int busId, int module,
ModuleType moduleType) {
auto stack = wpi::GetStackTrace(1);
int32_t status = 0;
m_handle = HAL_InitializePowerDistribution(
module, static_cast<HAL_PowerDistributionType>(moduleType), stack.c_str(),
&status);
busId, module, static_cast<HAL_PowerDistributionType>(moduleType),
stack.c_str(), &status);
FRC_CheckErrorStatus(status, "Module {}", module);
m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status);
FRC_ReportError(status, "Module {}", module);

View File

@@ -284,15 +284,16 @@ RadioLEDState RobotController::GetRadioLEDState() {
return retVal;
}
CANStatus RobotController::GetCANStatus() {
CANStatus RobotController::GetCANStatus(int busId) {
int32_t status = 0;
float percentBusUtilization = 0;
uint32_t busOffCount = 0;
uint32_t txFullCount = 0;
uint32_t receiveErrorCount = 0;
uint32_t transmitErrorCount = 0;
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
&receiveErrorCount, &transmitErrorCount, &status);
HAL_CAN_GetCANStatus(busId, &percentBusUtilization, &busOffCount,
&txFullCount, &receiveErrorCount, &transmitErrorCount,
&status);
FRC_CheckErrorStatus(status, "GetCANStatus");
return {percentBusUtilization, static_cast<int>(busOffCount),
static_cast<int>(txFullCount), static_cast<int>(receiveErrorCount),

View File

@@ -15,8 +15,9 @@
using namespace frc;
Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
: m_module{PneumaticsBase::GetForType(module, moduleType)},
Solenoid::Solenoid(int busId, int module, PneumaticsModuleType moduleType,
int channel)
: m_module{PneumaticsBase::GetForType(busId, module, moduleType)},
m_channel{channel} {
if (!m_module->CheckSolenoidChannel(m_channel)) {
throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", m_channel);
@@ -32,8 +33,8 @@ Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel)
m_channel);
}
Solenoid::Solenoid(PneumaticsModuleType moduleType, int channel)
: Solenoid{PneumaticsBase::GetDefaultForType(moduleType), moduleType,
Solenoid::Solenoid(int busId, PneumaticsModuleType moduleType, int channel)
: Solenoid{busId, PneumaticsBase::GetDefaultForType(moduleType), moduleType,
channel} {}
Solenoid::~Solenoid() {