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

This commit is contained in:
gdisirio 2010-07-26 15:01:58 +00:00
parent d7e91ec701
commit 8c836a17ff
5 changed files with 521 additions and 89 deletions

View File

@ -18,8 +18,9 @@
*/ */
/** /**
* @file STM32/spi_lld.c * @file STM32/spi_lld.c
* @brief STM32 SPI subsystem low level driver source. * @brief STM32 SPI subsystem low level driver source.
*
* @addtogroup STM32_SPI * @addtogroup STM32_SPI
* @{ * @{
*/ */
@ -113,7 +114,7 @@ static void spi_start_wait(SPIDriver *spip, size_t n,
#if USE_STM32_SPI1 || defined(__DOXYGEN__) #if USE_STM32_SPI1 || defined(__DOXYGEN__)
/** /**
* @brief SPI1 RX DMA interrupt handler (channel 2). * @brief SPI1 RX DMA interrupt handler (channel 2).
*/ */
CH_IRQ_HANDLER(Vector70) { CH_IRQ_HANDLER(Vector70) {
@ -130,7 +131,7 @@ CH_IRQ_HANDLER(Vector70) {
} }
/** /**
* @brief SPI1 TX DMA interrupt handler (channel 3). * @brief SPI1 TX DMA interrupt handler (channel 3).
*/ */
CH_IRQ_HANDLER(Vector74) { CH_IRQ_HANDLER(Vector74) {
@ -146,7 +147,7 @@ CH_IRQ_HANDLER(Vector74) {
#if USE_STM32_SPI2 || defined(__DOXYGEN__) #if USE_STM32_SPI2 || defined(__DOXYGEN__)
/** /**
* @brief SPI2 RX DMA interrupt handler (channel 4). * @brief SPI2 RX DMA interrupt handler (channel 4).
*/ */
CH_IRQ_HANDLER(Vector78) { CH_IRQ_HANDLER(Vector78) {
@ -163,7 +164,7 @@ CH_IRQ_HANDLER(Vector78) {
} }
/** /**
* @brief SPI2 TX DMA interrupt handler (channel 5). * @brief SPI2 TX DMA interrupt handler (channel 5).
*/ */
CH_IRQ_HANDLER(Vector7C) { CH_IRQ_HANDLER(Vector7C) {
@ -179,7 +180,7 @@ CH_IRQ_HANDLER(Vector7C) {
#if USE_STM32_SPI3 || defined(__DOXYGEN__) #if USE_STM32_SPI3 || defined(__DOXYGEN__)
/** /**
* @brief SPI3 RX DMA interrupt handler (DMA2, channel 1). * @brief SPI3 RX DMA interrupt handler (DMA2, channel 1).
*/ */
CH_IRQ_HANDLER(Vector120) { CH_IRQ_HANDLER(Vector120) {
@ -196,7 +197,7 @@ CH_IRQ_HANDLER(Vector120) {
} }
/** /**
* @brief SPI3 TX DMA2 interrupt handler (DMA2, channel 2). * @brief SPI3 TX DMA2 interrupt handler (DMA2, channel 2).
*/ */
CH_IRQ_HANDLER(Vector124) { CH_IRQ_HANDLER(Vector124) {
@ -215,7 +216,7 @@ CH_IRQ_HANDLER(Vector124) {
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief Low level SPI driver initialization. * @brief Low level SPI driver initialization.
*/ */
void spi_lld_init(void) { void spi_lld_init(void) {
@ -256,7 +257,7 @@ void spi_lld_init(void) {
} }
/** /**
* @brief Configures and activates the SPI peripheral. * @brief Configures and activates the SPI peripheral.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
*/ */
@ -306,7 +307,7 @@ void spi_lld_start(SPIDriver *spip) {
} }
/** /**
* @brief Deactivates the SPI peripheral. * @brief Deactivates the SPI peripheral.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
*/ */
@ -342,7 +343,7 @@ void spi_lld_stop(SPIDriver *spip) {
} }
/** /**
* @brief Asserts the slave select signal and prepares for transfers. * @brief Asserts the slave select signal and prepares for transfers.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
*/ */
@ -352,7 +353,7 @@ void spi_lld_select(SPIDriver *spip) {
} }
/** /**
* @brief Deasserts the slave select signal. * @brief Deasserts the slave select signal.
* @details The previously selected peripheral is unselected. * @details The previously selected peripheral is unselected.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
@ -363,7 +364,7 @@ void spi_lld_unselect(SPIDriver *spip) {
} }
/** /**
* @brief Ignores data on the SPI bus. * @brief Ignores data on the SPI bus.
* @details This function transmits a series of idle words on the SPI bus and * @details This function transmits a series of idle words on the SPI bus and
* ignores the received data. This function can be invoked even * ignores the received data. This function can be invoked even
* when a slave select signal has not been yet asserted. * when a slave select signal has not been yet asserted.
@ -379,16 +380,15 @@ void spi_lld_ignore(SPIDriver *spip, size_t n) {
} }
/** /**
* @brief Exchanges data on the SPI bus. * @brief Exchanges data on the SPI bus.
* @details This function performs a simultaneous transmit/receive operation. * @details This function performs a simultaneous transmit/receive operation.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged * @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer * @param[in] txbuf the pointer to the transmit buffer
* @param[out] rxbuf the pointer to the receive buffer * @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/ */
void spi_lld_exchange(SPIDriver *spip, size_t n, void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) { const void *txbuf, void *rxbuf) {
@ -399,14 +399,13 @@ void spi_lld_exchange(SPIDriver *spip, size_t n,
} }
/** /**
* @brief Sends data ever the SPI bus. * @brief Sends data ever the SPI bus.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to send * @param[in] n number of words to send
* @param[in] txbuf the pointer to the transmit buffer * @param[in] txbuf the pointer to the transmit buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/ */
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
@ -416,14 +415,13 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
} }
/** /**
* @brief Receives data from the SPI bus. * @brief Receives data from the SPI bus.
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
* *
* @param[in] spip pointer to the @p SPIDriver object * @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to receive * @param[in] n number of words to receive
* @param[out] rxbuf the pointer to the receive buffer * @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/ */
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {

View File

@ -39,105 +39,105 @@
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief SPI1 driver enable switch. * @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SPI1 is included. * @details If set to @p TRUE the support for SPI1 is included.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(USE_STM32_SPI1) || defined(__DOXYGEN__) #if !defined(USE_STM32_SPI1) || defined(__DOXYGEN__)
#define USE_STM32_SPI1 TRUE #define USE_STM32_SPI1 TRUE
#endif #endif
/** /**
* @brief SPI2 driver enable switch. * @brief SPI2 driver enable switch.
* @details If set to @p TRUE the support for SPI2 is included. * @details If set to @p TRUE the support for SPI2 is included.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(USE_STM32_SPI2) || defined(__DOXYGEN__) #if !defined(USE_STM32_SPI2) || defined(__DOXYGEN__)
#define USE_STM32_SPI2 TRUE #define USE_STM32_SPI2 TRUE
#endif #endif
/** /**
* @brief SPI3 driver enable switch. * @brief SPI3 driver enable switch.
* @details If set to @p TRUE the support for SPI3 is included. * @details If set to @p TRUE the support for SPI3 is included.
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#if !defined(USE_STM32_SPI3) || defined(__DOXYGEN__) #if !defined(USE_STM32_SPI3) || defined(__DOXYGEN__)
#define USE_STM32_SPI3 FALSE #define USE_STM32_SPI3 FALSE
#endif #endif
/** /**
* @brief SPI1 DMA priority (0..3|lowest..highest). * @brief SPI1 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but * @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority * because of the channels ordering the RX channel has always priority
* over the TX channel. * over the TX channel.
*/ */
#if !defined(STM32_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI1_DMA_PRIORITY 2 #define STM32_SPI1_DMA_PRIORITY 2
#endif #endif
/** /**
* @brief SPI2 DMA priority (0..3|lowest..highest). * @brief SPI2 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but * @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority * because of the channels ordering the RX channel has always priority
* over the TX channel. * over the TX channel.
*/ */
#if !defined(STM32_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI2_DMA_PRIORITY 2 #define STM32_SPI2_DMA_PRIORITY 2
#endif #endif
/** /**
* @brief SPI3 DMA priority (0..3|lowest..highest). * @brief SPI3 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but * @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority * because of the channels ordering the RX channel has always priority
* over the TX channel. * over the TX channel.
*/ */
#if !defined(STM32_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI3_DMA_PRIORITY 2 #define STM32_SPI3_DMA_PRIORITY 2
#endif #endif
/** /**
* @brief SPI1 interrupt priority level setting. * @brief SPI1 interrupt priority level setting.
*/ */
#if !defined(STM32_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI1_IRQ_PRIORITY 10 #define STM32_SPI1_IRQ_PRIORITY 10
#endif #endif
/** /**
* @brief SPI2 interrupt priority level setting. * @brief SPI2 interrupt priority level setting.
*/ */
#if !defined(STM32_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI2_IRQ_PRIORITY 10 #define STM32_SPI2_IRQ_PRIORITY 10
#endif #endif
/** /**
* @brief SPI3 interrupt priority level setting. * @brief SPI3 interrupt priority level setting.
*/ */
#if !defined(STM32_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) #if !defined(STM32_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI3_IRQ_PRIORITY 10 #define STM32_SPI3_IRQ_PRIORITY 10
#endif #endif
/** /**
* @brief SPI1 DMA error hook. * @brief SPI1 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_SPI1_DMA_ERROR_HOOK) || defined(__DOXYGEN__) #if !defined(STM32_SPI1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt() #define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt()
#endif #endif
/** /**
* @brief SPI2 DMA error hook. * @brief SPI2 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_SPI2_DMA_ERROR_HOOK) || defined(__DOXYGEN__) #if !defined(STM32_SPI2_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI2_DMA_ERROR_HOOK() chSysHalt() #define STM32_SPI2_DMA_ERROR_HOOK() chSysHalt()
#endif #endif
/** /**
* @brief SPI3 DMA error hook. * @brief SPI3 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_SPI3_DMA_ERROR_HOOK) || defined(__DOXYGEN__) #if !defined(STM32_SPI3_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI3_DMA_ERROR_HOOK() chSysHalt() #define STM32_SPI3_DMA_ERROR_HOOK() chSysHalt()
@ -155,17 +155,11 @@
* @brief Driver configuration structure. * @brief Driver configuration structure.
*/ */
typedef struct { typedef struct {
/** /** @brief The chip select line port.*/
* @brief The chip select line port.
*/
ioportid_t spc_ssport; ioportid_t spc_ssport;
/** /** @brief The chip select line pad number.*/
* @brief The chip select line pad number.
*/
uint16_t spc_sspad; uint16_t spc_sspad;
/** /** @brief SPI initialization data.*/
* @brief SPI initialization data.
*/
uint16_t spc_cr1; uint16_t spc_cr1;
} SPIConfig; } SPIConfig;
@ -173,44 +167,28 @@ typedef struct {
* @brief Structure representing a SPI driver. * @brief Structure representing a SPI driver.
*/ */
typedef struct { typedef struct {
/** /** @brief Driver state.*/
* @brief Driver state.
*/
spistate_t spd_state; spistate_t spd_state;
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) #if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__) #if CH_USE_MUTEXES || defined(__DOXYGEN__)
/** /** @brief Mutex protecting the bus.*/
* @brief Mutex protecting the bus.
*/
Mutex spd_mutex; Mutex spd_mutex;
#elif CH_USE_SEMAPHORES #elif CH_USE_SEMAPHORES
Semaphore spd_semaphore; Semaphore spd_semaphore;
#endif #endif
#endif /* SPI_USE_MUTUAL_EXCLUSION */ #endif /* SPI_USE_MUTUAL_EXCLUSION */
/** /** @brief Current configuration data.*/
* @brief Current configuration data.
*/
const SPIConfig *spd_config; const SPIConfig *spd_config;
/* End of the mandatory fields.*/ /* End of the mandatory fields.*/
/** /** @brief Thread waiting for I/O completion.*/
* @brief Thread waiting for I/O completion.
*/
Thread *spd_thread; Thread *spd_thread;
/** /** @brief Pointer to the SPIx registers block.*/
* @brief Pointer to the SPIx registers block.
*/
SPI_TypeDef *spd_spi; SPI_TypeDef *spd_spi;
/** /** @brief Pointer to the receive DMA channel registers block.*/
* @brief Pointer to the receive DMA channel registers block.
*/
DMA_Channel_TypeDef *spd_dmarx; DMA_Channel_TypeDef *spd_dmarx;
/** /** @brief Pointer to the transmit DMA channel registers block.*/
* @brief Pointer to the transmit DMA channel registers block.
*/
DMA_Channel_TypeDef *spd_dmatx; DMA_Channel_TypeDef *spd_dmatx;
/** /** @brief DMA priority bit mask.*/
* @brief DMA priority bit mask.
*/
uint32_t spd_dmaprio; uint32_t spd_dmaprio;
} SPIDriver; } SPIDriver;

View File

@ -20,6 +20,8 @@
/** /**
* @file stm32_dma.h * @file stm32_dma.h
* @brief STM32 DMA helper driver header. * @brief STM32 DMA helper driver header.
* @note This file requires definitions from the ST STM32 header file
* stm3232f10x.h.
* *
* @addtogroup STM32_DMA * @addtogroup STM32_DMA
* @{ * @{
@ -52,10 +54,53 @@
/* Driver data structures and types. */ /* Driver data structures and types. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @brief STM32 DMA channel memory structure.
*/
typedef struct {
volatile uint32_t CCR;
volatile uint32_t CNDTR;
volatile uint32_t CPAR;
volatile uint32_t CMAR;
volatile uint32_t dummy;
} stm32_dma_channel_t;
/**
* @brief STM32 DMA subsystem memory structure.
* @note This structure has been redefined here because it is convenient to
* have the channels organized as an array, the ST header does not
* do that.
*/
typedef struct {
volatile uint32_t ISR;
volatile uint32_t IFCR;
stm32_dma_channel_t channels[7];
} stm32_dma_t:
/*===========================================================================*/ /*===========================================================================*/
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
#define STM32_DMA1_BASE (AHBPERIPH_BASE + 0x0000)
#define STM32_DMA1 ((stm32_dma_t *)STM32_DMA1_BASE)
#define STM32_DMA1_CH1 (STM32_DMA1->channels[0])
#define STM32_DMA1_CH2 (STM32_DMA1->channels[1])
#define STM32_DMA1_CH3 (STM32_DMA1->channels[2])
#define STM32_DMA1_CH4 (STM32_DMA1->channels[3])
#define STM32_DMA1_CH5 (STM32_DMA1->channels[4])
#define STM32_DMA1_CH6 (STM32_DMA1->channels[5])
#define STM32_DMA1_CH7 (STM32_DMA1->channels[6])
#if defined(STM32F10X_HD) || defined (STM32F10X_CL) || defined(__DOXYGEN__)
#define STM32_DMA2_BASE (AHBPERIPH_BASE + 0x0400)
#define STM32_DMA2 ((stm32_dma_t *)STM32_DMA2_BASE)
#define STM32_DMA2_CH1 (STM32_DMA2->channels[0])
#define STM32_DMA2_CH2 (STM32_DMA2->channels[1])
#define STM32_DMA2_CH3 (STM32_DMA2->channels[2])
#define STM32_DMA2_CH4 (STM32_DMA2->channels[3])
#define STM32_DMA2_CH5 (STM32_DMA2->channels[4])
#endif
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */ /* External declarations. */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -0,0 +1,248 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32/uart_lld.c
* @brief STM32 low level UART driver code.
*
* @addtogroup STM32_UART
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_UART || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART1 UART driver identifier.*/
#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
UARTDriver UARTD1;
#endif
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#define dma_setup(dmap, cndtr, cmar, ccr) { \
(dmap)->CNDTR = (uint32_t)(cndtr); \
(dmap)->CMAR = (uint32_t)(cmar); \
(dmap)->CCR = (uint32_t)(ccr); \
}
#define dma_disable(dmap) { \
(dmap)->CCR = 0; \
}
#define dma_rx_setup(uartp, cndtr, cmar, ccr) \
dma_setup((uartp)->ud_dmarx, (cndtr), (cmar), (uartp)->ud_dmaccr|(ccr))
#define dma_tx_setup(uartp, cndtr, cmar, ccr) { \
dma_setup((uartp)->ud_dmatx, (cndtr), (cmar), (uartp)->ud_dmaccr|(ccr))
/**
* @brief USART initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
static void usart_start(UARTDriver *uartp) {
USART_TypeDef *u = uartp->ud_usart;
/* Baud rate setting.*/
if (uartp->ud_usart == USART1)
u->BRR = STM32_PCLK2 / uartp->ud_config->uc_speed;
else
u->BRR = STM32_PCLK1 / uartp->ud_config->uc_speed;
/* Note that some bits are enforced because required for correct driver
operations.*/
u->CR1 = uartp->ud_config->uc_cr1 | USART_CR1_UE | USART_CR1_PEIE |
USART_CR1_TE | USART_CR1_RE;
u->CR2 = uartp->ud_config->uc_cr2 | USART_CR2_LBDIE;
u->CR3 = uartp->ud_config->uc_cr3 | USART_CR3_EIE;
(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.*/
dma_rx_setup(uartp, 1, &uartp->ud_rxbuf,
DMA_CCR1_TCIE | DMA_CCR1_TEIE | DMA_CCR1_CIRC | DMA_CCR1_EN);
/* TX DMA channel preparation, simply disabled.*/
dma_disable(uartp->ud_dmatx);
}
/**
* @brief USART de-initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] u pointer to an USART I/O block
*/
static void usart_stop(UARTDriver *uartp) {
/* Stops RX and TX DMA channels.*/
dma_disable(uartp->ud_dmarx);
dma_disable(uartp->ud_dmatx);
/* Stops USART operations.*/
uartp->ud_usart->CR1 = 0;
uartp->ud_usart->CR2 = 0;
uartp->ud_usart->CR3 = 0;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level UART driver initialization.
*/
void uart_lld_init(void) {
#if STM32_UART_USE_USART1
RCC->APB2RSTR = RCC_APB2RSTR_USART1RST;
RCC->APB2RSTR = 0;
uartObjectInit(&UARTD1);
UARTD1.ud_usart = USART1;
UARTD1.ud_dmarx = DMA1_Channel4;
UARTD1.ud_dmatx = DMA1_Channel5;
UARTD1.ud_dmaccr = 0;
UARTD1.ud_dmarmsk = 0xF << (4 - 1);
UARTD1.ud_dmatmsk = 0xF << (5 - 1);
#endif
}
/**
* @brief Configures and activates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
void uart_lld_start(UARTDriver *uartp) {
if (uartp->ud_state == UART_STOP) {
#if STM32_UART_USE_USART1
if (&UARTD1 == uartp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
NVICEnableVector(USART1_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART1_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel4_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART1_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel5_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART1_IRQ_PRIORITY));
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
}
#endif
/* Static DMA setup, the transfer size depends on the USART settings,
it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/
uartp->ud_dmaccr = STM32_UART_USART1_DMA_PRIORITY << 12;
if ((uartp->ud_config->uc_cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M)
uartp->ud_dmaccr |= DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0;
uartp->ud_dmarx->CPAR = (uint32_t)&uartp->ud_usart->DR;
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);
}
/**
* @brief Deactivates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
void uart_lld_stop(UARTDriver *uartp) {
if (uartp->ud_state == SD_READY) {
usart_stop(uartp);
#if STM32_UART_USE_USART1
if (&UARTD1 == uartp) {
NVICDisableVector(USART1_IRQn);
NVICDisableVector(DMA1_Channel4_IRQn);
NVICDisableVector(DMA1_Channel5_IRQn);
dmaDisable(DMA1_ID);
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
return;
}
#endif
}
}
/**
* @brief Starts a transmission on the UART peripheral.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[in] txbuf the pointer to the transmit buffer
*/
void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
}
/**
* @brief Stops any ongoing transmission.
* @note Stopping a transmission also suppresses the transmission callbacks.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
void uart_lld_stop_send(UARTDriver *uartp) {
}
/**
* @brief Starts a receive operation on the UART peripheral.
* @note The buffers are organized as uint8_t arrays for data sizes below
* or equal to 8 bits else it is organized as uint16_t arrays.
*
* @param[in] uartp pointer to the @p UARTDriver object
* @param[in] n number of data frames to send
* @param[in] rxbuf the pointer to the receive buffer
*/
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
}
/**
* @brief Stops any ongoing receive operation.
* @note Stopping a receive operation also suppresses the receive callbacks.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
void uart_lld_stop_receive(UARTDriver *uartp) {
}
#endif /* CH_HAL_USE_UART */
/** @} */

View File

@ -0,0 +1,163 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32/uart_lld.h
* @brief STM32 low level UART driver header.
*
* @addtogroup STM32_UART
* @{
*/
#ifndef _UART_LLD_H_
#define _UART_LLD_H_
#if CH_HAL_USE_UART || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief UART driver on USART1 enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__)
#define STM32_UART_USE_USART1 TRUE
#endif
/**
* @brief USART1 interrupt priority level setting.
*/
#if !defined(STM32_UART_USART1_IRQ_PRIO) || defined(__DOXYGEN__)
#define STM32_UART_USART1_IRQ_PRIORITY 12
#endif
/**
* @brief USART1 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority
* over the TX channel.
*/
#if !defined(STM32_UART_USART1_DMA_PRIO) || defined(__DOXYGEN__)
#define STM32_UART_USART1_DMA_PRIORITY 1
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief UART driver condition flags type.
*/
typedef uint32_t uartflags_t;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/** @brief End of transmission buffer callback.*/
uartcb_t uc_txend1;
/** @brief Physical end of transmission callback.*/
uartcb_t uc_txend2;
/** @brief Receive buffer filled callback.*/
uartcb_t uc_rxend;
/** @brief Character received while out if the @p UART_RECEIVE state.*/
uartcb_t uc_rxchar;
/** @brief Receive error callback.*/
uartcb_t uc_rxerr;
/* End of the mandatory fields.*/
/** @brief Bit rate.*/
uint32_t uc_speed;
/** @brief Initialization value for the CR1 register.*/
uint16_t uc_cr1;
/** @brief Initialization value for the CR2 register.*/
uint16_t uc_cr2;
/** @brief Initialization value for the CR3 register.*/
uint16_t uc_cr3;
} UARTConfig;
/**
* @brief Structure representing an UART driver.
*/
typedef struct {
/** @brief Driver state.*/
uartstate_t ud_state;
/** @brief Current configuration data.*/
const UARTConfig *ud_config;
/** @brief Transmitter state.*/
uarttxstate_t ud_txstate;
/** @brief Receiver state.*/
uartrxstate_t ud_rxstate;
/** @brief UART driver status flags.*/
uartflags_t ud_flags;
/* End of the mandatory fields.*/
/** @brief Default receive buffer while into @p UART_RX_IDLE state.*/
uint16_t ud_rxbuf;
/** @brief Pointer to the USART registers block.*/
USART_TypeDef *ud_usart;
/** @brief Pointer to the receive DMA channel registers block.*/
DMA_Channel_TypeDef *ud_dmarx;
/** @brief Receive DMA flags mask*/
uint32_t ud_dmarmsk;
/** @brief Pointer to the transmit DMA channel registers block.*/
DMA_Channel_TypeDef *ud_dmatx;
/** @brief Transmit DMA flags mask*/
uint32_t ud_dmatmsk;
/** @brief DMA priority bit mask.*/
uint32_t ud_dmaccr;
} UARTDriver;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void uart_lld_init(void);
void uart_lld_start(UARTDriver *uartp);
void uart_lld_stop(UARTDriver *uartp);
void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
void uart_lld_stop_send(UARTDriver *uartp);
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
void uart_lld_stop_receive(UARTDriver *uartp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_UART */
#endif /* _UART_LLD_H_ */
/** @} */