Skip to content

[2.0.0] Adds the setRXInterrupt #4656

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

Closed
wants to merge 46 commits into from
Closed

Conversation

timkoers
Copy link
Contributor

Should fix pull request #3376

I haven't tested the code yet myself, but feel free to review

@timkoers timkoers changed the title Adds the setRXInterrupt, which passing tests. Adds the setRXInterrupt Dec 23, 2020
@timkoers
Copy link
Contributor Author

I'll take a look at the failing tests after X-mass

@AlessandroAU
Copy link

Thanks for doing this! I've wanted this feature for awhile

@timkoers
Copy link
Contributor Author

timkoers commented Jan 8, 2021

I'm working on a rewrite, which makes it easier to manage the interrupt functions.

@me-no-dev
Copy link
Member

Please note my comments and revers all code style changes. Stick to the style in the files and change only what is necessary for this to work. I can not review this request as-is.

@timkoers
Copy link
Contributor Author

Are you able to merge it?

@ianr34
Copy link

ianr34 commented Feb 10, 2021

it looks good - and when this issue was first raised (in another post, a year or two ago) I got so frustrated I just junked the whole serial class and did my own.. Polling for input in your top program is just so not the way to go..

@me-no-dev
Copy link
Member

Coming in 2.0.0 almost everything will be event based. I'm thinking that events are probably the best solution here also. They are thread-safe and can still access the RX Queue. Events can come based on different factors (byte received, transmission done, queue full, etc.). What do you think?

@ianr34
Copy link

ianr34 commented Feb 16, 2021

Yes, Yes, and Yes. Events are the way to go (not interrupts, that was OK for a short term solution) - the one I wrote to replace the arduino-esp32 one was event based, with a queue.

We have to get everyone away from thinking about a single task with polling, it simply isn't the way to use hardware this powerful, let alone the way to use more than 1 core, and all those nice hardware bits.. And events are much nicer than interrupts in most cases.

@timkoers
Copy link
Contributor Author

Coming in 2.0.0 almost everything will be event based. I'm thinking that events are probably the best solution here also. They are thread-safe and can still access the RX Queue. Events can come based on different factors (byte received, transmission done, queue full, etc.). What do you think?

For the sake of unified code, I think that is good practice. Are you going to change it up to events?

@me-no-dev
Copy link
Member

@timkoers yes I will :) do not close this PR so it reminds me of it.

@me-no-dev me-no-dev changed the title Adds the setRXInterrupt [2.0.0] Adds the setRXInterrupt Feb 22, 2021
@me-no-dev me-no-dev added the Type: For reference Common questions & problems label Feb 22, 2021
@VojtechBartoska VojtechBartoska added this to the 2.0.0 milestone Mar 2, 2021
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@me-no-dev me-no-dev removed this from the 2.0.0 milestone Jul 19, 2021
Serial.begin(115200);
Serial2.begin(115200);

Serial2.setRxInterrupt(onSerialRX, NULL);
Copy link

@mycbtec mycbtec Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timkoers I tested the code and it is working fine. I have only one issue at this point during Setup initilization... it sometimes stop at setrxInterrupt function. When I delete Serial2.begin and Serial2.setRxInterrupt -> upload the code -> then add Serial2.begin and Serial2.setRxInterrupt -> upload the code, everything starts to work fine again... I'm trying to figure out why this is happening...

@SuGlider
Copy link
Collaborator

SerialHardware and HAL have changed to work over IDF 4.4 layer.
This PR won't fit anymore in the new refactoring effort.

Another way to solve it would be creating Serial.onReceive(callback_function)
This follows Arduino style and works as way to setRCInterrupt as well.

Example:

A potential solution is being implemented.
It's the Serial.onReceive(function)

As soon as any data arrives UART RX, function() will called.

Example:

void UART_RX_IRQ(){
  uint16_t size = Serial.available();
  Serial.printf("Got %d bytes on Serial to read\n", size);
  while(Serial.available()) {
    Serial.write(Serial.read());
  }
  Serial.printf("\nSerial data processed!\n");
}

void setup() {
  Serial.begin(115200);
  Serial.onReceive(UART_RX_IRQ);
  Serial.println("Send data to UART0 in order to activate the RX callback");
}

void loop() {
  Serial.println("Sleeping for 10 seconds...");
  delay(10000);
}

@SuGlider SuGlider added the Status: To be implemented Selected for Development label Jan 12, 2022
@ianr34
Copy link

ianr34 commented Jan 12, 2022

I I said above - it shouldn't be an interrupt, it should be either a queue that you can wait on ie xQueueReceive, or an event that you can also wait on.

I wrote my own quite a while ago, you do a uart_driver_install, then have a task waiting on that queue, then a task that waits on that to copy it over to another queue for the user program (doing a logical packet at a time), with an optional event. Works great and NO polling OR interrupts..

Waiting on something is much better than interrupts for these types of things, though maybe I think that because I've been writing multi threaded programs for 40 years... It's too limiting trying to process things in an interrupt, which often means you'd just have to raise an event in that anyway... (And I don't mean a volatile bool that you do polling on type of event!!)

@SuGlider
Copy link
Collaborator

I I said above - it shouldn't be an interrupt, it should be either a queue that you can wait on ie xQueueReceive, or an event that you can also wait on.

I wrote my own quite a while ago, you do a uart_driver_install, then have a task waiting on that queue, then a task that waits on that to copy it over to another queue for the user program (doing a logical packet at a time), with an optional event. Works great and NO polling OR interrupts..

Waiting on something is much better than interrupts for these types of things, though maybe I think that because I've been writing multi threaded programs for 40 years... It's too limiting trying to process things in an interrupt, which often means you'd just have to raise an event in that anyway... (And I don't mean a volatile bool that you do polling on type of event!!)

Hi @ianr34

The Arduino API will be the Serial.onReceive(callback_func) but internally it will use a task waiting for UART Events to know when to execute the UART callback. IDF UART has an EventQueue that is populated from the UART ISR, which will be read by a separated task.

So everything will be done exactly as you described above. It will work correctly with FreeRTOS, IDF and Arduino.
You will be able to see it in the code next week, when I publish this PR.

Thanks for your contribution!

@ianr34
Copy link

ianr34 commented Jan 12, 2022

thanks - I'd missed the fact it was a callback, not an interrupt (or a callback from an interrupt) - which means they can spend as much time in it as they need to.. Though of course they will need to be processing fast enough that the serial queue doesn't fill up waiting for this callback to return (I assume in most cases they will be reading the queue in this callback) .. :-)

@SuGlider
Copy link
Collaborator

SuGlider commented Jan 12, 2022

thanks - I'd missed the fact it was a callback, not an interrupt (or a callback from an interrupt) - which means they can spend as much time in it as they need to.. Though of course they will need to be processing fast enough that the serial queue doesn't fill up waiting for this callback to return (I assume in most cases they will be reading the queue in this callback) .. :-)

Yes, exactly. The only potential issue is when the callback never returns and blocks the UART Event Task. But it won't cause any issue to the UART ISR and neither to the regular Arduino Sketch that is running in a separated task as well (or to any other task running within the application). Maybe some WDT will complain about the UART Event Task in the FreeRTOS runtime.

I think it's a safe solution. Let me know if you think about any other potential issue in order to consider it when implementing it.
Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: To be implemented Selected for Development Type: For reference Common questions & problems
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants