aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/include/uart.h19
-rw-r--r--os/hal/platforms/STM32/adc_lld.c17
-rw-r--r--os/hal/platforms/STM32/adc_lld.h55
-rw-r--r--os/hal/platforms/STM32/can_lld.h79
-rw-r--r--os/hal/platforms/STM32/pwm_lld.h55
-rw-r--r--os/hal/platforms/STM32/stm32_dma.h29
-rw-r--r--os/hal/platforms/STM32/uart_lld.c86
-rw-r--r--os/hal/platforms/STM32/uart_lld.h23
8 files changed, 219 insertions, 144 deletions
diff --git a/os/hal/include/uart.h b/os/hal/include/uart.h
index 245bd1939..c0ee4c9ef 100644
--- a/os/hal/include/uart.h
+++ b/os/hal/include/uart.h
@@ -60,25 +60,6 @@
/*===========================================================================*/
/**
- * @brief Generic UART notification callback type.
- */
-typedef void (*uartcb_t)(void);
-
-/**
- * @brief Character received UART notification callback type.
- *
- * @param[in] c received character
- */
-typedef void (*uartccb_t)(uint16_t c);
-
-/**
- * @brief Receive error UART notification callback type.
- *
- * @param[in] e receive error mask
- */
-typedef void (*uartecb_t)(uint16_t e);
-
-/**
* @brief Driver state machine possible states.
*/
typedef enum {
diff --git a/os/hal/platforms/STM32/adc_lld.c b/os/hal/platforms/STM32/adc_lld.c
index 82b70bd12..203eff7d4 100644
--- a/os/hal/platforms/STM32/adc_lld.c
+++ b/os/hal/platforms/STM32/adc_lld.c
@@ -18,8 +18,9 @@
*/
/**
- * @file STM32/adc_lld.c
- * @brief STM32 ADC subsystem low level driver source.
+ * @file STM32/adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
* @addtogroup STM32_ADC
* @{
*/
@@ -52,7 +53,7 @@ ADCDriver ADCD1;
#if USE_STM32_ADC1 || defined(__DOXYGEN__)
/**
- * @brief ADC1 DMA interrupt handler (channel 1).
+ * @brief ADC1 DMA interrupt handler (channel 1).
*/
CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
uint32_t isr;
@@ -107,7 +108,7 @@ CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
/*===========================================================================*/
/**
- * @brief Low level ADC driver initialization.
+ * @brief Low level ADC driver initialization.
*/
void adc_lld_init(void) {
@@ -144,7 +145,7 @@ void adc_lld_init(void) {
}
/**
- * @brief Configures and activates the ADC peripheral.
+ * @brief Configures and activates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
@@ -170,7 +171,7 @@ void adc_lld_start(ADCDriver *adcp) {
}
/**
- * @brief Deactivates the ADC peripheral.
+ * @brief Deactivates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
@@ -191,7 +192,7 @@ void adc_lld_stop(ADCDriver *adcp) {
}
/**
- * @brief Starts an ADC conversion.
+ * @brief Starts an ADC conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
@@ -230,7 +231,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) {
}
/**
- * @brief Stops an ongoing conversion.
+ * @brief Stops an ongoing conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
diff --git a/os/hal/platforms/STM32/adc_lld.h b/os/hal/platforms/STM32/adc_lld.h
index 2b9ac2dd7..599acf69c 100644
--- a/os/hal/platforms/STM32/adc_lld.h
+++ b/os/hal/platforms/STM32/adc_lld.h
@@ -18,8 +18,9 @@
*/
/**
- * @file STM32/adc_lld.h
- * @brief STM32 ADC subsystem low level driver header.
+ * @file STM32/adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
* @addtogroup STM32_ADC
* @{
*/
@@ -60,32 +61,32 @@
/*===========================================================================*/
/**
- * @brief ADC1 driver enable switch.
+ * @brief ADC1 driver enable switch.
* @details If set to @p TRUE the support for ADC1 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_ADC1) || defined(__DOXYGEN__)
#define USE_STM32_ADC1 TRUE
#endif
/**
- * @brief ADC1 DMA priority (0..3|lowest..highest).
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
*/
#if !defined(STM32_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_PRIORITY 3
#endif
/**
- * @brief ADC1 interrupt priority level setting.
+ * @brief ADC1 interrupt priority level setting.
*/
#if !defined(STM32_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_IRQ_PRIORITY 5
#endif
/**
- * @brief ADC1 DMA error hook.
- * @note The default action for DMA errors is a system halt because DMA error
- * can only happen because programming errors.
+ * @brief ADC1 DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA error
+ * can only happen because programming errors.
*/
#if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
@@ -100,24 +101,25 @@
/*===========================================================================*/
/**
- * @brief ADC sample data type.
+ * @brief ADC sample data type.
*/
typedef uint16_t adcsample_t;
/**
- * @brief Channels number in a conversion group.
+ * @brief Channels number in a conversion group.
*/
typedef uint16_t adc_channels_num_t;
/**
- * @brief ADC notification callback type.
- * @param[in] buffer pointer to the most recent samples data
- * @param[in] n number of buffer rows available starting from @p buffer
+ * @brief ADC notification callback type.
+ *
+ * @param[in] buffer pointer to the most recent samples data
+ * @param[in] n number of buffer rows available starting from @p buffer
*/
typedef void (*adccallback_t)(adcsample_t *buffer, size_t n);
/**
- * @brief Conversion group configuration structure.
+ * @brief Conversion group configuration structure.
* @details This implementation-dependent structure describes a conversion
* operation.
*/
@@ -133,15 +135,15 @@ typedef struct {
/* End of the mandatory fields.*/
/**
* @brief ADC CR1 register initialization data.
- * @note All the required bits must be defined into this field except
- * @p ADC_CR1_SCAN that is enforced inside the driver.
+ * @note All the required bits must be defined into this field except
+ * @p ADC_CR1_SCAN that is enforced inside the driver.
*/
uint32_t acg_cr1;
/**
* @brief ADC CR2 register initialization data.
- * @note All the required bits must be defined into this field except
- * @p ADC_CR2_DMA and @p ADC_CR2_ADON that are enforced inside the
- * driver.
+ * @note All the required bits must be defined into this field except
+ * @p ADC_CR2_DMA and @p ADC_CR2_ADON that are enforced inside the
+ * driver.
*/
uint32_t acg_cr2;
/**
@@ -167,21 +169,14 @@ typedef struct {
} ADCConversionGroup;
/**
- * @brief Driver configuration structure.
- * @note It could be empty on some architectures.
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
*/
typedef struct {
- /* * <----------
- * @brief ADC prescaler setting.
- * @note This field can assume one of the following values:
- * @p RCC_CFGR_ADCPRE_DIV2, @p RCC_CFGR_ADCPRE_DIV4,
- * @p RCC_CFGR_ADCPRE_DIV6, @p RCC_CFGR_ADCPRE_DIV8.
- */
-/* uint32_t ac_prescaler;*/
} ADCConfig;
/**
- * @brief Structure representing an ADC driver.
+ * @brief Structure representing an ADC driver.
*/
typedef struct {
/**
diff --git a/os/hal/platforms/STM32/can_lld.h b/os/hal/platforms/STM32/can_lld.h
index 85d86b0cb..fd4784fc7 100644
--- a/os/hal/platforms/STM32/can_lld.h
+++ b/os/hal/platforms/STM32/can_lld.h
@@ -18,8 +18,9 @@
*/
/**
- * @file STM32/can_lld.h
- * @brief STM32 CAN subsystem low level driver header.
+ * @file STM32/can_lld.h
+ * @brief STM32 CAN subsystem low level driver header.
+ *
* @addtogroup STM32_CAN
* @{
*/
@@ -43,13 +44,13 @@
#undef CAN_BTR_SJW
/**
- * @brief This switch defines whether the driver implementation supports
- * a low power switch mode with automatic an wakeup feature.
+ * @brief This switch defines whether the driver implementation supports
+ * a low power switch mode with automatic an wakeup feature.
*/
#define CAN_SUPPORTS_SLEEP TRUE
/**
- * @brief Minimum number of CAN filters.
+ * @brief Minimum number of CAN filters.
*/
#if defined(STM32F10X_CL) || defined(__DOXYGEN__)
#define CAN_MAX_FILTERS 28
@@ -73,16 +74,16 @@
/*===========================================================================*/
/**
- * @brief CAN1 driver enable switch.
+ * @brief CAN1 driver enable switch.
* @details If set to @p TRUE the support for ADC1 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_CAN1) || defined(__DOXYGEN__)
#define USE_STM32_CAN1 TRUE
#endif
/**
- * @brief CAN1 interrupt priority level setting.
+ * @brief CAN1 interrupt priority level setting.
*/
#if !defined(STM32_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_CAN1_IRQ_PRIORITY 11
@@ -101,14 +102,14 @@
/*===========================================================================*/
/**
- * @brief CAN status flags.
+ * @brief CAN status flags.
*/
typedef uint32_t canstatus_t;
/**
- * @brief CAN transmission frame.
- * @note Accessing the frame data as word16 or word32 is not portable because
- * machine data endianness, it can be still useful for a quick filling.
+ * @brief CAN transmission frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
*/
typedef struct {
struct {
@@ -132,9 +133,9 @@ typedef struct {
} CANTxFrame;
/**
- * @brief CAN received frame.
- * @note Accessing the frame data as word16 or word32 is not portable because
- * machine data endianness, it can be still useful for a quick filling.
+ * @brief CAN received frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
*/
typedef struct {
struct {
@@ -162,26 +163,26 @@ typedef struct {
} CANRxFrame;
/**
- * @brief CAN filter.
- * @note Refer to the STM32 reference manual for info about filters.
+ * @brief CAN filter.
+ * @note Refer to the STM32 reference manual for info about filters.
*/
typedef struct {
/**
* @brief Filter mode.
- * @note This bit represent the CAN_FM1R register bit associated to this
- * filter (0=mask mode, 1=list mode).
+ * @note This bit represent the CAN_FM1R register bit associated to this
+ * filter (0=mask mode, 1=list mode).
*/
uint32_t cf_mode:1;
/**
* @brief Filter sclae.
- * @note This bit represent the CAN_FS1R register bit associated to this
- * filter (0=16 bits mode, 1=32 bits mode).
+ * @note This bit represent the CAN_FS1R register bit associated to this
+ * filter (0=16 bits mode, 1=32 bits mode).
*/
uint32_t cf_scale:1;
/**
* @brief Filter mode.
- * @note This bit represent the CAN_FFA1R register bit associated to this
- * filter, must be set to zero in this version of the driver.
+ * @note This bit represent the CAN_FFA1R register bit associated to this
+ * filter, must be set to zero in this version of the driver.
*/
uint32_t cf_assignment:1;
/**
@@ -195,37 +196,37 @@ typedef struct {
} CANFilter;
/**
- * @brief Driver configuration structure.
+ * @brief Driver configuration structure.
*/
typedef struct {
/**
* @brief CAN MCR register initialization data.
- * @note Some bits in this register are enforced by the driver regardless
- * their status in this field.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
*/
uint32_t cc_mcr;
/**
* @brief CAN BTR register initialization data.
- * @note Some bits in this register are enforced by the driver regardless
- * their status in this field.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
*/
uint32_t cc_btr;
/**
* @brief Number of elements into the filters array.
- * @note By setting this field to zero a default filter is enabled that
- * allows all frames, this should be adequate for simple applications.
+ * @note By setting this field to zero a default filter is enabled that
+ * allows all frames, this should be adequate for simple applications.
*/
uint32_t cc_num;
/**
* @brief Pointer to an array of @p CANFilter structures.
- * @note This field can be set to @p NULL if the field @p cc_num is set to
- * zero.
+ * @note This field can be set to @p NULL if the field @p cc_num is set to
+ * zero.
*/
const CANFilter *cc_filters;
} CANConfig;
/**
- * @brief Structure representing an CAN driver.
+ * @brief Structure representing an CAN driver.
*/
typedef struct {
/**
@@ -246,12 +247,12 @@ typedef struct {
Semaphore cd_rxsem;
/**
* @brief One or more frames become available.
- * @note After broadcasting this event it will not be broadcasted again
- * until the received frames queue has been completely emptied. It
- * is <b>not</b> broadcasted for each received frame. It is
- * responsibility of the application to empty the queue by repeatedly
- * invoking @p chReceive() when listening to this event. This behavior
- * minimizes the interrupt served by the system because CAN traffic.
+ * @note After broadcasting this event it will not be broadcasted again
+ * until the received frames queue has been completely emptied. It
+ * is <b>not</b> broadcasted for each received frame. It is
+ * responsibility of the application to empty the queue by repeatedly
+ * invoking @p chReceive() when listening to this event. This behavior
+ * minimizes the interrupt served by the system because CAN traffic.
*/
EventSource cd_rxfull_event;
/**
diff --git a/os/hal/platforms/STM32/pwm_lld.h b/os/hal/platforms/STM32/pwm_lld.h
index 4249a8514..8605bb314 100644
--- a/os/hal/platforms/STM32/pwm_lld.h
+++ b/os/hal/platforms/STM32/pwm_lld.h
@@ -18,8 +18,9 @@
*/
/**
- * @file STM32/pwm_lld.h
- * @brief STM32 PWM subsystem low level driver header.
+ * @file STM32/pwm_lld.h
+ * @brief STM32 PWM subsystem low level driver header.
+ *
* @addtogroup STM32_PWM
* @{
*/
@@ -34,7 +35,7 @@
/*===========================================================================*/
/**
- * @brief Number of PWM channels per PWM driver.
+ * @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS 4
@@ -43,64 +44,64 @@
/*===========================================================================*/
/**
- * @brief PWM1 driver enable switch.
+ * @brief PWM1 driver enable switch.
* @details If set to @p TRUE the support for PWM1 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_PWM1) || defined(__DOXYGEN__)
#define USE_STM32_PWM1 TRUE
#endif
/**
- * @brief PWM2 driver enable switch.
+ * @brief PWM2 driver enable switch.
* @details If set to @p TRUE the support for PWM2 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_PWM2) || defined(__DOXYGEN__)
#define USE_STM32_PWM2 TRUE
#endif
/**
- * @brief PWM3 driver enable switch.
+ * @brief PWM3 driver enable switch.
* @details If set to @p TRUE the support for PWM3 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_PWM3) || defined(__DOXYGEN__)
#define USE_STM32_PWM3 TRUE
#endif
/**
- * @brief PWM4 driver enable switch.
+ * @brief PWM4 driver enable switch.
* @details If set to @p TRUE the support for PWM4 is included.
- * @note The default is @p TRUE.
+ * @note The default is @p TRUE.
*/
#if !defined(USE_STM32_PWM4) || defined(__DOXYGEN__)
#define USE_STM32_PWM4 TRUE
#endif
/**
- * @brief PWM1 interrupt priority level setting.
+ * @brief PWM1 interrupt priority level setting.
*/
#if !defined(STM32_PWM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM1_IRQ_PRIORITY 7
#endif
/**
- * @brief PWM2 interrupt priority level setting.
+ * @brief PWM2 interrupt priority level setting.
*/
#if !defined(STM32_PWM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM2_IRQ_PRIORITY 7
#endif
/**
- * @brief PWM3 interrupt priority level setting.
+ * @brief PWM3 interrupt priority level setting.
*/
#if !defined(STM32_PWM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM3_IRQ_PRIORITY 7
#endif
/**
- * @brief PWM4 interrupt priority level setting.
+ * @brief PWM4 interrupt priority level setting.
*/
#if !defined(STM32_PWM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM4_IRQ_PRIORITY 7
@@ -119,18 +120,18 @@
/*===========================================================================*/
/**
- * @brief PWM channel type.
+ * @brief PWM channel type.
*/
typedef uint8_t pwmchannel_t;
/**
- * @brief PWM counter type.
+ * @brief PWM counter type.
*/
typedef uint16_t pwmcnt_t;
/**
- * @brief PWM driver channel configuration structure.
- * @note It could be empty on some architectures.
+ * @brief PWM driver channel configuration structure.
+ * @note It could be empty on some architectures.
*/
typedef struct {
/**
@@ -139,22 +140,22 @@ typedef struct {
pwmmode_t pcc_mode;
/**
* @brief Channel callback pointer.
- * @details This callback is invoked on the channel compare event. If set to
- * @p NULL then the callback is disabled.
+ * @note This callback is invoked on the channel compare event. If set to
+ * @p NULL then the callback is disabled.
*/
pwmcallback_t pcc_callback;
/* End of the mandatory fields.*/
} PWMChannelConfig;
/**
- * @brief PWM driver configuration structure.
- * @note It could be empty on some architectures.
+ * @brief PWM driver configuration structure.
+ * @note It could be empty on some architectures.
*/
typedef struct {
/**
* @brief Periodic callback pointer.
- * @details This callback is invoked on PWM counter reset. If set to
- * @p NULL then the callback is disabled.
+ * @note This callback is invoked on PWM counter reset. If set to
+ * @p NULL then the callback is disabled.
*/
pwmcallback_t pc_callback;
/**
@@ -172,13 +173,13 @@ typedef struct {
uint16_t pc_arr;
/**
* @brief TIM CR2 register initialization data.
- * @note The value of this field should normally be equal to zero.
+ * @note The value of this field should normally be equal to zero.
*/
uint16_t pc_cr2;
} PWMConfig;
/**
- * @brief Structure representing a PWM driver.
+ * @brief Structure representing a PWM driver.
*/
typedef struct {
/**
diff --git a/os/hal/platforms/STM32/stm32_dma.h b/os/hal/platforms/STM32/stm32_dma.h
index dba85711e..94e863d31 100644
--- a/os/hal/platforms/STM32/stm32_dma.h
+++ b/os/hal/platforms/STM32/stm32_dma.h
@@ -131,7 +131,13 @@ typedef struct {
* value does not change frequently, it usually points to a peripheral
* data register.
* @note Channels are numbered from 0 to 6, use the appropriate macro
- * as parameter.
+ * as parameter.
+ *
+ * @param[in] dmap pointer to a stm32_dma_t structure
+ * @param[in] ch channel number
+ * @param[in] cntdr value to be written in the CNDTR register
+ * @param[in] cmar value to be written in the CMAR register
+ * @param[in] ccr value to be written in the CCR register
*/
#define dmaSetupChannel(dmap, ch, cndtr, cmar, ccr) { \
stm32_dma_channel_t *dmachp = &dmap->channels[ch]; \
@@ -142,11 +148,28 @@ typedef struct {
/**
* @brief DMA channel disable.
- * @note Channel's pending interrupts are cleared.
+ * @note Channels are numbered from 0 to 6, use the appropriate macro
+ * as parameter.
+ *
+ * @param[in] dmap pointer to a stm32_dma_t structure
+ * @param[in] ch channel number
*/
#define dmaDisableChannel(dmap, ch) { \
(dmap)->channels[ch].CCR = 0; \
- (dmap)->IFCR = 0xF << (ch); \
+}
+
+/**
+ * @brief DMA channel interrupt sources clear.
+ * @details Sets the appropriate CGIF bit into the IFCR register in order to
+ * withdraw all the pending interrupt bits from the ISR register.
+ * @note Channels are numbered from 0 to 6, use the appropriate macro
+ * as parameter.
+ *
+ * @param[in] dmap pointer to a stm32_dma_t structure
+ * @param[in] ch channel number
+ */
+#define dmaClearChannel(dmap, ch){ \
+ (dmap)->IFCR = 1 << (ch); \
}
/*===========================================================================*/
diff --git a/os/hal/platforms/STM32/uart_lld.c b/os/hal/platforms/STM32/uart_lld.c
index 73088a454..56930a686 100644
--- a/os/hal/platforms/STM32/uart_lld.c
+++ b/os/hal/platforms/STM32/uart_lld.c
@@ -48,6 +48,39 @@ UARTDriver UARTD1;
/*===========================================================================*/
/**
+ * @brief Puts the receiver in the UART_RX_IDLE state.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void set_rx_idle(UARTDriver *uartp) {
+ uint32_t ccr;
+
+ dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
+ dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx);
+ uartp->ud_rxstate = UART_RX_IDLE;
+
+ /* RX DMA channel preparation, circular 1 frame transfers, an interrupt is
+ generated for each received character if the callback is defined.*/
+ ccr = DMA_CCR1_TEIE | DMA_CCR1_CIRC | DMA_CCR1_EN;
+ if (uartp->ud_config->uc_rxchar != NULL)
+ ccr |= DMA_CCR1_TCIE;
+ dmaSetupChannel(uartp->ud_dmap, uartp->ud_dmarx, 1,
+ &uartp->ud_rxbuf, uartp->ud_dmaccr | ccr);
+}
+
+/**
+ * @brief Puts the transmitter in the UART_TX_IDLE state.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void set_tx_idle(UARTDriver *uartp) {
+
+ dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx);
+ dmaClearChannel(uartp->ud_dmap, uartp->ud_dmatx);
+ uartp->ud_txstate = UART_TX_IDLE;
+}
+
+/**
* @brief USART initialization.
* @details This function must be invoked with interrupts disabled.
*
@@ -73,26 +106,23 @@ static void usart_start(UARTDriver *uartp) {
(void)u->SR; /* SR reset step 1.*/
(void)u->DR; /* SR reset step 2.*/
- /* RX DMA channel preparation, circular 1 frame transfers, an interrupt is
- generated for each received character.*/
- dmaSetupChannel(uartp->ud_dmap, uartp->ud_dmarx, 1, &uartp->ud_rxbuf,
- DMA_CCR1_TCIE | DMA_CCR1_TEIE | DMA_CCR1_CIRC | DMA_CCR1_EN);
-
- /* TX DMA channel preparation, simply disabled.*/
- dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx);
+ set_rx_idle(uartp);
+ set_tx_idle(uartp);
}
/**
* @brief USART de-initialization.
* @details This function must be invoked with interrupts disabled.
*
- * @param[in] u pointer to an USART I/O block
+ * @param[in] uartp pointer to the @p UARTDriver object
*/
static void usart_stop(UARTDriver *uartp) {
/* Stops RX and TX DMA channels.*/
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx);
+ dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx);
+ dmaClearChannel(uartp->ud_dmap, uartp->ud_dmatx);
/* Stops USART operations.*/
uartp->ud_usart->CR1 = 0;
@@ -109,11 +139,30 @@ static void usart_stop(UARTDriver *uartp) {
* @brief USART1 RX DMA interrupt handler (channel 4).
*/
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
+ UARTDriver *uartp;
CH_IRQ_PROLOGUE();
- DMA1->IFCR |= DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 |
- DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4;
+ dmaClearChannel(&DMA1, STM32_DMA_CHANNEL_4);
+
+ uartp = &UARTD1;
+ if (uartp->ud_rxstate == UART_RX_IDLE) {
+ /* Receiver in idle state, a callback is generated, if enabled, for each
+ received character.*/
+ if (uartp->ud_config->uc_rxchar != NULL)
+ uartp->ud_config->uc_rxchar(uartp->ud_rxbuf);
+ }
+ else {
+ /* Receiver in active state, a callback is generated, if enabled, after
+ a completed transfer.*/
+ uartp->ud_rxstate = UART_RX_COMPLETE;
+ if (uartp->ud_config->uc_rxend != NULL)
+ uartp->ud_config->uc_rxend();
+ /* If the callback didn't restart a receive operation then the receiver
+ returns to the idle state.*/
+ if (uartp->ud_rxstate == UART_RX_COMPLETE)
+ set_rx_idle(uartp);
+ }
CH_IRQ_EPILOGUE();
}
@@ -125,17 +174,24 @@ CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
CH_IRQ_PROLOGUE();
- DMA1->IFCR |= DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 |
- DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5;
+ dmaClearChannel(&DMA1, STM32_DMA_CHANNEL_5);
+
+ /* A callback is generated, if enabled, after a completed transfer.*/
+ uartp->ud_txstate = UART_TX_COMPLETE;
+ if (UARTD1.ud_config->uc_txend1 != NULL)
+ UARTD1.ud_config->uc_txend1();
+ /* If the callback didn't restart a transmit operation then the transmitter
+ returns to the idle state.*/
+ if (uartp->ud_txstate == UART_TX_COMPLETE)
+ set_tx_idle(uartp);
CH_IRQ_EPILOGUE();
}
-CH_IRQ_HANDLER(USART2_IRQHandler) {
+CH_IRQ_HANDLER(USART1_IRQHandler) {
CH_IRQ_PROLOGUE();
- serve_interrupt(&SD2);
CH_IRQ_EPILOGUE();
}
@@ -190,8 +246,6 @@ void uart_lld_start(UARTDriver *uartp) {
uartp->ud_dmap->channels[uartp->ud_dmarx].CPAR = (uint32_t)&uartp->ud_usart->DR;
uartp->ud_dmap->channels[uartp->ud_dmatx].CPAR = (uint32_t)&uartp->ud_usart->DR;
}
- uartp->ud_txstate = UART_TX_IDLE;
- uartp->ud_rxstate = UART_RX_IDLE;
usart_start(uartp);
}
diff --git a/os/hal/platforms/STM32/uart_lld.h b/os/hal/platforms/STM32/uart_lld.h
index 29cdda1ed..2977e15c5 100644
--- a/os/hal/platforms/STM32/uart_lld.h
+++ b/os/hal/platforms/STM32/uart_lld.h
@@ -78,6 +78,25 @@
typedef uint32_t uartflags_t;
/**
+ * @brief Generic UART notification callback type.
+ */
+typedef void (*uartcb_t)(void);
+
+/**
+ * @brief Character received UART notification callback type.
+ *
+ * @param[in] c received character
+ */
+typedef void (*uartccb_t)(uint16_t c);
+
+/**
+ * @brief Receive error UART notification callback type.
+ *
+ * @param[in] e receive error mask
+ */
+typedef void (*uartecb_t)(uartflags_t e);
+
+/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
@@ -89,9 +108,9 @@ typedef struct {
/** @brief Receive buffer filled callback.*/
uartcb_t uc_rxend;
/** @brief Character received while out if the @p UART_RECEIVE state.*/
- uartcb_t uc_rxchar;
+ uartccb_t uc_rxchar;
/** @brief Receive error callback.*/
- uartcb_t uc_rxerr;
+ uartecb_t uc_rxerr;
/* End of the mandatory fields.*/
/** @brief Bit rate.*/
uint32_t uc_speed;