Skip to content

Commit

Permalink
separate ISR handling from IRQ processing (#956)
Browse files Browse the repository at this point in the history
  • Loading branch information
2bndy5 authored Mar 11, 2024
1 parent 9eca153 commit 7e97360
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 39 deletions.
52 changes: 31 additions & 21 deletions examples/InterruptConfigure/InterruptConfigure.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

// We will be using the nRF24L01's IRQ pin for this example
#define IRQ_PIN 2 // this needs to be a digital input capable pin
volatile bool got_interrupt = false; // used to signal processing of interrupt
volatile bool wait_for_event = false; // used to wait for an IRQ event to trigger

#define CE_PIN 7
Expand Down Expand Up @@ -136,9 +137,11 @@ void setup() {
}

void loop() {
if (role && !wait_for_event) {
if (got_interrupt) {
assessInterruptEvent();
}

// delay(1); // wait for IRQ pin to fully RISE
if (role && !wait_for_event) {

// This device is a TX node. This if block is only triggered when
// NOT waiting for an IRQ event to happen
Expand Down Expand Up @@ -218,25 +221,22 @@ void loop() {
pl_iterator++; // proceed from step 3 to last step (stop at step 4 for readability)
}

} else if (!role) {
// This device is a RX node

if (radio.rxFifoFull()) {
// wait until RX FIFO is full then stop listening
} else if (!role && radio.rxFifoFull()) {
// This device is a RX node:
// wait until RX FIFO is full then stop listening

delay(100); // let ACK payload finish transmitting
radio.stopListening(); // also discards unused ACK payloads
printRxFifo(); // flush the RX FIFO
delay(100); // let ACK payload finish transmitting
radio.stopListening(); // also discards unused ACK payloads
printRxFifo(); // flush the RX FIFO

// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1.
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1.
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);

delay(100); // let TX node finish its role
radio.startListening(); // We're ready to start over. Begin listening.
}
delay(100); // let TX node finish its role
radio.startListening(); // We're ready to start over. Begin listening.

} // role

Expand Down Expand Up @@ -271,6 +271,7 @@ void loop() {
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
radio.flush_tx(); // make sure there is room for 3 new ACK payloads
radio.flush_rx(); // make sure there is room for 3 incoming payloads
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
Expand All @@ -281,9 +282,18 @@ void loop() {


/**
* when the IRQ pin goes active LOW, call this fuction print out why
* when the IRQ pin goes active LOW.
* Here we just tell the main loop() to call `assessInterruptEve4nt()`.
*/
void interruptHandler() {
got_interrupt = true; // forward event handling back to main loop()
}

/**
* Called when an event has been triggered.
* Here, we want to verify the expected IRQ flag has been asserted.
*/
void assessInterruptEvent() {
// print IRQ status and all masking flags' states

Serial.println(F("\tIRQ pin is actively LOW")); // show that this function was called
Expand Down Expand Up @@ -316,9 +326,9 @@ void interruptHandler() {
Serial.print(F(" 'Data Fail' event test "));
Serial.println(tx_df ? F("passed") : F("failed"));
}
got_interrupt = false; // reset this flag to prevent calling this function from loop()
wait_for_event = false; // ready to continue with loop() operations
} // interruptHandler

}

/**
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
Expand Down
28 changes: 15 additions & 13 deletions examples_linux/interruptConfigure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ using namespace std;
#define IRQ_PIN 12 // this needs to be a digital input capable pin

// this example is a sequential program. so we need to wait for the event to be handled
volatile bool wait_for_event = false; // used to signify that the event is handled
volatile bool got_interrupt = false; // used to signify that the event started

/****************** Linux ***********************/
// Radio CE Pin, CSN Pin, SPI Speed
Expand Down Expand Up @@ -245,12 +245,12 @@ void slave()
*/
void ping_n_wait()
{
got_interrupt = false;

// use the non-blocking call to write a payload and begin transmission
// the "false" argument means we are expecting an ACK packet response
radio.startFastWrite(tx_payloads[pl_iterator], tx_pl_size, false);

wait_for_event = true;
while (wait_for_event) {
while (!got_interrupt) {
/*
* IRQ pin is LOW when activated. Otherwise it is always HIGH
* Wait in this empty loop until IRQ pin is activated.
Expand All @@ -260,13 +260,6 @@ void ping_n_wait()
* default, we don't need a timeout check to prevent an infinite loop.
*/
}
}

/**
* when the IRQ pin goes active LOW, call this fuction print out why
*/
void interruptHandler()
{
// print IRQ status and all masking flags' states

cout << "\tIRQ pin is actively LOW" << endl; // show that this function was called
Expand All @@ -292,8 +285,17 @@ void interruptHandler()
else if (pl_iterator == 3)
cout << " 'Data Fail' event test " << (tx_df ? "passed" : "failed") << endl;

wait_for_event = false; // ready to continue
} // interruptHandler
got_interrupt = false;
}

/**
* when the IRQ pin goes active LOW.
* Here we just set a flag to unblock ping_n_wait()
*/
void interruptHandler()
{
got_interrupt = true; // ready to continue
}

/**
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
Expand Down
24 changes: 19 additions & 5 deletions examples_pico/interruptConfigure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

// We will be using the nRF24L01's IRQ pin for this example
volatile bool wait_for_event = false; // used to wait for an IRQ event to trigger
volatile bool got_interrupt = false; // used to signal when an IRQ event has been triggered

// instantiate an object for the nRF24L01 transceiver
RF24 radio(CE_PIN, CSN_PIN);
Expand All @@ -40,6 +41,7 @@ char ack_payloads[][ack_pl_size + 1] = {"Yak ", "Back", " ACK"};

void interruptHandler(uint gpio, uint32_t events); // prototype to handle IRQ events
void printRxFifo(); // prototype to print RX FIFO with 1 buffer
void assessInterruptEvent(); // prototype to assess IRQ flags triggered

bool setup()
{
Expand Down Expand Up @@ -121,7 +123,6 @@ bool setup()
}

// For debugging info
// printf_begin(); // needed only once for printing details
// radio.printDetails(); // (smaller) function that prints raw register values
// radio.printPrettyDetails(); // (larger) function that prints human readable data

Expand Down Expand Up @@ -231,6 +232,10 @@ void loop()

} // role

if (got_interrupt) {
assessInterruptEvent();
}

char input = getchar_timeout_us(0); // get char from buffer for user input
if (input != PICO_ERROR_TIMEOUT) {
// change the role via the serial terminal
Expand All @@ -239,7 +244,7 @@ void loop()
// Become the TX node
if (!role)
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n");
else if (role && wait_for_event) // don't interrupt on ongoing test
else if (role && wait_for_event) // don't interrupt an ongoing test
return; // exit now; start next loop()
else
printf("*** RESTARTING IRQ PIN TEST ***\n");
Expand Down Expand Up @@ -277,16 +282,24 @@ void loop()
} // loop

/**
* when the IRQ pin goes active LOW, call this fuction print out why
* when the IRQ pin goes active LOW.
* Here we just tell the main loop() to call `assessInterruptEve4nt()`.
*/
void interruptHandler(uint gpio, uint32_t events)
{

if (gpio != IRQ_PIN && !(events | GPIO_IRQ_EDGE_FALL)) {
// the gpio pin and event does not match the configuration we specified
return;
}
got_interrupt = true; // forward event handling back to main loop()
}

/**
* Called when an event has been triggered.
* Here, we want to verify the expected IRQ flag has been asserted.
*/
void assessInterruptEvent()
{
// print IRQ status and all masking flags' states
printf("\tIRQ pin is actively LOW\n"); // show that this function was called
bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
Expand Down Expand Up @@ -315,8 +328,9 @@ void interruptHandler(uint gpio, uint32_t events)
else if (pl_iterator == 4) {
printf(" 'Data Fail' event test %s\n", tx_df ? "passed" : "failed");
}
got_interrupt = false; // reset this flag to prevent calling this function from loop()
wait_for_event = false; // ready to continue with loop() operations
} // interruptHandler
}

/**
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
Expand Down

0 comments on commit 7e97360

Please sign in to comment.