ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
UioBackend.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#include "UioBackend.h"
5
6namespace ChimeraTK {
7
8 UioBackend::UioBackend(std::string deviceName, std::string mapFileName) : NumericAddressedBackend(mapFileName) {
9 _uioAccess = std::make_shared<UioAccess>("/dev/" + deviceName);
10 }
11
15
16 boost::shared_ptr<DeviceBackend> UioBackend::createInstance(
17 std::string address, std::map<std::string, std::string> parameters) {
18 if(address.empty()) {
19 throw ChimeraTK::logic_error("UIO: Device name not specified.");
20 }
21 return boost::shared_ptr<DeviceBackend>(new UioBackend(address, parameters["map"]));
22 }
23
25 if(_opened) {
26 if(isFunctional()) {
27 return;
28 }
29 close();
30 }
31
32 _uioAccess->open();
34 }
35
37 if(_opened) {
38 if(_interruptWaitingThread.joinable()) {
39 _stopInterruptLoop = true;
40 _interruptWaitingThread.join();
41 }
42 _asyncDomain.reset();
43 _uioAccess->close();
44 }
45
46 _opened = false;
47 }
48
49 bool UioBackend::barIndexValid(uint64_t bar) {
50 return (bar == 0);
51 }
52
53 void UioBackend::read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) {
54 assert(_opened);
56
57 _uioAccess->read(bar, address, data, sizeInBytes);
58 }
59
60 void UioBackend::write(uint64_t bar, uint64_t address, int32_t const* data, size_t sizeInBytes) {
61 assert(_opened);
63
64 _uioAccess->write(bar, address, data, sizeInBytes);
65 }
66
68 uint32_t interruptNumber, boost::shared_ptr<async::DomainImpl<std::nullptr_t>> asyncDomain) {
69 std::promise<void> subscriptionDonePromise;
70
71 if(interruptNumber != 0) {
72 setException("UIO: Backend only uses interrupt number 0");
73 subscriptionDonePromise.set_value();
74 return subscriptionDonePromise.get_future();
75 }
76 if(_interruptWaitingThread.joinable()) {
77 subscriptionDonePromise.set_value();
78 return subscriptionDonePromise.get_future();
79 }
80
81 _stopInterruptLoop = false;
82 _asyncDomain = asyncDomain;
83 auto subscriptionDoneFuture = subscriptionDonePromise.get_future();
84 _interruptWaitingThread = std::thread(&UioBackend::waitForInterruptLoop, this, std::move(subscriptionDonePromise));
85 return subscriptionDoneFuture;
86 }
87
89 std::string result = std::string("UIO backend: Device path = " + _uioAccess->getDeviceFilePath());
90 if(!isOpen()) {
91 result += " (device closed)";
92 }
93
94 return result;
95 }
96
97 void UioBackend::waitForInterruptLoop(std::promise<void> subscriptionDonePromise) {
98 try { // also the scope for the promiseFulfiller
99
100 // The NumericAddressedBackend is waiting for subscription done to be fulfilled, so it can continue with
101 // polling the initial values. It is important to clear the old interrupts before this, so we don't clear any
102 // interrupts that are triggered after the polling, but before this tread is ready to process them.
103 //
104 // We put the code into a finally so it is always executed when the promiseFulfiller goes out of scope, even if
105 // there are exceptions in between.
106 //
107 auto promiseFulfiller = cppext::finally([&]() { subscriptionDonePromise.set_value(); });
108
109 // This also enables the interrupts if they are not active.
110 _uioAccess->clearInterrupts();
111
112 // Clearing active interrupts actually is only effective after a poll (inside waitForInterrupt)
113 if(_uioAccess->waitForInterrupt(0) > 0) {
114 _uioAccess->clearInterrupts();
115 }
116 } // end of the promiseFulfiller scope
117 catch(ChimeraTK::runtime_error& e) {
118 setException(e.what());
119 return;
120 }
121
122 while(!_stopInterruptLoop) {
123 try {
124 auto numberOfInterrupts = _uioAccess->waitForInterrupt(100);
125
126 if(numberOfInterrupts > 0) {
127 _uioAccess->clearInterrupts();
128
129 if(!isFunctional()) {
130 break;
131 }
132
133#ifdef _DEBUG_UIO
134 if(numberOfInterrupts > 1) {
135 std::cout << "UioBackend: Lost " << (numberOfInterrupts - 1) << " interrupts. " << std::endl;
136 }
137 std::cout << "dispatching interrupt " << std::endl;
138#endif
139
140 _asyncDomain->distribute(nullptr);
141 }
142 }
143 catch(ChimeraTK::runtime_error& ex) {
144 setException(ex.what());
145 break;
146 }
147 }
148 }
149
150} // namespace ChimeraTK
bool isFunctional() const noexcept final
Return whether a device is working as intended, usually this means it is opened and does not have any...
void setOpenedAndClearException() noexcept
Backends should call this function at the end of a (successful) open() call.
void setException(const std::string &message) noexcept final
Set the backend into an exception state.
void checkActiveException() final
Function to be called by backends when needing to check for an active exception.
bool isOpen() override
Return whether a device has been opened or not.
std::atomic< bool > _opened
flag if backend is opened
Base class for address-based device backends (e.g.
void close() final
Deactivates all asynchronous accessors and calls closeImpl().
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
Definition UioBackend.cc:16
void write(uint64_t bar, uint64_t address, int32_t const *data, size_t sizeInBytes) override
Write function to be implemented by backends.
Definition UioBackend.cc:60
void open() override
Open the device.
Definition UioBackend.cc:24
void closeImpl() override
All backends derrived from NumericAddressedBackend must implement closeImpl() instead of close.
Definition UioBackend.cc:36
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
Read function to be implemented by backends.
Definition UioBackend.cc:53
std::future< void > activateSubscription(uint32_t interruptNumber, boost::shared_ptr< async::DomainImpl< std::nullptr_t > > asyncDomain) override
Activate/create the subscription for a given interrupt (for instance by starting the according interr...
Definition UioBackend.cc:67
UioBackend(std::string deviceName, std::string mapFileName)
Definition UioBackend.cc:8
std::string readDeviceInfo() override
Return a device information string containing hardware details like the firmware version number or th...
Definition UioBackend.cc:88
boost::shared_ptr< async::DomainImpl< std::nullptr_t > > _asyncDomain
Definition UioBackend.h:43
bool barIndexValid(uint64_t bar) override
Function to be implemented by the backends.
Definition UioBackend.cc:49
Exception thrown when a logic error has occured.
Definition Exception.h:51
Exception thrown when a runtime error has occured.
Definition Exception.h:18
const char * what() const noexcept override
Return the message describing what exactly went wrong.
Definition Exception.cpp:14