-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Arduino 2.0.0 - Question: wants to use UART Rx interrupt but still keeps HardwareSerial API to handles data from Rx FIFO #5678
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
Comments
Looks like PR#4656 is "on the radar" to be included officially? I was expecting it to be in the v2.0.0 already... I'm using my Hardware serial.cpp modified according to this PR. |
Thanks for pointing this. It seems not including on v2.0.0 yet. This PR is exactly what I was looking for. On PR#4656 actually the same way that I used to enable serial interrupt on v1.0.6. But as v2.0.0 underlying of HardwareSerial changes to used IDF's APIs as I mentioned. The downside of current interrupt usage on v2.0.0 is that it need to overrides Example of my current serial interrupt usage. As you can see it's like going back to v1.0.6. void MyHardwareSerial::begin(uint32_t baud)
{
//? same implementation of `uartBegin()` but with my queue init
....
_uart0_queue = xQueueCreate(bufferSize, sizeof(uint8_t));
....
uart_t *uart = &_uart_bus_array[_uart_nr];
....
//? register uart driver and hardware pins
....
//? register uart interrupt
ESP_ERROR_CHECK(uart_isr_free(_uart_nr));
ESP_ERROR_CHECK(uart_isr_register(_uart_nr, _interruptHandler, NULL, ARDUINO_ISR_FLAG, NULL));
ESP_ERROR_CHECK(uart_enable_rx_intr(_uart_nr));
_uart = uart; //? points my init uart to HardwareSerial uart object
}
void ARDUINO_ISR_ATTR MyHardwareSerial::_interruptHandler(void *arg)
{
uint8_t inByte;
usb_serial_t selected_buffer;
uart_dev_t *hw = UART_REG_ADDR(0);
BaseType_t xHigherPriorityTaskWoken;
//? clear interrupt status by set masks
hw->int_clr.val = (UART_RXFIFO_FULL_INT_CLR | UART_FRM_ERR_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
while (hw->status.rxfifo_cnt || (hw->mem_rx_status.wr_addr != hw->mem_rx_status.rd_addr))
{
inByte = hw->fifo.rw_byte;
//? checking my packet byte if isn't my packet put it to uart queue for other purpose by access via HardwareSerial APIs
if ( ... )
{
// doing my packet stuff ...
}
else
{
if (_uart0_queue != NULL)
{
xQueueSendFromISR(_uart0_queue, &inByte, &xHigherPriorityTaskWoken);
}
}
}
if (xHigherPriorityTaskWoken)
{
portYIELD_FROM_ISR();
}
}
int MyHardwareSerial::available(void)
{
if (_uart == NULL || _uart0_queue == NULL || _uart2_queue == NULL)
return 0;
QueueHandle_t selected_queue = (_uart_nr == 0) ? _uart0_queue : (_uart_nr == 2) ? _uart2_queue : NULL;
return uxQueueMessagesWaiting(selected_queue);
}
int MyHardwareSerial::read(void)
{
if (available())
{
if (_uart == NULL || _uart0_queue == NULL || _uart2_queue == NULL)
return 0;
QueueHandle_t selected_queue = (_uart_nr == 0) ? _uart0_queue : (_uart_nr == 2) ? _uart2_queue : NULL;
uint8_t c;
if (xQueueReceive(selected_queue, &c, 0))
{
return c;
}
return 0;
}
return -1;
} The main point of my problem is when I took data from Rx FIFO to check the packet, I cannot put it back(or it can ?) if it's not my packet. So I do as an example shown to workaround Rx FIFO access by created the queue. Anyway it's not an issue at all, just wants to asking there is the other way round. I understand that current implementation will be fits for most users usage. |
If you want to try the PR4656, just replace the attached four files in your ESP32 core folder (make a backup of existing ones first). For me it's working 99%. I'm just trying to understand why only sometimes, during :
The ESP32 is freezing in the Setup initialization.... maybe you can try to see if that happens with you as well. BTW, I'm still using HardwareSerial esp32_2.0.0_cores.zip
|
@mycbtec your issue may relate to this one RX line has traffic at boot, this has been solved by using core v2.0.0 (UART IDF refactoring). I tried the PR#4656 and stuck at BTW, I don't want to mesh up with core itself. As my example |
A potential solution is being implemented. As soon as any data arrives UART RX, 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);
} Would that work for you? |
Sure, This can be solved current 'Arduino Things' that need to be handles from user side when using serial interrupt. Looking forward to trying out on 2.0.3, Thanks ! |
@MomePP did you try I still have PR#4656 implemented in my code and was planning to update it... any feedback would be appreciated!! |
@mycbtec Same here, I did not try One thing, I notice when I'm trying to use In future, if I had a chance to use this in my new project implementation, I will update here. 😀 |
I'm testing your example above... Is it possible to trigger ISR every single byte UART RX receives? |
Hardware:
Board: ESP32 Dev Module
Core Installation version: 2.0.0
IDE name: PlatformIO
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 921600
Computer OS: Mac OSX
Description:
Currently, I got UART interrupt working fine. I have created new class to inherits
HardwareSerial
then overridesbegin()
to enables interrupt routine. As my understanding from ESP32 docs, when registered interrupt isr, its override default isr handler. This means the RxHardwareSerial
that relies on IDF's API (eg.read
,available
, etc.) will be unusable, need to handles from isr by user. So, I have override HardwareSerial functions to points to a new create buffer, queue that handles the data from isr (likes an old implementation in 1.0.6).I have take a look at
uart-event
but if i want to unpack my serial packet per byte, i think isr still the way to go. correct me if i misunderstood.Is there any other solution to workaround this if i still want to use HardwareSerial functions (some libraries that based on default HardwareSerial functions) while using UART interrupt.
Cheers,
MomePP
The text was updated successfully, but these errors were encountered: