blob: 420f8065c8a12ec97530b3dcdfd091223c451a68 [file] [log] [blame]
James Kuszmaulcf324122023-01-14 14:07:17 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "hal/roborio/InterruptManager.h"
6
7#include <fmt/format.h>
8
9#include "FPGACalls.h"
10#include "HALInternal.h"
11#include "dlfcn.h"
12#include "hal/Errors.h"
13
14using namespace hal;
15
16InterruptManager& InterruptManager::GetInstance() {
17 static InterruptManager manager;
18 return manager;
19}
20
21void InterruptManager::Initialize(tSystemInterface* baseSystem) {
22 auto& manager = GetInstance();
23 manager.fpgaSession = baseSystem->getHandle();
24}
25
26NiFpga_IrqContext InterruptManager::GetContext() noexcept {
27 NiFpga_IrqContext context;
28 HAL_NiFpga_ReserveIrqContext(fpgaSession, &context);
29 return context;
30}
31
32void InterruptManager::ReleaseContext(NiFpga_IrqContext context) noexcept {
33 HAL_NiFpga_UnreserveIrqContext(fpgaSession, context);
34}
35
36uint32_t InterruptManager::WaitForInterrupt(NiFpga_IrqContext context,
37 uint32_t mask, bool ignorePrevious,
38 uint32_t timeoutMs,
39 int32_t* status) {
40 {
41 // Make sure we can safely use this
42 std::scoped_lock lock(currentMaskMutex);
43 if ((currentMask & mask) != 0) {
44 *status = PARAMETER_OUT_OF_RANGE;
45 hal::SetLastError(
46 status, fmt::format("Interrupt mask {} has bits {} already in use",
47 mask, (currentMask & mask)));
48 return 0;
49 }
50 currentMask |= mask;
51 }
52
53 if (ignorePrevious) {
54 HAL_NiFpga_AcknowledgeIrqs(fpgaSession, mask);
55 }
56
57 uint32_t irqsAsserted = 0;
58 NiFpga_Bool timedOut = 0;
59 *status = HAL_NiFpga_WaitOnIrqs(fpgaSession, context, mask, timeoutMs,
60 &irqsAsserted, &timedOut);
61
62 if (!timedOut) {
63 HAL_NiFpga_AcknowledgeIrqs(fpgaSession, irqsAsserted);
64 }
65
66 {
67 std::scoped_lock lock(currentMaskMutex);
68 currentMask &= ~mask;
69 }
70
71 return irqsAsserted;
72}