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 Mar 19, 2024
1 parent b4eb4c6 commit 2fd377f
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 @@ -12,8 +12,7 @@
template<class mesh_t, class network_t, class radio_t>
ESBGateway<mesh_t, network_t, radio_t>::ESBGateway(radio_t& _radio, network_t& _network, mesh_t& _mesh) : radio(_radio), network(_network), mesh(_mesh)
{
interruptInProgress = 0;
interruptsEnabled = 1;
gotInterrupt = false;
}

/***************************************************************************************/
Expand Down Expand Up @@ -44,9 +43,9 @@ bool ESBGateway<mesh_t, network_t, radio_t>::begin(bool configTUN, bool meshEnab
#endif
config_TUN = configTUN;

///FIX
/// FIX

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

dataRate = data_rate;

Expand All @@ -68,7 +67,7 @@ bool ESBGateway<mesh_t, network_t, radio_t>::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;
Expand Down Expand Up @@ -143,9 +142,9 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -192,7 +191,7 @@ int ESBGateway<mesh_t, network_t, radio_t>::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;
}
Expand All @@ -207,15 +206,15 @@ int ESBGateway<mesh_t, network_t, radio_t>::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;
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 @@ -233,7 +232,7 @@ int ESBGateway<mesh_t, network_t, radio_t>::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) {
Expand Down Expand Up @@ -261,7 +260,7 @@ int ESBGateway<mesh_t, network_t, radio_t>::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 @@ -278,7 +277,7 @@ int ESBGateway<mesh_t, network_t, radio_t>::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 @@ -314,18 +313,7 @@ int ESBGateway<mesh_t, network_t, radio_t>::setIP(char* ip_addr, char* mask)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::interrupts(bool enable)
{
if (enable) {
interruptsEnabled = enable;
}
else {
while (interruptInProgress) {
usleep(100);
}
interruptsEnabled = 0;
while (interruptInProgress) {
usleep(500);
}
}
// No longer required
}

/***************************************************************************************/
Expand All @@ -335,18 +323,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -362,25 +339,21 @@ template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -416,10 +389,10 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -429,7 +402,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -458,7 +431,7 @@ struct in_addr ESBGateway<mesh_t, network_t, radio_t>::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 @@ -489,16 +462,16 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -515,22 +488,22 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -549,19 +522,19 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -570,7 +543,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -585,22 +558,22 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -637,7 +610,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -667,7 +640,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::handleTX()

if (msg->size > MAX_PAYLOAD_SIZE)
{
//printf("*****WTF OVER *****");
// printf("*****WTF OVER *****");
rxQueue.pop();
return;
}
Expand All @@ -678,7 +651,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -691,10 +664,10 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -732,7 +705,7 @@ void ESBGateway<mesh_t, network_t, radio_t>::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 @@ -245,9 +245,7 @@ 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);

Expand All @@ -263,7 +261,7 @@ 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();
Expand Down
Loading

0 comments on commit 2fd377f

Please sign in to comment.