aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/platforms/AT91SAM7
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-01-01 13:41:31 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2010-01-01 13:41:31 +0000
commitf8c40043e469d81f2a9f380d6723b92c79bd30bc (patch)
tree3611911703c617241bb91c00c48163f147e3b123 /os/hal/platforms/AT91SAM7
parent320a3f140e693a0d8647fd05ec6d2d4cb10c523a (diff)
downloadChibiOS-f8c40043e469d81f2a9f380d6723b92c79bd30bc.tar.gz
ChibiOS-f8c40043e469d81f2a9f380d6723b92c79bd30bc.tar.bz2
ChibiOS-f8c40043e469d81f2a9f380d6723b92c79bd30bc.zip
Serial driver enhancements for STM32 and AT91SAM7.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1485 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/platforms/AT91SAM7')
-rw-r--r--os/hal/platforms/AT91SAM7/serial_lld.c122
-rw-r--r--os/hal/platforms/AT91SAM7/serial_lld.h81
2 files changed, 110 insertions, 93 deletions
diff --git a/os/hal/platforms/AT91SAM7/serial_lld.c b/os/hal/platforms/AT91SAM7/serial_lld.c
index be28045fc..8fac96e33 100644
--- a/os/hal/platforms/AT91SAM7/serial_lld.c
+++ b/os/hal/platforms/AT91SAM7/serial_lld.c
@@ -66,7 +66,7 @@ SerialDriver SD2;
/*===========================================================================*/
/** @brief Driver default configuration.*/
-static const SerialDriverConfig default_config = {
+static const SerialConfig default_config = {
38400,
AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK |
AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT
@@ -78,21 +78,22 @@ static const SerialDriverConfig default_config = {
/**
* @brief USART initialization.
- * @param[in] u pointer to an USART I/O block
- * @param[in] config the architecture-dependent serial driver configuration
+ *
+ * @param[in] sdp communication channel associated to the USART
*/
-static void usart_init(AT91PS_USART u, const SerialDriverConfig *config) {
+static void usart_init(SerialDriver *sdp) {
+ AT91PS_USART u = sdp->sd.usart;
/* Disables IRQ sources and stop operations.*/
u->US_IDR = 0xFFFFFFFF;
u->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
/* New parameters setup.*/
- if (config->mr & AT91C_US_OVER)
- u->US_BRGR = MCK / (config->speed * 8);
+ if (sdp->sd.config->sc_mr & AT91C_US_OVER)
+ u->US_BRGR = MCK / (sdp->sd.config->sc_speed * 8);
else
- u->US_BRGR = MCK / (config->speed * 16);
- u->US_MR = config->mr;
+ u->US_BRGR = MCK / (sdp->sd.config->sc_speed * 16);
+ u->US_MR = sdp->sd.config->sc_mr;
u->US_RTOR = 0;
u->US_TTGR = 0;
@@ -121,7 +122,7 @@ static void usart_deinit(AT91PS_USART u) {
* @param[in] err USART CSR register value
* @param[in] sdp communication channel associated to the USART
*/
-static void set_error(AT91_REG csr, SerialDriver *sdp) {
+static void set_error(SerialDriver *sdp, AT91_REG csr) {
sdflags_t sts = 0;
if (csr & AT91C_US_OVRE)
@@ -142,27 +143,35 @@ __attribute__((noinline))
#endif
/**
* @brief Common IRQ handler.
- * @param[in] u pointer to an USART I/O block
- * @param[in] com communication channel associated to the USART
+ *
+ * @param[in] sdp communication channel associated to the USART
*/
-static void serve_interrupt(AT91PS_USART u, SerialDriver *sdp) {
+static void serve_interrupt(SerialDriver *sdp) {
+ uint32_t csr;
+ AT91PS_USART u = sdp->sd.usart;
- if (u->US_CSR & AT91C_US_RXRDY) {
+ csr = u->US_CSR;
+ if (csr & AT91C_US_RXRDY) {
chSysLockFromIsr();
sdIncomingDataI(sdp, u->US_RHR);
chSysUnlockFromIsr();
}
- if (u->US_CSR & AT91C_US_TXRDY) {
+ if ((u->US_IMR & AT91C_US_TXRDY) && (csr & AT91C_US_TXRDY)) {
+ msg_t b;
+
chSysLockFromIsr();
- msg_t b = sdRequestDataI(sdp);
- chSysUnlockFromIsr();
- if (b < Q_OK)
+ b = chOQGetI(&sdp->sd.oqueue);
+ if (b < Q_OK) {
+ chEvtBroadcastI(&sdp->bac.oevent);
u->US_IDR = AT91C_US_TXRDY;
+ }
else
u->US_THR = b;
+ chSysUnlockFromIsr();
}
- if (u->US_CSR & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK)) {
- set_error(u->US_CSR, sdp);
+ csr &= (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK);
+ if (csr != 0) {
+ set_error(sdp, csr);
u->US_CR = AT91C_US_RSTSTA;
}
AT91C_BASE_AIC->AIC_EOICR = 0;
@@ -191,7 +200,7 @@ CH_IRQ_HANDLER(USART0IrqHandler) {
CH_IRQ_PROLOGUE();
- serve_interrupt(AT91C_BASE_US0, &SD1);
+ serve_interrupt(&SD1);
CH_IRQ_EPILOGUE();
}
@@ -202,7 +211,7 @@ CH_IRQ_HANDLER(USART1IrqHandler) {
CH_IRQ_PROLOGUE();
- serve_interrupt(AT91C_BASE_US1, &SD2);
+ serve_interrupt(&SD2);
CH_IRQ_EPILOGUE();
}
@@ -219,6 +228,7 @@ void sd_lld_init(void) {
#if USE_SAM7_USART0
sdObjectInit(&SD1, NULL, notify1);
+ SD1.sd.usart = AT91C_BASE_US0;
AT91C_BASE_PIOA->PIO_PDR = SAM7_USART0_RX | SAM7_USART0_TX;
AT91C_BASE_PIOA->PIO_ASR = SAM7_USART0_RX | SAM7_USART0_TX;
AT91C_BASE_PIOA->PIO_PPUDR = SAM7_USART0_RX | SAM7_USART0_TX;
@@ -229,6 +239,7 @@ void sd_lld_init(void) {
#if USE_SAM7_USART1
sdObjectInit(&SD2, NULL, notify2);
+ SD2.sd.usart = AT91C_BASE_US1;
AT91C_BASE_PIOA->PIO_PDR = SAM7_USART1_RX | SAM7_USART1_TX;
AT91C_BASE_PIOA->PIO_ASR = SAM7_USART1_RX | SAM7_USART1_TX;
AT91C_BASE_PIOA->PIO_PPUDR = SAM7_USART1_RX | SAM7_USART1_TX;
@@ -242,37 +253,33 @@ void sd_lld_init(void) {
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
- * @param[in] config the architecture-dependent serial driver configuration.
- * If this parameter is set to @p NULL then a default
- * configuration is used.
*/
-void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
+void sd_lld_start(SerialDriver *sdp) {
- if (config == NULL)
- config = &default_config;
+ if (sdp->sd.config == NULL)
+ sdp->sd.config = &default_config;
+ if (sdp->sd.state == SD_STOP) {
#if USE_SAM7_USART0
- if (&SD1 == sdp) {
- /* Starts the clock and clears possible sources of immediate interrupts.*/
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0);
- /* USART initialization.*/
- usart_init(AT91C_BASE_US0, config);
- /* Enables associated interrupt vector.*/
- AIC_EnableIT(AT91C_ID_US0);
- return;
- }
+ if (&SD1 == sdp) {
+ /* Starts the clock and clears possible sources of immediate interrupts.*/
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0);
+ /* Enables associated interrupt vector.*/
+ AIC_EnableIT(AT91C_ID_US0);
+ return;
+ }
#endif
#if USE_SAM7_USART1
- if (&SD2 == sdp) {
- /* Starts the clock and clears possible sources of immediate interrupts.*/
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
- /* USART initialization.*/
- usart_init(AT91C_BASE_US1, config);
- /* Enables associated interrupt vector.*/
- AIC_EnableIT(AT91C_ID_US1);
- return;
- }
+ if (&SD2 == sdp) {
+ /* Starts the clock and clears possible sources of immediate interrupts.*/
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
+ /* Enables associated interrupt vector.*/
+ AIC_EnableIT(AT91C_ID_US1);
+ return;
+ }
#endif
+ }
+ usart_init(sdp);
}
/**
@@ -284,22 +291,23 @@ void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
*/
void sd_lld_stop(SerialDriver *sdp) {
+ if (sdp->sd.state == SD_READY) {
+ usart_deinit(sdp->sd.usart);
#if USE_SAM7_USART0
- if (&SD1 == sdp) {
- usart_deinit(AT91C_BASE_US0);
- AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US0);
- AIC_DisableIT(AT91C_ID_US0);
- return;
- }
+ if (&SD1 == sdp) {
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US0);
+ AIC_DisableIT(AT91C_ID_US0);
+ return;
+ }
#endif
#if USE_SAM7_USART1
- if (&SD2 == sdp) {
- usart_deinit(AT91C_BASE_US1);
- AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US1);
- AIC_DisableIT(AT91C_ID_US1);
- return;
- }
+ if (&SD2 == sdp) {
+ AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US1);
+ AIC_DisableIT(AT91C_ID_US1);
+ return;
+ }
#endif
+ }
}
#endif /* CH_HAL_USE_SERIAL */
diff --git a/os/hal/platforms/AT91SAM7/serial_lld.h b/os/hal/platforms/AT91SAM7/serial_lld.h
index b5394aeed..7b7deba95 100644
--- a/os/hal/platforms/AT91SAM7/serial_lld.h
+++ b/os/hal/platforms/AT91SAM7/serial_lld.h
@@ -38,16 +38,6 @@
/*===========================================================================*/
/**
- * @brief Serial buffers size.
- * @details Configuration parameter, you can change the depth of the queue
- * buffers depending on the requirements of your application.
- * @note The default is 128 bytes for both the transmission and receive buffers.
- */
-#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
-#define SERIAL_BUFFERS_SIZE 128
-#endif
-
-/**
* @brief UART0 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p TRUE.
@@ -93,48 +83,67 @@
typedef uint32_t sdflags_t;
/**
+ * @brief AT91SAM7 Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ */
+typedef struct {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t sc_speed;
+ /**
+ * @brief Initialization value for the MR register.
+ */
+ uint32_t sc_mr;
+} SerialConfig;
+
+/**
* @brief @p SerialDriver specific data.
*/
struct _serial_driver_data {
/**
- * Input queue, incoming data can be read from this input queue by
- * using the queues APIs.
+ * @brief Driver state.
+ */
+ sdstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const SerialConfig *config;
+ /**
+ * @brief Input queue, incoming data can be read from this input queue by
+ * using the queues APIs.
+ */
+ InputQueue iqueue;
+ /**
+ * @brief Output queue, outgoing data can be written to this output queue by
+ * using the queues APIs.
*/
- InputQueue iqueue;
+ OutputQueue oqueue;
/**
- * Output queue, outgoing data can be written to this output queue by
- * using the queues APIs.
+ * @brief Status Change @p EventSource. This event is generated when one or
+ * more condition flags change.
*/
- OutputQueue oqueue;
+ EventSource sevent;
/**
- * Status Change @p EventSource. This event is generated when one or more
- * condition flags change.
+ * @brief I/O driver status flags.
*/
- EventSource sevent;
+ sdflags_t flags;
/**
- * I/O driver status flags.
+ * @brief Input circular buffer.
*/
- sdflags_t flags;
+ uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
- * Input circular buffer.
+ * @brief Output circular buffer.
*/
- uint8_t ib[SERIAL_BUFFERS_SIZE];
+ uint8_t ob[SERIAL_BUFFERS_SIZE];
+ /* End of the mandatory fields.*/
/**
- * Output circular buffer.
+ * @brief Pointer to the USART registers block.
*/
- uint8_t ob[SERIAL_BUFFERS_SIZE];
+ AT91PS_USART usart;
};
-/**
- * @brief AT91SAM7 Serial Driver configuration structure.
- * @details An instance of this structure must be passed to @p sdStart()
- * in order to configure and start a serial driver operations.
- */
-typedef struct {
- uint32_t speed;
- uint32_t mr;
-} SerialDriverConfig;
-
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
@@ -155,7 +164,7 @@ extern SerialDriver SD2;
extern "C" {
#endif
void sd_lld_init(void);
- void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
+ void sd_lld_start(SerialDriver *sdp);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}