Skip to content

Commit e35a47d

Browse files
committed
si57x_ctrl: add timeout to busy polling.
When the SI57x IC isn't on the I2C bus, I2C transactions might never conclude, leaving the si57x_ctrl core perenially busy. This situation can happen with BPM boards which aren't fitted with digitizer boards on both of its FMC slots. Since we added the get_busy() function in order to simplify the implementation of still_busy(), we also use it in write_params(), to avoid repetition. The 2 second timeout was defined by the FPGA core developer, @augustofg.
1 parent e553723 commit e35a47d

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

include/modules/si57x_ctrl.h

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ class Controller: public RegisterDecoderController {
3838
/** The device's internal crystal frequency. */
3939
double fxtal;
4040

41+
/** Update all registers and return state of busy flag. */
42+
bool get_busy();
43+
/** Loop until timeout while busy, return immediately otherwise. Updates all
44+
* registers every iteration. Returns the final state of the busy flag. */
45+
bool still_busy();
46+
4147
public:
4248
/** The startup frequency has to be provided if read_startup_regs() is going
4349
* to be called. */

modules/si57x_ctrl.cc

+28-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#include <chrono>
2+
#include <thread>
3+
14
#include "printer.h"
25
#include "util.h"
36
#include "si57x_util.h"
@@ -14,6 +17,10 @@ namespace {
1417
.device_id = SI57X_CTRL_DEVID,
1518
.abi_ver_major = 1
1619
};
20+
21+
using namespace std::chrono_literals;
22+
constexpr auto busy_loop_time = 10ms;
23+
constexpr unsigned busy_wait_attempts = 2s / busy_loop_time;
1724
}
1825

1926
Core::Core(struct pcie_bars &bars):
@@ -71,10 +78,27 @@ Controller::Controller(struct pcie_bars &bars, double fstartup):
7178
}
7279
Controller::~Controller() = default;
7380

74-
void Controller::write_params()
81+
bool Controller::get_busy()
7582
{
7683
dec.get_data();
77-
if (dec.get_general_data<int32_t>("BUSY")) {
84+
return dec.get_general_data<int32_t>("BUSY");
85+
}
86+
87+
bool Controller::still_busy()
88+
{
89+
bool busy = get_busy();
90+
for (unsigned i = 0; busy && i < busy_wait_attempts; i++) {
91+
std::this_thread::sleep_for(busy_loop_time);
92+
93+
busy = get_busy();
94+
}
95+
96+
return busy;
97+
}
98+
99+
void Controller::write_params()
100+
{
101+
if (get_busy()) {
78102
/* clear any action bits */
79103
regs.ctl = 0;
80104
throw std::runtime_error("writes not allowed while busy");
@@ -94,11 +118,7 @@ bool Controller::read_startup_regs()
94118
write_general("READ_STRP_REGS", 1);
95119
write_params();
96120

97-
do {
98-
dec.get_data();
99-
} while (dec.get_general_data<int32_t>("BUSY"));
100-
101-
if (!dec.get_general_data<int32_t>("STRP_COMPLETE"))
121+
if (still_busy() || !dec.get_general_data<int32_t>("STRP_COMPLETE"))
102122
return false;
103123
}
104124

@@ -127,11 +147,7 @@ bool Controller::apply_config()
127147
write_general("APPLY_CFG", 1);
128148
write_params();
129149

130-
do {
131-
dec.get_data();
132-
} while (dec.get_general_data<int32_t>("BUSY"));
133-
134-
if (!dec.get_general_data<int32_t>("CFG_IN_SYNC"))
150+
if (still_busy() || !dec.get_general_data<int32_t>("CFG_IN_SYNC"))
135151
return false;
136152

137153
return true;

0 commit comments

Comments
 (0)