diff --git a/hal/src/main/native/athena/Accelerometer.cpp b/hal/src/main/native/athena/Accelerometer.cpp index f0917f4601..14404613de 100644 --- a/hal/src/main/native/athena/Accelerometer.cpp +++ b/hal/src/main/native/athena/Accelerometer.cpp @@ -15,6 +15,7 @@ #include "HAL/ChipObject.h" #include "HAL/HAL.h" +#include "HALInitializer.h" using namespace hal; @@ -92,6 +93,7 @@ static uint8_t readRegister(Register reg); * Initialize the accelerometer. */ static void initializeAccelerometer() { + hal::init::CheckInit(); int32_t status; if (!accel) { diff --git a/hal/src/main/native/athena/AnalogGyro.cpp b/hal/src/main/native/athena/AnalogGyro.cpp index cdc9b0c9d1..83937b1831 100644 --- a/hal/src/main/native/athena/AnalogGyro.cpp +++ b/hal/src/main/native/athena/AnalogGyro.cpp @@ -13,6 +13,7 @@ #include "HAL/AnalogAccumulator.h" #include "HAL/AnalogInput.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" namespace { @@ -56,6 +57,7 @@ extern "C" { HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle, int32_t* status) { + hal::init::CheckInit(); if (!HAL_IsAccumulatorChannel(analogHandle, status)) { if (*status == 0) { *status = HAL_INVALID_ACCUMULATOR_CHANNEL; diff --git a/hal/src/main/native/athena/AnalogInput.cpp b/hal/src/main/native/athena/AnalogInput.cpp index 140671a0a6..cc3700502a 100644 --- a/hal/src/main/native/athena/AnalogInput.cpp +++ b/hal/src/main/native/athena/AnalogInput.cpp @@ -14,6 +14,7 @@ #include "HAL/AnalogAccumulator.h" #include "HAL/HAL.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "PortsInternal.h" namespace hal { @@ -33,6 +34,7 @@ extern "C" { */ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); initializeAnalog(status); if (*status != 0) return HAL_kInvalidHandle; diff --git a/hal/src/main/native/athena/AnalogInternal.cpp b/hal/src/main/native/athena/AnalogInternal.cpp index 0bb97d7add..a864556cd9 100644 --- a/hal/src/main/native/athena/AnalogInternal.cpp +++ b/hal/src/main/native/athena/AnalogInternal.cpp @@ -13,6 +13,7 @@ #include "HAL/AnalogInput.h" #include "HAL/ChipObject.h" +#include "HALInitializer.h" #include "PortsInternal.h" namespace hal { @@ -44,6 +45,7 @@ void InitializeAnalogInternal() { * Initialize the analog System. */ void initializeAnalog(int32_t* status) { + hal::init::CheckInit(); if (analogSystemInitialized) return; std::lock_guard lock(analogRegisterWindowMutex); if (analogSystemInitialized) return; diff --git a/hal/src/main/native/athena/AnalogOutput.cpp b/hal/src/main/native/athena/AnalogOutput.cpp index eae0e21412..07edfdbea7 100644 --- a/hal/src/main/native/athena/AnalogOutput.cpp +++ b/hal/src/main/native/athena/AnalogOutput.cpp @@ -11,6 +11,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -45,6 +46,7 @@ extern "C" { */ HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); initializeAnalog(status); if (*status != 0) return HAL_kInvalidHandle; diff --git a/hal/src/main/native/athena/AnalogTrigger.cpp b/hal/src/main/native/athena/AnalogTrigger.cpp index bcbe68accb..58bdf0fc7b 100644 --- a/hal/src/main/native/athena/AnalogTrigger.cpp +++ b/hal/src/main/native/athena/AnalogTrigger.cpp @@ -12,6 +12,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -46,6 +47,7 @@ extern "C" { HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger( HAL_AnalogInputHandle portHandle, int32_t* index, int32_t* status) { + hal::init::CheckInit(); // ensure we are given a valid and active AnalogInput handle auto analog_port = analogInputHandles->Get(portHandle); if (analog_port == nullptr) { diff --git a/hal/src/main/native/athena/Compressor.cpp b/hal/src/main/native/athena/Compressor.cpp index c5277ef3c3..44ffdf97da 100644 --- a/hal/src/main/native/athena/Compressor.cpp +++ b/hal/src/main/native/athena/Compressor.cpp @@ -9,6 +9,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "PCMInternal.h" #include "PortsInternal.h" #include "ctre/PCM.h" @@ -24,6 +25,7 @@ void InitializeCompressor() {} extern "C" { HAL_CompressorHandle HAL_InitializeCompressor(int32_t module, int32_t* status) { + hal::init::CheckInit(); // Use status to check for invalid index initializePCM(module, status); if (*status != 0) { diff --git a/hal/src/main/native/athena/Counter.cpp b/hal/src/main/native/athena/Counter.cpp index ec2f9c4942..2bba5ae2ab 100644 --- a/hal/src/main/native/athena/Counter.cpp +++ b/hal/src/main/native/athena/Counter.cpp @@ -11,6 +11,7 @@ #include "DigitalInternal.h" #include "HAL/HAL.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -42,6 +43,7 @@ extern "C" { HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index, int32_t* status) { + hal::init::CheckInit(); auto handle = counterHandles->Allocate(); if (handle == HAL_kInvalidHandle) { // out of resources *status = NO_AVAILABLE_RESOURCES; diff --git a/hal/src/main/native/athena/DIO.cpp b/hal/src/main/native/athena/DIO.cpp index cf5fb060c7..3eeeab0b82 100644 --- a/hal/src/main/native/athena/DIO.cpp +++ b/hal/src/main/native/athena/DIO.cpp @@ -16,6 +16,7 @@ #include "HAL/cpp/fpga_clock.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -46,6 +47,7 @@ extern "C" { */ HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle, HAL_Bool input, int32_t* status) { + hal::init::CheckInit(); initializeDigital(status); if (*status != 0) return HAL_kInvalidHandle; diff --git a/hal/src/main/native/athena/DigitalInternal.cpp b/hal/src/main/native/athena/DigitalInternal.cpp index e562e29323..191c1fafe5 100644 --- a/hal/src/main/native/athena/DigitalInternal.cpp +++ b/hal/src/main/native/athena/DigitalInternal.cpp @@ -19,6 +19,7 @@ #include "HAL/HAL.h" #include "HAL/Ports.h" #include "HAL/cpp/UnsafeDIO.h" +#include "HALInitializer.h" #include "PortsInternal.h" namespace hal { @@ -70,6 +71,7 @@ int32_t ComputeDigitalMask(HAL_DigitalHandle handle, int32_t* status) { * Initialize the digital system. */ void initializeDigital(int32_t* status) { + hal::init::CheckInit(); static std::atomic_bool initialized{false}; static wpi::mutex initializeMutex; // Initial check, as if it's true initialization has finished diff --git a/hal/src/main/native/athena/Encoder.cpp b/hal/src/main/native/athena/Encoder.cpp index 240c25246d..a481208c79 100644 --- a/hal/src/main/native/athena/Encoder.cpp +++ b/hal/src/main/native/athena/Encoder.cpp @@ -13,6 +13,7 @@ #include "HAL/Counter.h" #include "HAL/Errors.h" #include "HAL/handles/LimitedClassedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -243,6 +244,7 @@ HAL_EncoderHandle HAL_InitializeEncoder( HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB, HAL_Bool reverseDirection, HAL_EncoderEncodingType encodingType, int32_t* status) { + hal::init::CheckInit(); auto encoder = std::make_shared( digitalSourceHandleA, analogTriggerTypeA, digitalSourceHandleB, analogTriggerTypeB, reverseDirection, encodingType, status); diff --git a/hal/src/main/native/athena/FPGAEncoder.cpp b/hal/src/main/native/athena/FPGAEncoder.cpp index 764728e688..97ab143fe9 100644 --- a/hal/src/main/native/athena/FPGAEncoder.cpp +++ b/hal/src/main/native/athena/FPGAEncoder.cpp @@ -11,6 +11,7 @@ #include "DigitalInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -46,6 +47,7 @@ HAL_FPGAEncoderHandle HAL_InitializeFPGAEncoder( HAL_Handle digitalSourceHandleA, HAL_AnalogTriggerType analogTriggerTypeA, HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB, HAL_Bool reverseDirection, int32_t* index, int32_t* status) { + hal::init::CheckInit(); bool routingAnalogTriggerA = false; uint8_t routingChannelA = 0; uint8_t routingModuleA = 0; diff --git a/hal/src/main/native/athena/FRCDriverStation.cpp b/hal/src/main/native/athena/FRCDriverStation.cpp index 62081e8c28..8c353ddcb4 100644 --- a/hal/src/main/native/athena/FRCDriverStation.cpp +++ b/hal/src/main/native/athena/FRCDriverStation.cpp @@ -18,6 +18,7 @@ #include #include "HAL/DriverStation.h" +#include "HALInitializer.h" static_assert(sizeof(int32_t) >= sizeof(int), "FRC_NetworkComm status variable is larger than 32 bits"); @@ -380,6 +381,7 @@ static void newDataOccur(uint32_t refNum) { * that interfaces with LabVIEW. */ void HAL_InitializeDriverStation(void) { + hal::init::CheckInit(); static std::atomic_bool initialized{false}; static wpi::mutex initializeMutex; // Initial check, as if it's true initialization has finished diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp index 558c54bca1..942282c03e 100644 --- a/hal/src/main/native/athena/HAL.cpp +++ b/hal/src/main/native/athena/HAL.cpp @@ -372,6 +372,8 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) { hal::init::InitializeHAL(); + hal::init::HAL_IsInitialized.store(true); + setlinebuf(stdin); setlinebuf(stdout); wpi::outs().SetUnbuffered(); diff --git a/hal/src/main/native/athena/HALInitializer.cpp b/hal/src/main/native/athena/HALInitializer.cpp new file mode 100644 index 0000000000..d4c4394b3a --- /dev/null +++ b/hal/src/main/native/athena/HALInitializer.cpp @@ -0,0 +1,17 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "HALInitializer.h" + +#include "HAL/HAL.h" + +namespace hal { +namespace init { +std::atomic_bool HAL_IsInitialized{false}; +void RunInitialize() { HAL_Initialize(500, 0); } +} // namespace init +} // namespace hal diff --git a/hal/src/main/native/athena/HALInitializer.h b/hal/src/main/native/athena/HALInitializer.h index 967b8c684d..dfb4c70847 100644 --- a/hal/src/main/native/athena/HALInitializer.h +++ b/hal/src/main/native/athena/HALInitializer.h @@ -7,8 +7,17 @@ #pragma once +#include + namespace hal { namespace init { +extern std::atomic_bool HAL_IsInitialized; +extern void RunInitialize(); +static inline void CheckInit() { + if (HAL_IsInitialized.load(std::memory_order_relaxed)) return; + RunInitialize(); +} + extern void InitializeAccelerometer(); extern void InitializeAnalogAccumulator(); extern void InitializeAnalogGyro(); diff --git a/hal/src/main/native/athena/I2C.cpp b/hal/src/main/native/athena/I2C.cpp index 98c57764d8..50edd57137 100644 --- a/hal/src/main/native/athena/I2C.cpp +++ b/hal/src/main/native/athena/I2C.cpp @@ -18,6 +18,7 @@ #include "DigitalInternal.h" #include "HAL/DIO.h" #include "HAL/HAL.h" +#include "HALInitializer.h" using namespace hal; @@ -46,6 +47,7 @@ extern "C" { * @param port The port to open, 0 for the on-board, 1 for the MXP. */ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) { + hal::init::CheckInit(); initializeDigital(status); if (*status != 0) return; diff --git a/hal/src/main/native/athena/Interrupts.cpp b/hal/src/main/native/athena/Interrupts.cpp index 9139dce9db..b9991e07e5 100644 --- a/hal/src/main/native/athena/Interrupts.cpp +++ b/hal/src/main/native/athena/Interrupts.cpp @@ -16,6 +16,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -93,6 +94,7 @@ extern "C" { HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher, int32_t* status) { + hal::init::CheckInit(); HAL_InterruptHandle handle = interruptHandles->Allocate(); if (handle == HAL_kInvalidHandle) { *status = NO_AVAILABLE_RESOURCES; diff --git a/hal/src/main/native/athena/Notifier.cpp b/hal/src/main/native/athena/Notifier.cpp index abe9f40ea2..5cbbf00714 100644 --- a/hal/src/main/native/athena/Notifier.cpp +++ b/hal/src/main/native/athena/Notifier.cpp @@ -18,6 +18,7 @@ #include "HAL/Errors.h" #include "HAL/HAL.h" #include "HAL/handles/UnlimitedHandleResource.h" +#include "HALInitializer.h" using namespace hal; @@ -113,6 +114,7 @@ void InitializeNotifier() { extern "C" { HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status) { + hal::init::CheckInit(); if (!notifierAtexitRegistered.test_and_set()) std::atexit(cleanupNotifierAtExit); diff --git a/hal/src/main/native/athena/OSSerialPort.cpp b/hal/src/main/native/athena/OSSerialPort.cpp index 177d7cc612..9706d86e5a 100644 --- a/hal/src/main/native/athena/OSSerialPort.cpp +++ b/hal/src/main/native/athena/OSSerialPort.cpp @@ -18,6 +18,7 @@ #include "HAL/Errors.h" #include "HAL/cpp/SerialHelper.h" +#include "HALInitializer.h" static int portHandles[4]{-1, -1, -1, -1}; static std::chrono::milliseconds portTimeouts[4]{ @@ -38,6 +39,7 @@ void InitializeOSSerialPort() { extern "C" { void HAL_InitializeOSSerialPort(HAL_SerialPort port, int32_t* status) { + hal::init::CheckInit(); std::string portName; hal::SerialHelper serialHelper; diff --git a/hal/src/main/native/athena/PCMInternal.cpp b/hal/src/main/native/athena/PCMInternal.cpp index 8468cc8bda..4a840b8ceb 100644 --- a/hal/src/main/native/athena/PCMInternal.cpp +++ b/hal/src/main/native/athena/PCMInternal.cpp @@ -9,6 +9,7 @@ #include "HAL/Errors.h" #include "HAL/Solenoid.h" +#include "HALInitializer.h" #include "PortsInternal.h" namespace hal { @@ -24,6 +25,7 @@ void InitializePCMInternal() { } // namespace init void initializePCM(int32_t module, int32_t* status) { + hal::init::CheckInit(); if (!HAL_CheckSolenoidModule(module)) { *status = RESOURCE_OUT_OF_RANGE; return; diff --git a/hal/src/main/native/athena/PDP.cpp b/hal/src/main/native/athena/PDP.cpp index 97dba0ac78..dacfb15231 100644 --- a/hal/src/main/native/athena/PDP.cpp +++ b/hal/src/main/native/athena/PDP.cpp @@ -11,6 +11,7 @@ #include "HAL/Errors.h" #include "HAL/Ports.h" +#include "HALInitializer.h" #include "PortsInternal.h" #include "ctre/PDP.h" @@ -43,6 +44,7 @@ void InitializePDP() { extern "C" { void HAL_InitializePDP(int32_t module, int32_t* status) { + hal::init::CheckInit(); if (!HAL_CheckPDPModule(module)) { *status = RESOURCE_OUT_OF_RANGE; return; diff --git a/hal/src/main/native/athena/PWM.cpp b/hal/src/main/native/athena/PWM.cpp index b8b11a9842..b1b7db3531 100644 --- a/hal/src/main/native/athena/PWM.cpp +++ b/hal/src/main/native/athena/PWM.cpp @@ -16,6 +16,7 @@ #include "DigitalInternal.h" #include "HAL/cpp/fpga_clock.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -70,6 +71,7 @@ extern "C" { HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); initializeDigital(status); if (*status != 0) return HAL_kInvalidHandle; diff --git a/hal/src/main/native/athena/Power.cpp b/hal/src/main/native/athena/Power.cpp index c5c4dd9826..dbb7da8223 100644 --- a/hal/src/main/native/athena/Power.cpp +++ b/hal/src/main/native/athena/Power.cpp @@ -10,6 +10,7 @@ #include #include "HAL/ChipObject.h" +#include "HALInitializer.h" using namespace hal; @@ -18,6 +19,7 @@ namespace hal { static std::unique_ptr power{nullptr}; static void initializePower(int32_t* status) { + hal::init::CheckInit(); if (power == nullptr) { power.reset(tPower::create(status)); } diff --git a/hal/src/main/native/athena/Relay.cpp b/hal/src/main/native/athena/Relay.cpp index 886fbcf027..2567ca2bf8 100644 --- a/hal/src/main/native/athena/Relay.cpp +++ b/hal/src/main/native/athena/Relay.cpp @@ -9,6 +9,7 @@ #include "DigitalInternal.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" using namespace hal; @@ -43,6 +44,7 @@ extern "C" { HAL_RelayHandle HAL_InitializeRelayPort(HAL_PortHandle portHandle, HAL_Bool fwd, int32_t* status) { + hal::init::CheckInit(); initializeDigital(status); if (*status != 0) return HAL_kInvalidHandle; diff --git a/hal/src/main/native/athena/SPI.cpp b/hal/src/main/native/athena/SPI.cpp index a245c41174..bdd0a1f38f 100644 --- a/hal/src/main/native/athena/SPI.cpp +++ b/hal/src/main/native/athena/SPI.cpp @@ -23,6 +23,7 @@ #include "HAL/DIO.h" #include "HAL/HAL.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" using namespace hal; @@ -105,6 +106,7 @@ static void CommonSPIPortFree(void) { * @param port The number of the port to use. 0-3 for Onboard CS0-CS3, 4 for MXP */ void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { + hal::init::CheckInit(); if (port < 0 || port >= kSpiMaxHandles) { *status = PARAMETER_OUT_OF_RANGE; return; diff --git a/hal/src/main/native/athena/SerialPort.cpp b/hal/src/main/native/athena/SerialPort.cpp index ac7b581980..742e4d1b4b 100644 --- a/hal/src/main/native/athena/SerialPort.cpp +++ b/hal/src/main/native/athena/SerialPort.cpp @@ -10,6 +10,7 @@ #include #include "HAL/cpp/SerialHelper.h" +#include "HALInitializer.h" #include "visa/visa.h" static int32_t resourceManagerHandle{0}; @@ -24,6 +25,7 @@ void InitializeSerialPort() {} extern "C" { void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status) { + hal::init::CheckInit(); std::string portName; if (resourceManagerHandle == 0) diff --git a/hal/src/main/native/athena/Solenoid.cpp b/hal/src/main/native/athena/Solenoid.cpp index 1787b769f8..e7f43692d8 100644 --- a/hal/src/main/native/athena/Solenoid.cpp +++ b/hal/src/main/native/athena/Solenoid.cpp @@ -14,6 +14,7 @@ #include "HAL/Ports.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "PCMInternal.h" #include "PortsInternal.h" #include "ctre/PCM.h" @@ -49,6 +50,7 @@ extern "C" { HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); int16_t channel = getPortHandleChannel(portHandle); int16_t module = getPortHandleModule(portHandle); if (channel == InvalidHandleIndex) { diff --git a/hal/src/main/native/sim/AnalogGyro.cpp b/hal/src/main/native/sim/AnalogGyro.cpp index d3596759ff..730123d2f8 100644 --- a/hal/src/main/native/sim/AnalogGyro.cpp +++ b/hal/src/main/native/sim/AnalogGyro.cpp @@ -14,6 +14,7 @@ #include "HAL/AnalogAccumulator.h" #include "HAL/AnalogInput.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "MockData/AnalogGyroDataInternal.h" namespace { @@ -42,6 +43,7 @@ void InitializeAnalogGyro() { extern "C" { HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle, int32_t* status) { + hal::init::CheckInit(); if (!HAL_IsAccumulatorChannel(analogHandle, status)) { if (*status == 0) { *status = HAL_INVALID_ACCUMULATOR_CHANNEL; diff --git a/hal/src/main/native/sim/AnalogInput.cpp b/hal/src/main/native/sim/AnalogInput.cpp index 391df7185d..fa4859c979 100644 --- a/hal/src/main/native/sim/AnalogInput.cpp +++ b/hal/src/main/native/sim/AnalogInput.cpp @@ -9,6 +9,7 @@ #include "AnalogInternal.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "MockData/AnalogInDataInternal.h" #include "PortsInternal.h" @@ -23,6 +24,7 @@ void InitializeAnalogInput() {} extern "C" { HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); int16_t channel = getPortHandleChannel(portHandle); if (channel == InvalidHandleIndex) { *status = PARAMETER_OUT_OF_RANGE; diff --git a/hal/src/main/native/sim/AnalogOutput.cpp b/hal/src/main/native/sim/AnalogOutput.cpp index 31ef32b913..8373e9deb2 100644 --- a/hal/src/main/native/sim/AnalogOutput.cpp +++ b/hal/src/main/native/sim/AnalogOutput.cpp @@ -10,6 +10,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "MockData/AnalogOutDataInternal.h" #include "PortsInternal.h" @@ -39,6 +40,7 @@ void InitializeAnalogOutput() { extern "C" { HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); int16_t channel = getPortHandleChannel(portHandle); if (channel == InvalidHandleIndex) { *status = PARAMETER_OUT_OF_RANGE; diff --git a/hal/src/main/native/sim/AnalogTrigger.cpp b/hal/src/main/native/sim/AnalogTrigger.cpp index 2b990e2c03..72d547560a 100644 --- a/hal/src/main/native/sim/AnalogTrigger.cpp +++ b/hal/src/main/native/sim/AnalogTrigger.cpp @@ -12,6 +12,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "MockData/AnalogInDataInternal.h" #include "MockData/AnalogTriggerDataInternal.h" #include "PortsInternal.h" @@ -63,6 +64,7 @@ extern "C" { HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger( HAL_AnalogInputHandle portHandle, int32_t* index, int32_t* status) { + hal::init::CheckInit(); // ensure we are given a valid and active AnalogInput handle auto analog_port = analogInputHandles->Get(portHandle); if (analog_port == nullptr) { diff --git a/hal/src/main/native/sim/Compressor.cpp b/hal/src/main/native/sim/Compressor.cpp index ad9b2a22ea..4358669d63 100644 --- a/hal/src/main/native/sim/Compressor.cpp +++ b/hal/src/main/native/sim/Compressor.cpp @@ -9,6 +9,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "MockData/PCMDataInternal.h" #include "PortsInternal.h" @@ -23,6 +24,7 @@ void InitializeCompressor() {} extern "C" { HAL_CompressorHandle HAL_InitializeCompressor(int32_t module, int32_t* status) { + hal::init::CheckInit(); // As compressors can have unlimited objects, just create a // handle with the module number as the index. diff --git a/hal/src/main/native/sim/Counter.cpp b/hal/src/main/native/sim/Counter.cpp index 52ec724c38..a1c4352207 100644 --- a/hal/src/main/native/sim/Counter.cpp +++ b/hal/src/main/native/sim/Counter.cpp @@ -11,6 +11,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "PortsInternal.h" namespace hal { @@ -33,6 +34,7 @@ void InitializeCounter() { extern "C" { HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index, int32_t* status) { + hal::init::CheckInit(); return 0; } void HAL_FreeCounter(HAL_CounterHandle counterHandle, int32_t* status) {} diff --git a/hal/src/main/native/sim/DIO.cpp b/hal/src/main/native/sim/DIO.cpp index 2e08b8bcc6..5543e377ec 100644 --- a/hal/src/main/native/sim/DIO.cpp +++ b/hal/src/main/native/sim/DIO.cpp @@ -12,6 +12,7 @@ #include "DigitalInternal.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "MockData/DIODataInternal.h" #include "MockData/DigitalPWMDataInternal.h" #include "PortsInternal.h" @@ -41,6 +42,7 @@ extern "C" { */ HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle, HAL_Bool input, int32_t* status) { + hal::init::CheckInit(); if (*status != 0) return HAL_kInvalidHandle; int16_t channel = getPortHandleChannel(portHandle); diff --git a/hal/src/main/native/sim/DriverStation.cpp b/hal/src/main/native/sim/DriverStation.cpp index 53e312b735..4b59cd6092 100644 --- a/hal/src/main/native/sim/DriverStation.cpp +++ b/hal/src/main/native/sim/DriverStation.cpp @@ -19,6 +19,7 @@ #include #include +#include "HALInitializer.h" #include "MockData/DriverStationDataInternal.h" #include "MockData/MockHooks.h" @@ -289,6 +290,7 @@ static int32_t newDataOccur(uint32_t refNum) { * that interfaces with LabVIEW. */ void HAL_InitializeDriverStation(void) { + hal::init::CheckInit(); static std::atomic_bool initialized{false}; static wpi::mutex initializeMutex; // Initial check, as if it's true initialization has finished diff --git a/hal/src/main/native/sim/Encoder.cpp b/hal/src/main/native/sim/Encoder.cpp index 870719afaa..64b648277d 100644 --- a/hal/src/main/native/sim/Encoder.cpp +++ b/hal/src/main/native/sim/Encoder.cpp @@ -12,6 +12,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" +#include "HALInitializer.h" #include "MockData/EncoderDataInternal.h" #include "PortsInternal.h" @@ -56,6 +57,7 @@ HAL_EncoderHandle HAL_InitializeEncoder( HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB, HAL_Bool reverseDirection, HAL_EncoderEncodingType encodingType, int32_t* status) { + hal::init::CheckInit(); HAL_Handle nativeHandle = HAL_kInvalidHandle; if (encodingType == HAL_EncoderEncodingType::HAL_Encoder_k4X) { // k4x, allocate encoder diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp index 4a87ea166b..9799cff16b 100644 --- a/hal/src/main/native/sim/HAL.cpp +++ b/hal/src/main/native/sim/HAL.cpp @@ -263,6 +263,8 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) { hal::init::InitializeHAL(); + hal::init::HAL_IsInitialized.store(true); + wpi::outs().SetUnbuffered(); if (HAL_LoadExtensions() < 0) return false; hal::RestartTiming(); diff --git a/hal/src/main/native/sim/HALInitializer.cpp b/hal/src/main/native/sim/HALInitializer.cpp new file mode 100644 index 0000000000..d4c4394b3a --- /dev/null +++ b/hal/src/main/native/sim/HALInitializer.cpp @@ -0,0 +1,17 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2018 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "HALInitializer.h" + +#include "HAL/HAL.h" + +namespace hal { +namespace init { +std::atomic_bool HAL_IsInitialized{false}; +void RunInitialize() { HAL_Initialize(500, 0); } +} // namespace init +} // namespace hal diff --git a/hal/src/main/native/sim/HALInitializer.h b/hal/src/main/native/sim/HALInitializer.h index 67093977ae..7bcddb6ea0 100644 --- a/hal/src/main/native/sim/HALInitializer.h +++ b/hal/src/main/native/sim/HALInitializer.h @@ -7,8 +7,17 @@ #pragma once +#include + namespace hal { namespace init { +extern std::atomic_bool HAL_IsInitialized; +extern void RunInitialize(); +static inline void CheckInit() { + if (HAL_IsInitialized.load(std::memory_order_relaxed)) return; + RunInitialize(); +} + extern void InitializeAccelerometerData(); extern void InitializeAnalogGyroData(); extern void InitializeAnalogInData(); diff --git a/hal/src/main/native/sim/I2C.cpp b/hal/src/main/native/sim/I2C.cpp index 7108ed136c..dc2155246a 100644 --- a/hal/src/main/native/sim/I2C.cpp +++ b/hal/src/main/native/sim/I2C.cpp @@ -7,6 +7,7 @@ #include "HAL/I2C.h" +#include "HALInitializer.h" #include "MockData/I2CDataInternal.h" using namespace hal; @@ -19,6 +20,7 @@ void InitializeI2C() {} extern "C" { void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) { + hal::init::CheckInit(); SimI2CData[port].SetInitialized(true); } int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress, diff --git a/hal/src/main/native/sim/Interrupts.cpp b/hal/src/main/native/sim/Interrupts.cpp index 1336104e0f..c4ee964108 100644 --- a/hal/src/main/native/sim/Interrupts.cpp +++ b/hal/src/main/native/sim/Interrupts.cpp @@ -19,6 +19,7 @@ #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/LimitedHandleResource.h" #include "HAL/handles/UnlimitedHandleResource.h" +#include "HALInitializer.h" #include "MockData/AnalogInDataInternal.h" #include "MockData/DIODataInternal.h" #include "MockData/HAL_Value.h" @@ -85,6 +86,7 @@ void InitializeInterrupts() { extern "C" { HAL_InterruptHandle HAL_InitializeInterrupts(HAL_Bool watcher, int32_t* status) { + hal::init::CheckInit(); HAL_InterruptHandle handle = interruptHandles->Allocate(); if (handle == HAL_kInvalidHandle) { *status = NO_AVAILABLE_RESOURCES; diff --git a/hal/src/main/native/sim/Notifier.cpp b/hal/src/main/native/sim/Notifier.cpp index 622c00bde2..d5bfc644d2 100644 --- a/hal/src/main/native/sim/Notifier.cpp +++ b/hal/src/main/native/sim/Notifier.cpp @@ -16,6 +16,7 @@ #include "HAL/HAL.h" #include "HAL/cpp/fpga_clock.h" #include "HAL/handles/UnlimitedHandleResource.h" +#include "HALInitializer.h" namespace { struct Notifier { @@ -60,6 +61,7 @@ void InitializeNotifier() { extern "C" { HAL_NotifierHandle HAL_InitializeNotifier(int32_t* status) { + hal::init::CheckInit(); std::shared_ptr notifier = std::make_shared(); HAL_NotifierHandle handle = notifierHandles->Allocate(notifier); if (handle == HAL_kInvalidHandle) { diff --git a/hal/src/main/native/sim/OSSerialPort.cpp b/hal/src/main/native/sim/OSSerialPort.cpp index b5060ffc6f..32232ff235 100644 --- a/hal/src/main/native/sim/OSSerialPort.cpp +++ b/hal/src/main/native/sim/OSSerialPort.cpp @@ -6,6 +6,7 @@ /*----------------------------------------------------------------------------*/ #include "HAL/SerialPort.h" +#include "HALInitializer.h" namespace hal { namespace init { @@ -14,7 +15,9 @@ void InitializeOSSerialPort() {} } // namespace hal extern "C" { -void HAL_InitializeOSSerialPort(HAL_SerialPort port, int32_t* status) {} +void HAL_InitializeOSSerialPort(HAL_SerialPort port, int32_t* status) { + hal::init::CheckInit(); +} void HAL_SetOSSerialBaudRate(HAL_SerialPort port, int32_t baud, int32_t* status) {} void HAL_SetOSSerialDataBits(HAL_SerialPort port, int32_t bits, diff --git a/hal/src/main/native/sim/PDP.cpp b/hal/src/main/native/sim/PDP.cpp index 3b4b098ef5..88c7f68226 100644 --- a/hal/src/main/native/sim/PDP.cpp +++ b/hal/src/main/native/sim/PDP.cpp @@ -7,6 +7,7 @@ #include "HAL/PDP.h" +#include "HALInitializer.h" #include "MockData/PDPDataInternal.h" #include "PortsInternal.h" @@ -20,6 +21,7 @@ void InitializePDP() {} extern "C" { void HAL_InitializePDP(int32_t module, int32_t* status) { + hal::init::CheckInit(); SimPDPData[module].SetInitialized(true); } HAL_Bool HAL_CheckPDPModule(int32_t module) { diff --git a/hal/src/main/native/sim/PWM.cpp b/hal/src/main/native/sim/PWM.cpp index a806189b02..1fc2aa4b56 100644 --- a/hal/src/main/native/sim/PWM.cpp +++ b/hal/src/main/native/sim/PWM.cpp @@ -10,6 +10,7 @@ #include "ConstantsInternal.h" #include "DigitalInternal.h" #include "HAL/handles/HandlesInternal.h" +#include "HALInitializer.h" #include "MockData/PWMDataInternal.h" #include "PortsInternal.h" @@ -25,6 +26,7 @@ extern "C" { HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); if (*status != 0) return HAL_kInvalidHandle; int16_t channel = getPortHandleChannel(portHandle); diff --git a/hal/src/main/native/sim/Relay.cpp b/hal/src/main/native/sim/Relay.cpp index 528579f3ef..a32c7354f2 100644 --- a/hal/src/main/native/sim/Relay.cpp +++ b/hal/src/main/native/sim/Relay.cpp @@ -8,6 +8,7 @@ #include "HAL/Relay.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "MockData/RelayDataInternal.h" #include "PortsInternal.h" @@ -37,6 +38,7 @@ void InitializeRelay() { extern "C" { HAL_RelayHandle HAL_InitializeRelayPort(HAL_PortHandle portHandle, HAL_Bool fwd, int32_t* status) { + hal::init::CheckInit(); if (*status != 0) return HAL_kInvalidHandle; int16_t channel = getPortHandleChannel(portHandle); diff --git a/hal/src/main/native/sim/SPI.cpp b/hal/src/main/native/sim/SPI.cpp index b60497dc66..a9ce17a980 100644 --- a/hal/src/main/native/sim/SPI.cpp +++ b/hal/src/main/native/sim/SPI.cpp @@ -7,6 +7,7 @@ #include "HAL/SPI.h" +#include "HALInitializer.h" #include "MockData/SPIDataInternal.h" using namespace hal; @@ -18,6 +19,7 @@ void InitializeSPI() {} } // namespace hal void HAL_InitializeSPI(HAL_SPIPort port, int32_t* status) { + hal::init::CheckInit(); SimSPIData[port].SetInitialized(true); } int32_t HAL_TransactionSPI(HAL_SPIPort port, const uint8_t* dataToSend, diff --git a/hal/src/main/native/sim/SerialPort.cpp b/hal/src/main/native/sim/SerialPort.cpp index efdc5be565..df96bc451c 100644 --- a/hal/src/main/native/sim/SerialPort.cpp +++ b/hal/src/main/native/sim/SerialPort.cpp @@ -7,6 +7,8 @@ #include "HAL/SerialPort.h" +#include "HALInitializer.h" + namespace hal { namespace init { void InitializeSerialPort() {} @@ -14,7 +16,9 @@ void InitializeSerialPort() {} } // namespace hal extern "C" { -void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status) {} +void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status) { + hal::init::CheckInit(); +} void HAL_InitializeSerialPortDirect(HAL_SerialPort port, const char* portName, int32_t* status) {} diff --git a/hal/src/main/native/sim/Solenoid.cpp b/hal/src/main/native/sim/Solenoid.cpp index c227eeae5c..9fcf535eef 100644 --- a/hal/src/main/native/sim/Solenoid.cpp +++ b/hal/src/main/native/sim/Solenoid.cpp @@ -10,6 +10,7 @@ #include "HAL/Errors.h" #include "HAL/handles/HandlesInternal.h" #include "HAL/handles/IndexedHandleResource.h" +#include "HALInitializer.h" #include "MockData/PCMDataInternal.h" #include "PortsInternal.h" @@ -41,6 +42,7 @@ void InitializeSolenoid() { extern "C" { HAL_SolenoidHandle HAL_InitializeSolenoidPort(HAL_PortHandle portHandle, int32_t* status) { + hal::init::CheckInit(); int16_t channel = getPortHandleChannel(portHandle); int16_t module = getPortHandleModule(portHandle); if (channel == InvalidHandleIndex) {