Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

separate ISR handling from IRQ processing #956

Merged
merged 2 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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