From 3842e19e604cabf74af38762fdfa722710fdbf9f Mon Sep 17 00:00:00 2001 From: kaizoku-oh Date: Wed, 5 Jun 2024 16:37:56 +0100 Subject: [PATCH] Raise Serial/SerialUSB interrupts to user code This commit Adds the ability for the user to register a callback for Serial/SerialUSB events (TX/RX) Signed-off-by: kaizoku-oh --- cores/arduino/HardwareSerial.cpp | 20 ++++++++++++++++++- cores/arduino/HardwareSerial.h | 1 + cores/arduino/USBSerial.cpp | 8 ++++++++ cores/arduino/USBSerial.h | 2 ++ cores/arduino/stm32/uart.h | 8 ++++++++ cores/arduino/stm32/usb/cdc/usbd_cdc_if.c | 24 +++++++++++++++++++++++ cores/arduino/stm32/usb/cdc/usbd_cdc_if.h | 8 ++++++++ 7 files changed, 70 insertions(+), 1 deletion(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 146cfa234e..8d20fd98b3 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -347,6 +347,12 @@ void HardwareSerial::_rx_complete_irq(serial_t *obj) obj->rx_head = i; } } + + // Raise user event callback if registered + if (obj->event_callback) + { + obj->event_callback(SERIAL_EVENT_RX); + } } // Actual interrupt handlers ////////////////////////////////////////////////// @@ -368,7 +374,11 @@ int HardwareSerial::_tx_complete_irq(serial_t *obj) uart_attach_tx_callback(obj, _tx_complete_irq, obj->tx_size); return -1; } - + // Raise user event callback if registered + if (obj->event_callback) + { + obj->event_callback(SERIAL_EVENT_TX); + } return 0; } @@ -655,4 +665,12 @@ void HardwareSerial::enableHalfDuplexRx(void) } } +void HardwareSerial::onEvent(SerialCallback_t callback) +{ + if (callback) + { + _serial.event_callback = callback; + } +} + #endif // HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index bfd94620ba..e2d4e538cf 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -169,6 +169,7 @@ class HardwareSerial : public Stream { void setHalfDuplex(void); bool isHalfDuplex(void) const; void enableHalfDuplexRx(void); + void onEvent(SerialCallback_t event_callback); friend class STM32LowPower; diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index c777105038..328d97ba35 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -197,4 +197,12 @@ USBSerial::operator bool() return dtrState; } +void USBSerial::onEvent(USBSerialCallback_t callback) +{ + if (callback) + { + CDC_register_cb(callback); + } +} + #endif // USBCON && USBD_USE_CDC diff --git a/cores/arduino/USBSerial.h b/cores/arduino/USBSerial.h index 202c059daa..dcabf5bb77 100644 --- a/cores/arduino/USBSerial.h +++ b/cores/arduino/USBSerial.h @@ -22,6 +22,7 @@ #if defined (USBCON) && defined(USBD_USE_CDC) #include "Stream.h" #include "usbd_core.h" +#include "usbd_cdc_if.h" //================================================================================ // Serial over CDC @@ -43,6 +44,7 @@ class USBSerial : public Stream { virtual size_t write(const uint8_t *buffer, size_t size); using Print::write; // pull in write(str) from Print operator bool(void); + void onEvent(USBSerialCallback_t callback); // These return the settings specified by the USB host for the // serial port. These aren't really used, but are offered here diff --git a/cores/arduino/stm32/uart.h b/cores/arduino/stm32/uart.h index 2a8537f45c..00c3f9bfc2 100644 --- a/cores/arduino/stm32/uart.h +++ b/cores/arduino/stm32/uart.h @@ -59,6 +59,13 @@ extern "C" { /* Exported types ------------------------------------------------------------*/ typedef struct serial_s serial_t; +typedef enum { + SERIAL_EVENT_TX, + SERIAL_EVENT_RX +} SerialEvent_t; + +typedef void (*SerialCallback_t)(SerialEvent_t event); + struct serial_s { /* The 1st 2 members USART_TypeDef *uart * and UART_HandleTypeDef handle should @@ -69,6 +76,7 @@ struct serial_s { UART_HandleTypeDef handle; void (*rx_callback)(serial_t *); int (*tx_callback)(serial_t *); + SerialCallback_t event_callback; PinName pin_tx; PinName pin_rx; PinName pin_rts; diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index 326ef3216d..10f4b38413 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -59,6 +59,7 @@ __IO bool dtrState = false; /* lineState */ __IO bool rtsState = false; __IO bool receivePended = true; static uint32_t transmitStart = 0; +static USBSerialCallback_t eventCallback; #ifdef DTR_TOGGLING_SEQ /* DTR toggling sequence management */ @@ -244,6 +245,10 @@ static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) if (!CDC_resume_receive()) { USBD_CDC_ClearBuffer(&hUSBD_Device_CDC); } + // Raise user event callback if registered + if (eventCallback) { + eventCallback(USB_SERIAL_EVENT_RX); + } return ((int8_t)USBD_OK); } @@ -268,6 +273,10 @@ static int8_t USBD_CDC_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) transmitStart = 0; CDC_TransmitQueue_CommitRead(&TransmitQueue); CDC_continue_transmit(); + // Raise user event callback if registered + if (eventCallback) { + eventCallback(USB_SERIAL_EVENT_TX); + } return ((int8_t)USBD_OK); } @@ -379,6 +388,21 @@ void CDC_enableDTR(bool enable) CDC_DTR_enabled = enable; } +/** + * @brief CDC_register_cb + * Register USBCDC event callback + * @param callback: Pointer to user callback function + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +int8_t CDC_register_cb(USBSerialCallback_t callback) +{ + if (callback) { + eventCallback = callback; + return ((int8_t)USBD_OK); + } + return ((int8_t)USBD_FAIL); +} + #endif /* USBD_USE_CDC */ #endif /* USBCON */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index fe05df536a..67ebc1ede2 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -37,6 +37,13 @@ extern "C" { #define CDC_POLLING_INTERVAL 2 /* in ms. The max is 65 and the min is 1 */ /* Exported types ------------------------------------------------------------*/ +typedef enum { + USB_SERIAL_EVENT_TX, + USB_SERIAL_EVENT_RX +} USBSerialEvent_t; + +typedef void (*USBSerialCallback_t)(USBSerialEvent_t); + /* Exported constants --------------------------------------------------------*/ extern USBD_CDC_ItfTypeDef USBD_CDC_fops; @@ -52,6 +59,7 @@ void CDC_init(void); void CDC_deInit(void); bool CDC_connected(void); void CDC_enableDTR(bool enable); +int8_t CDC_register_cb(USBSerialCallback_t callback); #ifdef __cplusplus }