Skip to content

Commit

Permalink
Simplify interrupt handling (#32)
Browse files Browse the repository at this point in the history
* Simplify interrupt handling
- Simplify interrupt handling for RF24Gateway
- Update examples to remove interrupt enable/disabling

* Modify delay
- Add a longer delay similar to the polling example to minimize CPU usage

* Only delay if no action
- Only delay if no IRQ and no radio data available

* Make delay configurable by users
- When using interrupts, still use the old waitDelay variable to set the delay in the poll() function
  • Loading branch information
TMRh20 authored and 2bndy5 committed Jun 11, 2024
1 parent be07b9f commit 9fb4e28
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 99 deletions.
139 changes: 56 additions & 83 deletions RF24Gateway.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

RF24Gateway::RF24Gateway(RF24& _radio, RF24Network& _network, RF24Mesh& _mesh) : radio(_radio), network(_network), mesh(_mesh)
{
interruptInProgress = 0;
interruptsEnabled = 1;
gotInterrupt = false;
}

/***************************************************************************************/
Expand Down Expand Up @@ -40,9 +39,9 @@ bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8
#endif
config_TUN = configTUN;

///FIX
/// FIX

channel = _channel; //97;
channel = _channel; // 97;

dataRate = data_rate;

Expand All @@ -64,7 +63,7 @@ bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8
if (!mesh_nodeID) {
mesh_nodeID = 253;
}
mesh.setNodeID(mesh_nodeID); //Try not to conflict with any low-numbered node-ids
mesh.setNodeID(mesh_nodeID); // Try not to conflict with any low-numbered node-ids
}
mesh.begin(channel, data_rate);
thisNodeAddress = mesh.mesh_address;
Expand Down Expand Up @@ -138,9 +137,9 @@ void RF24Gateway::loadRoutingTable()
}
routingTableSize = count;

//for(int i=0; i<count; i++){
// std::cout << inet_ntoa(routingStruct[i].ip) << ";" << inet_ntoa(routingStruct[i].mask) << ";" << inet_ntoa(routingStruct[i].gw) << std::endl;
//}
// for(int i=0; i<count; i++){
// std::cout << inet_ntoa(routingStruct[i].ip) << ";" << inet_ntoa(routingStruct[i].mask) << ";" << inet_ntoa(routingStruct[i].gw) << std::endl;
// }
}

/***************************************************************************************/
Expand Down Expand Up @@ -184,7 +183,7 @@ int RF24Gateway::allocateTunDevice(char* dev, int flags, uint16_t address)
struct ifreq ifr;
int fd;

//open the device
// open the device
if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
return fd;
}
Expand All @@ -199,15 +198,15 @@ int RF24Gateway::allocateTunDevice(char* dev, int flags, uint16_t address)

// Create device
if (ioctl(fd, TUNSETIFF, (void*)&ifr) < 0) {
//close(fd);
// close(fd);
//#if (DEBUG_LEVEL >= 1)
std::cerr << "RF24Gw: Error: enabling TUNSETIFF" << std::endl;
std::cerr << "RF24Gw: If changing from TAP/TUN, run 'sudo ip link delete tun_nrf24' to remove the interface" << std::endl;
return -1;
//#endif
}

//Make persistent
// Make persistent
if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
#if (DEBUG_LEVEL >= 1)
std::cerr << "RF24Gw: Error: enabling TUNSETPERSIST" << std::endl;
Expand All @@ -225,7 +224,7 @@ int RF24Gateway::allocateTunDevice(char* dev, int flags, uint16_t address)
((char*)sap.sa_data)[2] = 0x32;
((char*)sap.sa_data)[3] = 0x34;

//printf("Address 0%o first %u last %u\n",address,sap.sa_data[0],sap.sa_data[1]);
// printf("Address 0%o first %u last %u\n",address,sap.sa_data[0],sap.sa_data[1]);
memcpy((char*)&ifr.ifr_hwaddr, (char*)&sap, sizeof(struct sockaddr));

if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) {
Expand All @@ -252,7 +251,7 @@ int RF24Gateway::setIP(char* ip_addr, char* mask)
}

sin.sin_family = AF_INET;
//inet_aton(ip_addr,&sin.sin_addr.s_addr);
// inet_aton(ip_addr,&sin.sin_addr.s_addr);
inet_aton(ip_addr, &sin.sin_addr);
strncpy(ifr.ifr_name, tunName, IFNAMSIZ);

Expand All @@ -269,7 +268,7 @@ int RF24Gateway::setIP(char* ip_addr, char* mask)
#endif

if (!(ifr.IRFFLAGS & IFF_UP)) {
//fprintf(stdout, "Device is currently down..setting up.-- %u\n", ifr.IRFFLAGS);
// fprintf(stdout, "Device is currently down..setting up.-- %u\n", ifr.IRFFLAGS);
ifr.IRFFLAGS |= IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
fprintf(stderr, "ifup: failed ");
Expand Down Expand Up @@ -303,18 +302,7 @@ int RF24Gateway::setIP(char* ip_addr, char* mask)
/***************************************************************************************/
void RF24Gateway::interrupts(bool enable)
{
if (enable) {
interruptsEnabled = enable;
}
else {
while (interruptInProgress) {
usleep(100);
}
interruptsEnabled = 0;
while (interruptInProgress) {
usleep(500);
}
}
// No longer required
}

/***************************************************************************************/
Expand All @@ -323,18 +311,7 @@ void RF24Gateway::update(bool interrupts)
{

if (interrupts) {
interruptInProgress = 1;
uint32_t intTimer = millis();
while (!interruptsEnabled) {
usleep(750);
if (millis() - intTimer > 1000) { //Wait up to 1s for interrupts to be re-enabled
interruptInProgress = 0;
return;
}
}
handleRadioIn();
handleTX();
interruptInProgress = 0;
gotInterrupt = true;
}
else {
handleRadioIn();
Expand All @@ -349,25 +326,21 @@ void RF24Gateway::update(bool interrupts)
void RF24Gateway::poll(uint32_t waitDelay)
{

handleRX(waitDelay);

while (interruptInProgress) {
usleep(100);
}
interruptsEnabled = 0;
while (interruptInProgress) {
usleep(500);
if (gotInterrupt) {
gotInterrupt = false;
handleRadioIn();
handleTX();
}

//gateway.poll() is called manually when using interrupts, so if the radio RX buffer is full, or interrupts have been missed, check for it here.
if (radio.rxFifoFull()) {
else if (radio.rxFifoFull()) {
fifoCleared = true;
handleRadioIn();
interruptsEnabled = 1;
return;
handleRadioOut();
}
else {
delay(waitDelay);
}
handleRX();
handleRadioOut();
interruptsEnabled = 1;
}
/***************************************************************************************/

Expand Down Expand Up @@ -401,10 +374,10 @@ void RF24Gateway::handleRadioIn()
std::cout << "Radio: Received " << bytesRead << " bytes ... " << std::endl;
#endif
#if (DEBUG_LEVEL >= 3)
//printPayload(msg.getPayloadStr(),"radio RX");
// printPayload(msg.getPayloadStr(),"radio RX");
std::cout << "TunRead: " << std::endl;
for (size_t i = 0; i < msg.size; i++) {
//std::cout << std::hex << buffer[i];
// std::cout << std::hex << buffer[i];
printf(":%0x :", msg.message[i]);
}
std::cout << std::endl;
Expand All @@ -414,7 +387,7 @@ void RF24Gateway::handleRadioIn()
rxQueue.push(msg);
}
else {
//std::cerr << "Radio: Error reading data from radio. Read '" << bytesRead << "' Bytes." << std::endl;
// std::cerr << "Radio: Error reading data from radio. Read '" << bytesRead << "' Bytes." << std::endl;
}
network.external_queue.pop();
}
Expand Down Expand Up @@ -442,7 +415,7 @@ struct in_addr RF24Gateway::getLocalIP()

family = ifa->ifa_addr->sa_family;

//This is an IPv4 interface, get the IP
// This is an IPv4 interface, get the IP
if (family == AF_INET) {
s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s == 0) {
Expand Down Expand Up @@ -472,16 +445,16 @@ void RF24Gateway::handleRadioOut()
#endif
#if (DEBUG_LEVEL >= 3)

//PrintDebug == 1 does not have an endline.
//printPayload(msg.getPayloadStr(),"radio TX");
// PrintDebug == 1 does not have an endline.
// printPayload(msg.getPayloadStr(),"radio TX");
#endif

std::uint8_t* tmp = msgTx->message;

if (!config_TUN) { //TAP can use RF24Mesh for address assignment, but will still use ARP for address resolution
if (!config_TUN) { // TAP can use RF24Mesh for address assignment, but will still use ARP for address resolution

uint32_t RF24_STR = 0x34324652; //Identifies the mac as an RF24 mac
uint32_t ARP_BC = 0xFFFFFFFF; //Broadcast address
uint32_t RF24_STR = 0x34324652; // Identifies the mac as an RF24 mac
uint32_t ARP_BC = 0xFFFFFFFF; // Broadcast address
struct macStruct
{
uint32_t rf24_Verification;
Expand All @@ -498,22 +471,22 @@ void RF24Gateway::handleRadioOut()
ok = network.write(header, &msgTx->message, msgTx->size);
}
else if (macData.rf24_Verification == ARP_BC) {
RF24NetworkHeader header(/*to node*/ 00, EXTERNAL_DATA_TYPE); //Set to master node, will be modified by RF24Network if multi-casting
RF24NetworkHeader header(/*to node*/ 00, EXTERNAL_DATA_TYPE); // Set to master node, will be modified by RF24Network if multi-casting
if (msgTx->size <= 42) {
if (thisNodeAddress == 00) { //Master Node
if (thisNodeAddress == 00) { // Master Node

uint32_t arp_timeout = millis();

ok = network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1
ok = network.multicast(header, &msgTx->message, msgTx->size, 1); // Send to Level 1
while (millis() - arp_timeout < 5) {
network.update();
}
network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1
network.multicast(header, &msgTx->message, msgTx->size, 1); // Send to Level 1
arp_timeout = millis();
while (millis() - arp_timeout < 15) {
network.update();
}
network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1
network.multicast(header, &msgTx->message, msgTx->size, 1); // Send to Level 1
}
else {
ok = network.write(header, &msgTx->message, msgTx->size);
Expand All @@ -532,19 +505,19 @@ void RF24Gateway::handleRadioOut()
struct in_addr ipDestination;
memcpy(&ipDestination.s_addr, &tmp[16], 4);

if ((getLocalIP().s_addr & 0x00FFFFFF) == (ipDestination.s_addr & 0x00FFFFFF)) { //Is inside the RF24Mesh network
if ((getLocalIP().s_addr & 0x00FFFFFF) == (ipDestination.s_addr & 0x00FFFFFF)) { // Is inside the RF24Mesh network
if ((meshAddr = mesh.getAddress(lastOctet)) > 0) {
header.to_node = meshAddr;
sendData = true;
}
else {
if (thisNodeID > 0) { //If IP is in mesh range, address lookup fails, and this is not master,
sendData = true; //send to 00 anyway in case destination is master, or the lookup just failed
if (thisNodeID > 0) { // If IP is in mesh range, address lookup fails, and this is not master,
sendData = true; // send to 00 anyway in case destination is master, or the lookup just failed
}
//printf("Could not find matching mesh nodeID for IP ending in %d\n",lastOctet);
// printf("Could not find matching mesh nodeID for IP ending in %d\n",lastOctet);
}
}
else if (thisNodeID > 0) { //If not master, send to master for routing etc. if target not within mesh
else if (thisNodeID > 0) { // If not master, send to master for routing etc. if target not within mesh
sendData = true;
}
else if (routingTableSize > 0) {
Expand All @@ -553,7 +526,7 @@ void RF24Gateway::handleRadioOut()
network.s_addr = routingStruct[i].ip.s_addr & routingStruct[i].mask.s_addr;
struct in_addr destNet;
destNet.s_addr = ipDestination.s_addr & routingStruct[i].mask.s_addr;
//printf("network %s destNet: %s\n",inet_ntoa(network),inet_ntoa(destNet));
// printf("network %s destNet: %s\n",inet_ntoa(network),inet_ntoa(destNet));
if (destNet.s_addr == network.s_addr) {
uint8_t toNode = routingStruct[i].gw.s_addr >> 24;
int16_t netAddr = 0;
Expand All @@ -568,22 +541,22 @@ void RF24Gateway::handleRadioOut()

if (sendData) {
ok = network.write(header, msgTx->message, msgTx->size);
//std::cout << "SendData " << header.to_node << std::endl;
// std::cout << "SendData " << header.to_node << std::endl;
}
}
//delay( rf24_min(msgTx->size/48,20));
// delay( rf24_min(msgTx->size/48,20));
txQueue.pop();

//printf("Addr: 0%#x\n",macData.rf24_Addr);
//printf("Verif: 0%#x\n",macData.rf24_Verification);
// printf("Addr: 0%#x\n",macData.rf24_Addr);
// printf("Verif: 0%#x\n",macData.rf24_Verification);
if (ok) {
// std::cout << "ok." << std::endl;
}
else {
// std::cerr << "failed." << std::endl;
}

} //End Tx
} // End Tx
}

/***************************************************************************************/
Expand Down Expand Up @@ -619,7 +592,7 @@ void RF24Gateway::handleRX(uint32_t waitDelay)
msgStruct msg;
memcpy(&msg.message, &buffer, nread);
msg.size = nread;
if (txQueue.size() < 2) {
if (txQueue.size() < 10) {
txQueue.push(msg);
}
else {
Expand Down Expand Up @@ -648,7 +621,7 @@ void RF24Gateway::handleTX()

if (msg->size > MAX_PAYLOAD_SIZE)
{
//printf("*****WTF OVER *****");
// printf("*****WTF OVER *****");
rxQueue.pop();
return;
}
Expand All @@ -659,7 +632,7 @@ void RF24Gateway::handleTX()
size_t writtenBytes = write(tunFd, &msg->message, msg->size);
if (writtenBytes != msg->size)
{
//std::cerr << "Tun: Less bytes written to tun/tap device then requested." << std::endl;
// std::cerr << "Tun: Less bytes written to tun/tap device then requested." << std::endl;
#if DEBUG_LEVEL >= 1
printf("Tun: Less bytes written %d to tun/tap device then requested %d.", writtenBytes, msg->size);
#endif
Expand All @@ -672,10 +645,10 @@ void RF24Gateway::handleTX()
}

#if (DEBUG_LEVEL >= 3)
//printPayload(msg.message,"tun write");
// printPayload(msg.message,"tun write");
std::cout << "TunRead: " << std::endl;
for (size_t i = 0; i < msg->size; i++) {
//printf(":%0x :",msg->message[i]);
// printf(":%0x :",msg->message[i]);
}
std::cout << std::endl;
#endif
Expand Down Expand Up @@ -710,7 +683,7 @@ void RF24Gateway::setupSocket()
exit(1);
}
addr.sin_port = htons(32001);
//buf = "Hello UDP";
// buf = "Hello UDP";
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s == -1) {
perror("socket");
Expand Down
6 changes: 2 additions & 4 deletions RF24Gateway.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,7 @@ class RF24Gateway
void handleRadioIn();
void handleRX(uint32_t waitDelay = 0);
void handleTX();
volatile bool interruptInProgress;
volatile bool interruptsEnabled;

volatile bool gotInterrupt;
int configDevice(uint16_t address);
int allocateTunDevice(char* dev, int flags, uint16_t address);

Expand All @@ -238,7 +236,7 @@ class RF24Gateway
void printPayload(std::string buffer, std::string debugMsg = "");
void printPayload(char* buffer, int nread, std::string debugMsg = "");

int s; //Socket variable for sending UDP
int s; // Socket variable for sending UDP
void setupSocket();
struct sockaddr_in addr;
struct in_addr getLocalIP();
Expand Down
Loading

0 comments on commit 9fb4e28

Please sign in to comment.