git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2094 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2010-07-27 10:31:19 +00:00
parent b91f48eb10
commit 79b97b0f60
8 changed files with 219 additions and 144 deletions

View File

@ -59,25 +59,6 @@
/* Driver data structures and types. */ /* Driver data structures and types. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @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. * @brief Driver state machine possible states.
*/ */

View File

@ -18,8 +18,9 @@
*/ */
/** /**
* @file STM32/adc_lld.c * @file STM32/adc_lld.c
* @brief STM32 ADC subsystem low level driver source. * @brief STM32 ADC subsystem low level driver source.
*
* @addtogroup STM32_ADC * @addtogroup STM32_ADC
* @{ * @{
*/ */
@ -52,7 +53,7 @@ ADCDriver ADCD1;
#if USE_STM32_ADC1 || defined(__DOXYGEN__) #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) { CH_IRQ_HANDLER(DMA1_Ch1_IRQHandler) {
uint32_t isr; 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) { 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 * @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 * @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 * @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 * @param[in] adcp pointer to the @p ADCDriver object
*/ */

View File

@ -18,8 +18,9 @@
*/ */
/** /**
* @file STM32/adc_lld.h * @file STM32/adc_lld.h
* @brief STM32 ADC subsystem low level driver header. * @brief STM32 ADC subsystem low level driver header.
*
* @addtogroup STM32_ADC * @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. * @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__) #if !defined(USE_STM32_ADC1) || defined(__DOXYGEN__)
#define USE_STM32_ADC1 TRUE #define USE_STM32_ADC1 TRUE
#endif #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__) #if !defined(STM32_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_PRIORITY 3 #define STM32_ADC1_DMA_PRIORITY 3
#endif #endif
/** /**
* @brief ADC1 interrupt priority level setting. * @brief ADC1 interrupt priority level setting.
*/ */
#if !defined(STM32_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_IRQ_PRIORITY 5 #define STM32_ADC1_IRQ_PRIORITY 5
#endif #endif
/** /**
* @brief ADC1 DMA error hook. * @brief ADC1 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error * @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors. * can only happen because programming errors.
*/ */
#if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__) #if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt() #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; 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; typedef uint16_t adc_channels_num_t;
/** /**
* @brief ADC notification callback type. * @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 * @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); 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 * @details This implementation-dependent structure describes a conversion
* operation. * operation.
*/ */
@ -133,15 +135,15 @@ typedef struct {
/* End of the mandatory fields.*/ /* End of the mandatory fields.*/
/** /**
* @brief ADC CR1 register initialization data. * @brief ADC CR1 register initialization data.
* @note All the required bits must be defined into this field except * @note All the required bits must be defined into this field except
* @p ADC_CR1_SCAN that is enforced inside the driver. * @p ADC_CR1_SCAN that is enforced inside the driver.
*/ */
uint32_t acg_cr1; uint32_t acg_cr1;
/** /**
* @brief ADC CR2 register initialization data. * @brief ADC CR2 register initialization data.
* @note All the required bits must be defined into this field except * @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 * @p ADC_CR2_DMA and @p ADC_CR2_ADON that are enforced inside the
* driver. * driver.
*/ */
uint32_t acg_cr2; uint32_t acg_cr2;
/** /**
@ -167,21 +169,14 @@ typedef struct {
} ADCConversionGroup; } ADCConversionGroup;
/** /**
* @brief Driver configuration structure. * @brief Driver configuration structure.
* @note It could be empty on some architectures. * @note It could be empty on some architectures.
*/ */
typedef struct { 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; } ADCConfig;
/** /**
* @brief Structure representing an ADC driver. * @brief Structure representing an ADC driver.
*/ */
typedef struct { typedef struct {
/** /**

View File

@ -18,8 +18,9 @@
*/ */
/** /**
* @file STM32/can_lld.h * @file STM32/can_lld.h
* @brief STM32 CAN subsystem low level driver header. * @brief STM32 CAN subsystem low level driver header.
*
* @addtogroup STM32_CAN * @addtogroup STM32_CAN
* @{ * @{
*/ */
@ -43,13 +44,13 @@
#undef CAN_BTR_SJW #undef CAN_BTR_SJW
/** /**
* @brief This switch defines whether the driver implementation supports * @brief This switch defines whether the driver implementation supports
* a low power switch mode with automatic an wakeup feature. * a low power switch mode with automatic an wakeup feature.
*/ */
#define CAN_SUPPORTS_SLEEP TRUE #define CAN_SUPPORTS_SLEEP TRUE
/** /**
* @brief Minimum number of CAN filters. * @brief Minimum number of CAN filters.
*/ */
#if defined(STM32F10X_CL) || defined(__DOXYGEN__) #if defined(STM32F10X_CL) || defined(__DOXYGEN__)
#define CAN_MAX_FILTERS 28 #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. * @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__) #if !defined(USE_STM32_CAN1) || defined(__DOXYGEN__)
#define USE_STM32_CAN1 TRUE #define USE_STM32_CAN1 TRUE
#endif #endif
/** /**
* @brief CAN1 interrupt priority level setting. * @brief CAN1 interrupt priority level setting.
*/ */
#if !defined(STM32_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_CAN1_IRQ_PRIORITY 11 #define STM32_CAN1_IRQ_PRIORITY 11
@ -101,14 +102,14 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief CAN status flags. * @brief CAN status flags.
*/ */
typedef uint32_t canstatus_t; typedef uint32_t canstatus_t;
/** /**
* @brief CAN transmission frame. * @brief CAN transmission frame.
* @note Accessing the frame data as word16 or word32 is not portable because * @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. * machine data endianness, it can be still useful for a quick filling.
*/ */
typedef struct { typedef struct {
struct { struct {
@ -132,9 +133,9 @@ typedef struct {
} CANTxFrame; } CANTxFrame;
/** /**
* @brief CAN received frame. * @brief CAN received frame.
* @note Accessing the frame data as word16 or word32 is not portable because * @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. * machine data endianness, it can be still useful for a quick filling.
*/ */
typedef struct { typedef struct {
struct { struct {
@ -162,26 +163,26 @@ typedef struct {
} CANRxFrame; } CANRxFrame;
/** /**
* @brief CAN filter. * @brief CAN filter.
* @note Refer to the STM32 reference manual for info about filters. * @note Refer to the STM32 reference manual for info about filters.
*/ */
typedef struct { typedef struct {
/** /**
* @brief Filter mode. * @brief Filter mode.
* @note This bit represent the CAN_FM1R register bit associated to this * @note This bit represent the CAN_FM1R register bit associated to this
* filter (0=mask mode, 1=list mode). * filter (0=mask mode, 1=list mode).
*/ */
uint32_t cf_mode:1; uint32_t cf_mode:1;
/** /**
* @brief Filter sclae. * @brief Filter sclae.
* @note This bit represent the CAN_FS1R register bit associated to this * @note This bit represent the CAN_FS1R register bit associated to this
* filter (0=16 bits mode, 1=32 bits mode). * filter (0=16 bits mode, 1=32 bits mode).
*/ */
uint32_t cf_scale:1; uint32_t cf_scale:1;
/** /**
* @brief Filter mode. * @brief Filter mode.
* @note This bit represent the CAN_FFA1R register bit associated to this * @note This bit represent the CAN_FFA1R register bit associated to this
* filter, must be set to zero in this version of the driver. * filter, must be set to zero in this version of the driver.
*/ */
uint32_t cf_assignment:1; uint32_t cf_assignment:1;
/** /**
@ -195,37 +196,37 @@ typedef struct {
} CANFilter; } CANFilter;
/** /**
* @brief Driver configuration structure. * @brief Driver configuration structure.
*/ */
typedef struct { typedef struct {
/** /**
* @brief CAN MCR register initialization data. * @brief CAN MCR register initialization data.
* @note Some bits in this register are enforced by the driver regardless * @note Some bits in this register are enforced by the driver regardless
* their status in this field. * their status in this field.
*/ */
uint32_t cc_mcr; uint32_t cc_mcr;
/** /**
* @brief CAN BTR register initialization data. * @brief CAN BTR register initialization data.
* @note Some bits in this register are enforced by the driver regardless * @note Some bits in this register are enforced by the driver regardless
* their status in this field. * their status in this field.
*/ */
uint32_t cc_btr; uint32_t cc_btr;
/** /**
* @brief Number of elements into the filters array. * @brief Number of elements into the filters array.
* @note By setting this field to zero a default filter is enabled that * @note By setting this field to zero a default filter is enabled that
* allows all frames, this should be adequate for simple applications. * allows all frames, this should be adequate for simple applications.
*/ */
uint32_t cc_num; uint32_t cc_num;
/** /**
* @brief Pointer to an array of @p CANFilter structures. * @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 * @note This field can be set to @p NULL if the field @p cc_num is set to
* zero. * zero.
*/ */
const CANFilter *cc_filters; const CANFilter *cc_filters;
} CANConfig; } CANConfig;
/** /**
* @brief Structure representing an CAN driver. * @brief Structure representing an CAN driver.
*/ */
typedef struct { typedef struct {
/** /**
@ -246,12 +247,12 @@ typedef struct {
Semaphore cd_rxsem; Semaphore cd_rxsem;
/** /**
* @brief One or more frames become available. * @brief One or more frames become available.
* @note After broadcasting this event it will not be broadcasted again * @note After broadcasting this event it will not be broadcasted again
* until the received frames queue has been completely emptied. It * until the received frames queue has been completely emptied. It
* is <b>not</b> broadcasted for each received frame. It is * is <b>not</b> broadcasted for each received frame. It is
* responsibility of the application to empty the queue by repeatedly * responsibility of the application to empty the queue by repeatedly
* invoking @p chReceive() when listening to this event. This behavior * invoking @p chReceive() when listening to this event. This behavior
* minimizes the interrupt served by the system because CAN traffic. * minimizes the interrupt served by the system because CAN traffic.
*/ */
EventSource cd_rxfull_event; EventSource cd_rxfull_event;
/** /**

View File

@ -18,8 +18,9 @@
*/ */
/** /**
* @file STM32/pwm_lld.h * @file STM32/pwm_lld.h
* @brief STM32 PWM subsystem low level driver header. * @brief STM32 PWM subsystem low level driver header.
*
* @addtogroup STM32_PWM * @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 #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. * @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__) #if !defined(USE_STM32_PWM1) || defined(__DOXYGEN__)
#define USE_STM32_PWM1 TRUE #define USE_STM32_PWM1 TRUE
#endif #endif
/** /**
* @brief PWM2 driver enable switch. * @brief PWM2 driver enable switch.
* @details If set to @p TRUE the support for PWM2 is included. * @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__) #if !defined(USE_STM32_PWM2) || defined(__DOXYGEN__)
#define USE_STM32_PWM2 TRUE #define USE_STM32_PWM2 TRUE
#endif #endif
/** /**
* @brief PWM3 driver enable switch. * @brief PWM3 driver enable switch.
* @details If set to @p TRUE the support for PWM3 is included. * @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__) #if !defined(USE_STM32_PWM3) || defined(__DOXYGEN__)
#define USE_STM32_PWM3 TRUE #define USE_STM32_PWM3 TRUE
#endif #endif
/** /**
* @brief PWM4 driver enable switch. * @brief PWM4 driver enable switch.
* @details If set to @p TRUE the support for PWM4 is included. * @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__) #if !defined(USE_STM32_PWM4) || defined(__DOXYGEN__)
#define USE_STM32_PWM4 TRUE #define USE_STM32_PWM4 TRUE
#endif #endif
/** /**
* @brief PWM1 interrupt priority level setting. * @brief PWM1 interrupt priority level setting.
*/ */
#if !defined(STM32_PWM1_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_PWM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM1_IRQ_PRIORITY 7 #define STM32_PWM1_IRQ_PRIORITY 7
#endif #endif
/** /**
* @brief PWM2 interrupt priority level setting. * @brief PWM2 interrupt priority level setting.
*/ */
#if !defined(STM32_PWM2_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_PWM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM2_IRQ_PRIORITY 7 #define STM32_PWM2_IRQ_PRIORITY 7
#endif #endif
/** /**
* @brief PWM3 interrupt priority level setting. * @brief PWM3 interrupt priority level setting.
*/ */
#if !defined(STM32_PWM3_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_PWM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM3_IRQ_PRIORITY 7 #define STM32_PWM3_IRQ_PRIORITY 7
#endif #endif
/** /**
* @brief PWM4 interrupt priority level setting. * @brief PWM4 interrupt priority level setting.
*/ */
#if !defined(STM32_PWM4_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_PWM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_PWM4_IRQ_PRIORITY 7 #define STM32_PWM4_IRQ_PRIORITY 7
@ -119,18 +120,18 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief PWM channel type. * @brief PWM channel type.
*/ */
typedef uint8_t pwmchannel_t; typedef uint8_t pwmchannel_t;
/** /**
* @brief PWM counter type. * @brief PWM counter type.
*/ */
typedef uint16_t pwmcnt_t; typedef uint16_t pwmcnt_t;
/** /**
* @brief PWM driver channel configuration structure. * @brief PWM driver channel configuration structure.
* @note It could be empty on some architectures. * @note It could be empty on some architectures.
*/ */
typedef struct { typedef struct {
/** /**
@ -139,22 +140,22 @@ typedef struct {
pwmmode_t pcc_mode; pwmmode_t pcc_mode;
/** /**
* @brief Channel callback pointer. * @brief Channel callback pointer.
* @details This callback is invoked on the channel compare event. If set to * @note This callback is invoked on the channel compare event. If set to
* @p NULL then the callback is disabled. * @p NULL then the callback is disabled.
*/ */
pwmcallback_t pcc_callback; pwmcallback_t pcc_callback;
/* End of the mandatory fields.*/ /* End of the mandatory fields.*/
} PWMChannelConfig; } PWMChannelConfig;
/** /**
* @brief PWM driver configuration structure. * @brief PWM driver configuration structure.
* @note It could be empty on some architectures. * @note It could be empty on some architectures.
*/ */
typedef struct { typedef struct {
/** /**
* @brief Periodic callback pointer. * @brief Periodic callback pointer.
* @details This callback is invoked on PWM counter reset. If set to * @note This callback is invoked on PWM counter reset. If set to
* @p NULL then the callback is disabled. * @p NULL then the callback is disabled.
*/ */
pwmcallback_t pc_callback; pwmcallback_t pc_callback;
/** /**
@ -172,13 +173,13 @@ typedef struct {
uint16_t pc_arr; uint16_t pc_arr;
/** /**
* @brief TIM CR2 register initialization data. * @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; uint16_t pc_cr2;
} PWMConfig; } PWMConfig;
/** /**
* @brief Structure representing a PWM driver. * @brief Structure representing a PWM driver.
*/ */
typedef struct { typedef struct {
/** /**

View File

@ -131,7 +131,13 @@ typedef struct {
* value does not change frequently, it usually points to a peripheral * value does not change frequently, it usually points to a peripheral
* data register. * data register.
* @note Channels are numbered from 0 to 6, use the appropriate macro * @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) { \ #define dmaSetupChannel(dmap, ch, cndtr, cmar, ccr) { \
stm32_dma_channel_t *dmachp = &dmap->channels[ch]; \ stm32_dma_channel_t *dmachp = &dmap->channels[ch]; \
@ -142,11 +148,28 @@ typedef struct {
/** /**
* @brief DMA channel disable. * @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) { \ #define dmaDisableChannel(dmap, ch) { \
(dmap)->channels[ch].CCR = 0; \ (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); \
} }
/*===========================================================================*/ /*===========================================================================*/

View File

@ -47,6 +47,39 @@ UARTDriver UARTD1;
/* Driver local functions. */ /* Driver local functions. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @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. * @brief USART initialization.
* @details This function must be invoked with interrupts disabled. * @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->SR; /* SR reset step 1.*/
(void)u->DR; /* SR reset step 2.*/ (void)u->DR; /* SR reset step 2.*/
/* RX DMA channel preparation, circular 1 frame transfers, an interrupt is set_rx_idle(uartp);
generated for each received character.*/ set_tx_idle(uartp);
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);
} }
/** /**
* @brief USART de-initialization. * @brief USART de-initialization.
* @details This function must be invoked with interrupts disabled. * @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) { static void usart_stop(UARTDriver *uartp) {
/* Stops RX and TX DMA channels.*/ /* Stops RX and TX DMA channels.*/
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx); dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx); dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmatx);
dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx);
dmaClearChannel(uartp->ud_dmap, uartp->ud_dmatx);
/* Stops USART operations.*/ /* Stops USART operations.*/
uartp->ud_usart->CR1 = 0; uartp->ud_usart->CR1 = 0;
@ -109,11 +139,30 @@ static void usart_stop(UARTDriver *uartp) {
* @brief USART1 RX DMA interrupt handler (channel 4). * @brief USART1 RX DMA interrupt handler (channel 4).
*/ */
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) { CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
DMA1->IFCR |= DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 | dmaClearChannel(&DMA1, STM32_DMA_CHANNEL_4);
DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4;
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(); CH_IRQ_EPILOGUE();
} }
@ -125,17 +174,24 @@ CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
DMA1->IFCR |= DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 | dmaClearChannel(&DMA1, STM32_DMA_CHANNEL_5);
DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5;
/* 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_EPILOGUE();
} }
CH_IRQ_HANDLER(USART2_IRQHandler) { CH_IRQ_HANDLER(USART1_IRQHandler) {
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
serve_interrupt(&SD2);
CH_IRQ_EPILOGUE(); 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_dmarx].CPAR = (uint32_t)&uartp->ud_usart->DR;
uartp->ud_dmap->channels[uartp->ud_dmatx].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); usart_start(uartp);
} }

View File

@ -77,6 +77,25 @@
*/ */
typedef uint32_t uartflags_t; 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. * @brief Driver configuration structure.
* @note It could be empty on some architectures. * @note It could be empty on some architectures.
@ -89,9 +108,9 @@ typedef struct {
/** @brief Receive buffer filled callback.*/ /** @brief Receive buffer filled callback.*/
uartcb_t uc_rxend; uartcb_t uc_rxend;
/** @brief Character received while out if the @p UART_RECEIVE state.*/ /** @brief Character received while out if the @p UART_RECEIVE state.*/
uartcb_t uc_rxchar; uartccb_t uc_rxchar;
/** @brief Receive error callback.*/ /** @brief Receive error callback.*/
uartcb_t uc_rxerr; uartecb_t uc_rxerr;
/* End of the mandatory fields.*/ /* End of the mandatory fields.*/
/** @brief Bit rate.*/ /** @brief Bit rate.*/
uint32_t uc_speed; uint32_t uc_speed;