From 76275be00b7c74aa3105299318802c2d406fa776 Mon Sep 17 00:00:00 2001 From: TMRh20 Date: Sun, 17 Mar 2024 15:33:55 -0600 Subject: [PATCH] Simplify interrupt handling - Simplify interrupt handling for RF24Gateway - Update examples to remove interrupt enable/disabling --- RF24Gateway.cpp | 137 +++++++----------- RF24Gateway.h | 8 +- examples/gwNodeInt/RF24GatewayNodeInt.cpp | 5 +- .../ncursesInt/RF24Gateway_ncursesInt.cpp | 9 +- 4 files changed, 60 insertions(+), 99 deletions(-) diff --git a/RF24Gateway.cpp b/RF24Gateway.cpp index e5992a4..c633e0d 100644 --- a/RF24Gateway.cpp +++ b/RF24Gateway.cpp @@ -12,8 +12,7 @@ template ESBGateway::ESBGateway(radio_t& _radio, network_t& _network, mesh_t& _mesh) : radio(_radio), network(_network), mesh(_mesh) { - interruptInProgress = 0; - interruptsEnabled = 1; + gotInterrupt = false; } /***************************************************************************************/ @@ -44,9 +43,9 @@ bool ESBGateway::begin(bool configTUN, bool meshEnab #endif config_TUN = configTUN; - ///FIX + /// FIX - channel = _channel; //97; + channel = _channel; // 97; dataRate = data_rate; @@ -68,7 +67,7 @@ bool ESBGateway::begin(bool configTUN, bool meshEnab 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; @@ -143,9 +142,9 @@ void ESBGateway::loadRoutingTable() } routingTableSize = count; - //for(int i=0; i::allocateTunDevice(char* dev, int fla struct ifreq ifr; int fd; - //open the device + // open the device if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { return fd; } @@ -207,7 +206,7 @@ int ESBGateway::allocateTunDevice(char* dev, int fla // 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; @@ -215,7 +214,7 @@ int ESBGateway::allocateTunDevice(char* dev, int fla //#endif } - //Make persistent + // Make persistent if (ioctl(fd, TUNSETPERSIST, 1) < 0) { #if (DEBUG_LEVEL >= 1) std::cerr << "RF24Gw: Error: enabling TUNSETPERSIST" << std::endl; @@ -233,7 +232,7 @@ int ESBGateway::allocateTunDevice(char* dev, int fla ((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) { @@ -261,7 +260,7 @@ int ESBGateway::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); @@ -278,7 +277,7 @@ int ESBGateway::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 "); @@ -314,18 +313,7 @@ int ESBGateway::setIP(char* ip_addr, char* mask) template void ESBGateway::interrupts(bool enable) { - if (enable) { - interruptsEnabled = enable; - } - else { - while (interruptInProgress) { - usleep(100); - } - interruptsEnabled = 0; - while (interruptInProgress) { - usleep(500); - } - } + // No longer required } /***************************************************************************************/ @@ -335,18 +323,7 @@ void ESBGateway::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(); @@ -362,25 +339,19 @@ template void ESBGateway::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(); } + handleRX(); handleRadioOut(); - interruptsEnabled = 1; + usleep(500); } /***************************************************************************************/ @@ -416,10 +387,10 @@ void ESBGateway::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; @@ -429,7 +400,7 @@ void ESBGateway::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(); } @@ -458,7 +429,7 @@ struct in_addr ESBGateway::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) { @@ -489,16 +460,16 @@ void ESBGateway::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; @@ -515,22 +486,22 @@ void ESBGateway::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); @@ -549,19 +520,19 @@ void ESBGateway::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) { @@ -570,7 +541,7 @@ void ESBGateway::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; @@ -585,14 +556,14 @@ void ESBGateway::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; } @@ -600,7 +571,7 @@ void ESBGateway::handleRadioOut() // std::cerr << "failed." << std::endl; } - } //End Tx + } // End Tx } /***************************************************************************************/ @@ -637,7 +608,7 @@ void ESBGateway::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 { @@ -667,7 +638,7 @@ void ESBGateway::handleTX() if (msg->size > MAX_PAYLOAD_SIZE) { - //printf("*****WTF OVER *****"); + // printf("*****WTF OVER *****"); rxQueue.pop(); return; } @@ -678,7 +649,7 @@ void ESBGateway::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 @@ -691,10 +662,10 @@ void ESBGateway::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 @@ -732,7 +703,7 @@ void ESBGateway::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"); diff --git a/RF24Gateway.h b/RF24Gateway.h index b28f681..cd477b1 100644 --- a/RF24Gateway.h +++ b/RF24Gateway.h @@ -245,9 +245,8 @@ class ESBGateway 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); @@ -263,12 +262,13 @@ class ESBGateway // 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(); void loadRoutingTable(); + }; /** diff --git a/examples/gwNodeInt/RF24GatewayNodeInt.cpp b/examples/gwNodeInt/RF24GatewayNodeInt.cpp index 1bb2a3c..0b067a5 100644 --- a/examples/gwNodeInt/RF24GatewayNodeInt.cpp +++ b/examples/gwNodeInt/RF24GatewayNodeInt.cpp @@ -49,7 +49,6 @@ int main(int argc, char** argv) // The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface // RF24Network user payloads are loaded into the user cache - gw.interrupts(0); // Disable interrupts while accessing the radio if (network.available()) { RF24NetworkHeader header; @@ -83,11 +82,9 @@ int main(int argc, char** argv) mesh.begin(); } - gw.interrupts(); // Re-enable interrupts when done accessing the radio //When using interrupts, gw.poll(); needs to be called to handle incoming data from the network interface. - //The function will perform a delayed wait of max 3ms unless otherwise specified. - gw.poll(3); + gw.poll(); } return 0; } diff --git a/examples/ncursesInt/RF24Gateway_ncursesInt.cpp b/examples/ncursesInt/RF24Gateway_ncursesInt.cpp index 166b18b..390225c 100644 --- a/examples/ncursesInt/RF24Gateway_ncursesInt.cpp +++ b/examples/ncursesInt/RF24Gateway_ncursesInt.cpp @@ -157,8 +157,6 @@ int main() while (1) { - gw.interrupts(0); //Disable interrupts before accessing the radio - if (millis() - mesh_timer > 30000 && mesh.getNodeID() > 0) { //Every 30 seconds, test mesh connectivity if (!mesh.checkConnection()) @@ -174,14 +172,12 @@ int main() } mesh_timer = millis(); } - gw.interrupts(); if (ok) { //Non-master nodes need an active connection to the mesh in order to handle data /** Read RF24Network Payloads (Do nothing with them currently) **/ /*******************************/ - gw.interrupts(0); if (network.available()) { ++networkPacketsRX; @@ -210,7 +206,6 @@ int main() } network.read(header, 0, 0); } - gw.interrupts(); //Re-enable interrupts when done accessing the radio } else { @@ -221,7 +216,7 @@ int main() * The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface * RF24Network user payloads are loaded into the user cache */ - gw.poll(10); + gw.poll(); /** Mesh address/id printout **/ /*******************************/ @@ -349,7 +344,6 @@ int main() //checking for deviations from the default configuration (1MBPS data rate) //The mesh is restarted on failure and failure count logged to failLog.txt //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically - gw.interrupts(0); if (radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS) { @@ -364,7 +358,6 @@ int main() delay(1000); radio.failureDetected = 0; } - gw.interrupts(1); } //while 1