mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-01 00:04:07 +08:00
LPC11C24: select()
This commit is contained in:
parent
09203aab1d
commit
a1ea05bdea
@ -23,7 +23,7 @@ public:
|
||||
|
||||
int init(uavcan::uint32_t baudrate);
|
||||
|
||||
bool hasPendingRx() const;
|
||||
bool hasReadyRx() const;
|
||||
bool hasEmptyTx() const;
|
||||
|
||||
bool hadActivity();
|
||||
|
||||
@ -206,7 +206,7 @@ int CanDriver::init(uavcan::uint32_t baudrate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CanDriver::hasPendingRx() const
|
||||
bool CanDriver::hasReadyRx() const
|
||||
{
|
||||
CriticalSectionLocker locker;
|
||||
return rx_queue.getLength() > 0;
|
||||
@ -291,9 +291,35 @@ uavcan::int16_t CanDriver::receive(uavcan::CanFrame& out_frame, uavcan::Monotoni
|
||||
|
||||
uavcan::int16_t CanDriver::select(uavcan::CanSelectMasks& inout_masks, uavcan::MonotonicTime blocking_deadline)
|
||||
{
|
||||
(void)inout_masks;
|
||||
(void)blocking_deadline;
|
||||
return -1;
|
||||
const bool noblock = ((inout_masks.read == 1) && hasReadyRx()) ||
|
||||
((inout_masks.write == 1) && hasEmptyTx());
|
||||
|
||||
if (!noblock && (clock::getMonotonic() > blocking_deadline))
|
||||
{
|
||||
/*
|
||||
* Are you afraid of the global warming? Fear no more, the solution is right here.
|
||||
*
|
||||
* It's not cool (literally) to burn cycles in a busyloop, and we have no OS to pass control to other
|
||||
* tasks, thus solution is to halt the core until a hardware event occurs - e.g. clock timer overflow.
|
||||
* Upon such event the select() call will return, even if no requested IO operations became available.
|
||||
* It's OK to do that, libuavcan can handle such behavior.
|
||||
*
|
||||
* Note that it is not possible to precisely control the sleep time with WFE, since we can't predict when
|
||||
* the next hardware event occurs. Worst case conditions:
|
||||
* - WFE gets executed right after the clock timer interrupt;
|
||||
* - CAN bus is completely silent (no traffic);
|
||||
* - User's application has no interrupts and generates no hardware events.
|
||||
* In such scenario execution will stuck here for one period of the clock timer interrupt, even if
|
||||
* blocking_deadline will expire sooner.
|
||||
* If the user's application requires higher timing precision, an extra dummy IRQ can be added just to
|
||||
* break WFE every once in a while.
|
||||
*/
|
||||
asm volatile ("wfe");
|
||||
}
|
||||
|
||||
inout_masks.read = hasReadyRx() ? 1 : 0;
|
||||
inout_masks.write = hasEmptyTx() ? 1 : 0;
|
||||
return 0; // Return value doesn't matter as long as it is non-negative
|
||||
}
|
||||
|
||||
uavcan::int16_t CanDriver::configureFilters(const uavcan::CanFilterConfig* filter_configs,
|
||||
|
||||
@ -37,7 +37,12 @@ int main()
|
||||
board::setErrorLed(uavcan_lpc11c24::CanDriver::instance().getErrorCount() > 0 ||
|
||||
uavcan_lpc11c24::CanDriver::instance().hadActivity());
|
||||
|
||||
if (uavcan_lpc11c24::CanDriver::instance().hasPendingRx())
|
||||
uavcan::CanSelectMasks masks;
|
||||
masks.read = 1;
|
||||
masks.write = 1;
|
||||
uavcan_lpc11c24::CanDriver::instance().select(masks, ts_mono + uavcan::MonotonicDuration::fromMSec(10));
|
||||
|
||||
if (masks.read == 1)
|
||||
{
|
||||
board::setStatusLed(true);
|
||||
uavcan::CanFrame frm;
|
||||
@ -45,17 +50,23 @@ int main()
|
||||
uavcan::MonotonicTime mono;
|
||||
uavcan::CanIOFlags flags;
|
||||
ENFORCE(1 == uavcan_lpc11c24::CanDriver::instance().receive(frm, mono, utc, flags));
|
||||
asm volatile ("nop");
|
||||
|
||||
frm.id += 0x100;
|
||||
ENFORCE(1 == uavcan_lpc11c24::CanDriver::instance().send(frm, mono, 0));
|
||||
if (masks.write == 1)
|
||||
{
|
||||
frm.id += 0x100;
|
||||
ENFORCE(1 == uavcan_lpc11c24::CanDriver::instance().send(frm, mono, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
board::setStatusLed(false);
|
||||
}
|
||||
|
||||
if ((ts_mono - prev_time_pub_at).toMSec() >= 1000)
|
||||
masks.read = 0;
|
||||
masks.write = 1;
|
||||
uavcan_lpc11c24::CanDriver::instance().select(masks, ts_mono + uavcan::MonotonicDuration::fromMSec(10));
|
||||
|
||||
if ((ts_mono - prev_time_pub_at).toMSec() >= 1000 && (masks.write == 1))
|
||||
{
|
||||
prev_time_pub_at = ts_mono;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user