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

This commit is contained in:
gdisirio 2010-08-01 08:53:54 +00:00
parent 76d2dd6f45
commit a927edc984
3 changed files with 164 additions and 41 deletions

View File

@ -243,19 +243,19 @@ static void serve_usart_irq(UARTDriver *uartp) {
#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
/**
* @brief USART1 RX DMA interrupt handler (channel 4).
* @brief USART1 RX DMA interrupt handler (channel 5).
*/
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE();
uartp = &UARTD1;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) {
if ((STM32_DMA1->ISR & DMA_ISR_TEIF5) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
if (uartp->ud_rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
@ -265,7 +265,8 @@ CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
else {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
serve_rx_end_irq(uartp);
}
@ -273,17 +274,17 @@ CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
}
/**
* @brief USART1 TX DMA interrupt handler (channel 5).
* @brief USART1 TX DMA interrupt handler (channel 4).
*/
CH_IRQ_HANDLER(DMA1_Ch5_IRQHandler) {
CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF5) != 0) {
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_5);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
serve_tx_end_irq(&UARTD1);
CH_IRQ_EPILOGUE();
@ -315,8 +316,8 @@ CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
if ((STM32_DMA1->ISR & DMA_ISR_TEIF6) != 0) {
STM32_UART_USART2_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
if (uartp->ud_rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
@ -327,6 +328,7 @@ CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
/* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
serve_rx_end_irq(uartp);
}
@ -363,6 +365,68 @@ CH_IRQ_HANDLER(USART2_IRQHandler) {
}
#endif /* STM32_UART_USE_USART2 */
#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
/**
* @brief USART3 RX DMA interrupt handler (channel 3).
*/
CH_IRQ_HANDLER(DMA1_Ch3_IRQHandler) {
UARTDriver *uartp;
CH_IRQ_PROLOGUE();
uartp = &UARTD3;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF3) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
if (uartp->ud_rxstate == UART_RX_IDLE) {
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
/* Fast IRQ path, this is why it is not centralized in serve_rx_end_irq().*/
/* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/
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.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_3);
serve_rx_end_irq(uartp);
}
CH_IRQ_EPILOGUE();
}
/**
* @brief USART3 TX DMA interrupt handler (channel 2).
*/
CH_IRQ_HANDLER(DMA1_Ch2_IRQHandler) {
CH_IRQ_PROLOGUE();
if ((STM32_DMA1->ISR & DMA_ISR_TEIF2) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK();
}
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_2);
serve_tx_end_irq(&UARTD3);
CH_IRQ_EPILOGUE();
}
/**
* @brief USART3 IRQ handler.
*/
CH_IRQ_HANDLER(USART3_IRQHandler) {
CH_IRQ_PROLOGUE();
serve_usart_irq(&UARTD3);
CH_IRQ_EPILOGUE();
}
#endif /* STM32_UART_USE_USART3 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -378,8 +442,8 @@ void uart_lld_init(void) {
uartObjectInit(&UARTD1);
UARTD1.ud_usart = USART1;
UARTD1.ud_dmap = STM32_DMA1;
UARTD1.ud_dmarx = STM32_DMA_CHANNEL_4;
UARTD1.ud_dmatx = STM32_DMA_CHANNEL_5;
UARTD1.ud_dmarx = STM32_DMA_CHANNEL_5;
UARTD1.ud_dmatx = STM32_DMA_CHANNEL_4;
UARTD1.ud_dmaccr = 0;
#endif
@ -393,6 +457,17 @@ void uart_lld_init(void) {
UARTD2.ud_dmatx = STM32_DMA_CHANNEL_7;
UARTD2.ud_dmaccr = 0;
#endif
#if STM32_UART_USE_USART3
RCC->APB1RSTR = RCC_APB1RSTR_USART3RST;
RCC->APB1RSTR = 0;
uartObjectInit(&UARTD3);
UARTD2.ud_usart = USART3;
UARTD2.ud_dmap = STM32_DMA1;
UARTD2.ud_dmarx = STM32_DMA_CHANNEL_3;
UARTD2.ud_dmatx = STM32_DMA_CHANNEL_2;
UARTD2.ud_dmaccr = 0;
#endif
}
/**
@ -429,6 +504,19 @@ void uart_lld_start(UARTDriver *uartp) {
}
#endif
#if STM32_UART_USE_USART3
if (&UARTD3 == uartp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
NVICEnableVector(USART3_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART3_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel2_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART3_IRQ_PRIORITY));
NVICEnableVector(DMA1_Channel3_IRQn,
CORTEX_PRIORITY_MASK(STM32_UART_USART3_IRQ_PRIORITY));
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
}
#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;
@ -475,6 +563,17 @@ void uart_lld_stop(UARTDriver *uartp) {
return;
}
#endif
#if STM32_UART_USE_USART3
if (&UARTD3 == uartp) {
NVICDisableVector(USART3_IRQn);
NVICDisableVector(DMA1_Channel2_IRQn);
NVICDisableVector(DMA1_Channel3_IRQn);
dmaDisable(DMA1_ID);
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN;
return;
}
#endif
}
}
@ -519,9 +618,15 @@ void uart_lld_stop_send(UARTDriver *uartp) {
*/
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
(void)uartp;
(void)n;
(void)rxbuf;
/* Stopping previous activity (idle state).*/
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx);
/* RX DMA channel preparation and start.*/
dmaSetupChannel(uartp->ud_dmap, uartp->ud_dmarx, n, rxbuf,
uartp->ud_dmaccr | DMA_CCR1_MINC |
DMA_CCR1_TEIE | DMA_CCR1_TCIE);
dmaEnableChannel(uartp->ud_dmap, uartp->ud_dmarx);
}
/**
@ -532,7 +637,9 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
*/
void uart_lld_stop_receive(UARTDriver *uartp) {
(void)uartp;
dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
dmaClearChannel(uartp->ud_dmap, uartp->ud_dmarx);
set_rx_idle_loop(uartp);
}
#endif /* CH_HAL_USE_UART */

View File

@ -79,6 +79,8 @@
- NEW: Centralized DMA macros in the STM32 HAL.
- NEW: New UART device driver model, this device driver allows unbuffered,
callback driven access to UART-type devices.
- NEW: UART device driver for STM32 and UART demo application under
./testhal/STM32/UART.
- NEW: Added friendly interrupt vectors names to the STM32 HAL (change request
3023944).
- NEW: Added support for SPI3 in the STM32 HAL.

View File

@ -20,7 +20,7 @@
#include "ch.h"
#include "hal.h"
static VirtualTimer vt;
static VirtualTimer vt1, vt2;
static void restart(void *p) {
@ -28,31 +28,66 @@ static void restart(void *p) {
uartStartSend(&UARTD2, 14, "Hello World!\r\n");
}
static void txend1(void) {
static void ledoff(void *p) {
(void)p;
palSetPad(IOPORT3, GPIOC_LED);
}
/*
* This callback is invoked when a transmission buffer has been completely
* read by the driver.
*/
static void txend1(void) {
palClearPad(IOPORT3, GPIOC_LED);
}
/*
* This callback is invoked when a transmission has phisically completed.
*/
static void txend2(void) {
palSetPad(IOPORT3, GPIOC_LED);
chSysLockFromIsr();
chVTSetI(&vt, MS2ST(1000), restart, NULL);
chVTSetI(&vt1, MS2ST(5000), restart, NULL);
chSysUnlockFromIsr();
}
/*
* This callback is invoked on a receive error, the errors mask is passed
* as parameter.
*/
static void rxerr(uartflags_t e) {
(void)e;
}
/*
* This callback is invoked when a character is received but the application
* was not ready to receive it, the character is passed as parameter.
*/
static void rxchar(uint16_t c) {
(void)c;
/* Flashing the LED each time a character is received.*/
palClearPad(IOPORT3, GPIOC_LED);
chSysLockFromIsr();
if (!chVTIsArmedI(&vt2))
chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
chSysUnlockFromIsr();
}
/*
* This callback is invoked when a receive buffer has been completely written.
*/
static void rxend(void) {
}
/*
* UART driver configuration structure.
*/
static UARTConfig uart_cfg_1 = {
txend1,
txend2,
@ -65,22 +100,6 @@ static UARTConfig uart_cfg_1 = {
0
};
/*
* Red LEDs blinker thread, times are in milliseconds.
*/
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {
(void)arg;
while (TRUE) {
palClearPad(IOPORT3, GPIOC_LED);
chThdSleepMilliseconds(500);
palSetPad(IOPORT3, GPIOC_LED);
chThdSleepMilliseconds(500);
}
return 0;
}
/*
* Entry point, note, the main() function is already a thread in the system
* on entry.
@ -95,11 +114,6 @@ int main(int argc, char **argv) {
*/
uartStart(&UARTD2, &uart_cfg_1);
/*
* Creates the blinker thread.
*/
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
/*
* Starts the transmission, it will be handled entirely in background.
*/