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__) #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; UARTDriver *uartp;
CH_IRQ_PROLOGUE(); CH_IRQ_PROLOGUE();
uartp = &UARTD1; uartp = &UARTD1;
if ((STM32_DMA1->ISR & DMA_ISR_TEIF4) != 0) { if ((STM32_DMA1->ISR & DMA_ISR_TEIF5) != 0) {
STM32_UART_USART1_DMA_ERROR_HOOK(); STM32_UART_USART1_DMA_ERROR_HOOK();
} }
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
if (uartp->ud_rxstate == UART_RX_IDLE) { 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().*/ /* 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 /* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/ received character and then the driver stays in the same state.*/
@ -265,7 +265,8 @@ CH_IRQ_HANDLER(DMA1_Ch4_IRQHandler) {
else { else {
/* Receiver in active state, a callback is generated, if enabled, after /* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/ 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); 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(); 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(); STM32_UART_USART1_DMA_ERROR_HOOK();
} }
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_5); dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_5); dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_4);
serve_tx_end_irq(&UARTD1); serve_tx_end_irq(&UARTD1);
CH_IRQ_EPILOGUE(); CH_IRQ_EPILOGUE();
@ -315,8 +316,8 @@ CH_IRQ_HANDLER(DMA1_Ch6_IRQHandler) {
if ((STM32_DMA1->ISR & DMA_ISR_TEIF6) != 0) { if ((STM32_DMA1->ISR & DMA_ISR_TEIF6) != 0) {
STM32_UART_USART2_DMA_ERROR_HOOK(); STM32_UART_USART2_DMA_ERROR_HOOK();
} }
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
if (uartp->ud_rxstate == UART_RX_IDLE) { 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().*/ /* 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 /* Receiver in idle state, a callback is generated, if enabled, for each
received character and then the driver stays in the same state.*/ 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 /* Receiver in active state, a callback is generated, if enabled, after
a completed transfer.*/ a completed transfer.*/
dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_6); dmaDisableChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
dmaClearChannel(STM32_DMA1, STM32_DMA_CHANNEL_6);
serve_rx_end_irq(uartp); serve_rx_end_irq(uartp);
} }
@ -363,6 +365,68 @@ CH_IRQ_HANDLER(USART2_IRQHandler) {
} }
#endif /* STM32_UART_USE_USART2 */ #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. */ /* Driver exported functions. */
/*===========================================================================*/ /*===========================================================================*/
@ -378,8 +442,8 @@ void uart_lld_init(void) {
uartObjectInit(&UARTD1); uartObjectInit(&UARTD1);
UARTD1.ud_usart = USART1; UARTD1.ud_usart = USART1;
UARTD1.ud_dmap = STM32_DMA1; UARTD1.ud_dmap = STM32_DMA1;
UARTD1.ud_dmarx = STM32_DMA_CHANNEL_4; UARTD1.ud_dmarx = STM32_DMA_CHANNEL_5;
UARTD1.ud_dmatx = STM32_DMA_CHANNEL_5; UARTD1.ud_dmatx = STM32_DMA_CHANNEL_4;
UARTD1.ud_dmaccr = 0; UARTD1.ud_dmaccr = 0;
#endif #endif
@ -393,6 +457,17 @@ void uart_lld_init(void) {
UARTD2.ud_dmatx = STM32_DMA_CHANNEL_7; UARTD2.ud_dmatx = STM32_DMA_CHANNEL_7;
UARTD2.ud_dmaccr = 0; UARTD2.ud_dmaccr = 0;
#endif #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 #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, /* 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.*/ it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/
uartp->ud_dmaccr = STM32_UART_USART1_DMA_PRIORITY << 12; uartp->ud_dmaccr = STM32_UART_USART1_DMA_PRIORITY << 12;
@ -475,6 +563,17 @@ void uart_lld_stop(UARTDriver *uartp) {
return; return;
} }
#endif #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 uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
(void)uartp; /* Stopping previous activity (idle state).*/
(void)n; dmaDisableChannel(uartp->ud_dmap, uartp->ud_dmarx);
(void)rxbuf; 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 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 */ #endif /* CH_HAL_USE_UART */

View File

@ -79,6 +79,8 @@
- NEW: Centralized DMA macros in the STM32 HAL. - NEW: Centralized DMA macros in the STM32 HAL.
- NEW: New UART device driver model, this device driver allows unbuffered, - NEW: New UART device driver model, this device driver allows unbuffered,
callback driven access to UART-type devices. 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 - NEW: Added friendly interrupt vectors names to the STM32 HAL (change request
3023944). 3023944).
- NEW: Added support for SPI3 in the STM32 HAL. - NEW: Added support for SPI3 in the STM32 HAL.

View File

@ -20,7 +20,7 @@
#include "ch.h" #include "ch.h"
#include "hal.h" #include "hal.h"
static VirtualTimer vt; static VirtualTimer vt1, vt2;
static void restart(void *p) { static void restart(void *p) {
@ -28,31 +28,66 @@ static void restart(void *p) {
uartStartSend(&UARTD2, 14, "Hello World!\r\n"); 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) { static void txend2(void) {
palSetPad(IOPORT3, GPIOC_LED);
chSysLockFromIsr(); chSysLockFromIsr();
chVTSetI(&vt, MS2ST(1000), restart, NULL); chVTSetI(&vt1, MS2ST(5000), restart, NULL);
chSysUnlockFromIsr(); chSysUnlockFromIsr();
} }
/*
* This callback is invoked on a receive error, the errors mask is passed
* as parameter.
*/
static void rxerr(uartflags_t e) { static void rxerr(uartflags_t e) {
(void)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) { static void rxchar(uint16_t c) {
(void)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) { static void rxend(void) {
} }
/*
* UART driver configuration structure.
*/
static UARTConfig uart_cfg_1 = { static UARTConfig uart_cfg_1 = {
txend1, txend1,
txend2, txend2,
@ -65,22 +100,6 @@ static UARTConfig uart_cfg_1 = {
0 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 * Entry point, note, the main() function is already a thread in the system
* on entry. * on entry.
@ -95,11 +114,6 @@ int main(int argc, char **argv) {
*/ */
uartStart(&UARTD2, &uart_cfg_1); 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. * Starts the transmission, it will be handled entirely in background.
*/ */