// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #include "hal/roborio/InterruptManager.h" #include #include "FPGACalls.h" #include "HALInternal.h" #include "dlfcn.h" #include "hal/Errors.h" using namespace hal; InterruptManager& InterruptManager::GetInstance() { static InterruptManager manager; return manager; } void InterruptManager::Initialize(tSystemInterface* baseSystem) { auto& manager = GetInstance(); manager.fpgaSession = baseSystem->getHandle(); } NiFpga_IrqContext InterruptManager::GetContext() noexcept { NiFpga_IrqContext context; HAL_NiFpga_ReserveIrqContext(fpgaSession, &context); return context; } void InterruptManager::ReleaseContext(NiFpga_IrqContext context) noexcept { HAL_NiFpga_UnreserveIrqContext(fpgaSession, context); } uint32_t InterruptManager::WaitForInterrupt(NiFpga_IrqContext context, uint32_t mask, bool ignorePrevious, uint32_t timeoutMs, int32_t* status) { { // Make sure we can safely use this std::scoped_lock lock(currentMaskMutex); if ((currentMask & mask) != 0) { *status = PARAMETER_OUT_OF_RANGE; hal::SetLastError( status, fmt::format("Interrupt mask {} has bits {} already in use", mask, (currentMask & mask))); return 0; } currentMask |= mask; } if (ignorePrevious) { HAL_NiFpga_AcknowledgeIrqs(fpgaSession, mask); } uint32_t irqsAsserted = 0; NiFpga_Bool timedOut = 0; *status = HAL_NiFpga_WaitOnIrqs(fpgaSession, context, mask, timeoutMs, &irqsAsserted, &timedOut); if (!timedOut) { HAL_NiFpga_AcknowledgeIrqs(fpgaSession, irqsAsserted); } { std::scoped_lock lock(currentMaskMutex); currentMask &= ~mask; } return irqsAsserted; }