aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/TIVA
diff options
context:
space:
mode:
authormarcoveeneman <marco-veeneman@hotmail.com>2016-10-08 18:05:57 +0200
committermarcoveeneman <marco-veeneman@hotmail.com>2016-10-08 18:05:57 +0200
commitf8d62560b7e9f136f3d204e18cc321cdffc0ef80 (patch)
treee0fdb68a9e1d85e8ee96aef524e18ccca16dc3a7 /os/hal/ports/TIVA
parenteceaf26f2112fe7f09af03a51f159c927127457b (diff)
downloadChibiOS-Contrib-f8d62560b7e9f136f3d204e18cc321cdffc0ef80.tar.gz
ChibiOS-Contrib-f8d62560b7e9f136f3d204e18cc321cdffc0ef80.tar.bz2
ChibiOS-Contrib-f8d62560b7e9f136f3d204e18cc321cdffc0ef80.zip
Improve serial driver.
Diffstat (limited to 'os/hal/ports/TIVA')
-rw-r--r--os/hal/ports/TIVA/LLD/UART/hal_serial_lld.c121
-rw-r--r--os/hal/ports/TIVA/LLD/UART/hal_serial_lld.h22
2 files changed, 85 insertions, 58 deletions
diff --git a/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.c b/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.c
index 0ec960f..7203e74 100644
--- a/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.c
+++ b/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.c
@@ -34,58 +34,42 @@
/* Driver exported variables. */
/*===========================================================================*/
-/**
- * @brief UART0 serial driver identifier.
- */
+/** @brief UART0 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART0 || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
-/**
- * @brief UART1 serial driver identifier.
- */
+/** @brief UART1 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART1 || defined(__DOXYGEN__)
SerialDriver SD2;
#endif
-/**
- * @brief UART2 serial driver identifier.
- */
+/** @brief UART2 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART2 || defined(__DOXYGEN__)
SerialDriver SD3;
#endif
-/**
- * @brief UART3 serial driver identifier.
- */
+/** @brief UART3 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART3 || defined(__DOXYGEN__)
SerialDriver SD4;
#endif
-/**
- * @brief UART4 serial driver identifier.
- */
+/** @brief UART4 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART4 || defined(__DOXYGEN__)
SerialDriver SD5;
#endif
-/**
- * @brief UART5 serial driver identifier.
- */
+/** @brief UART5 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART5 || defined(__DOXYGEN__)
SerialDriver SD6;
#endif
-/**
- * @brief UART6 serial driver identifier.
- */
+/** @brief UART6 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART6 || defined(__DOXYGEN__)
SerialDriver SD7;
#endif
-/**
- * @brief UART7 serial driver identifier.
- */
+/** @brief UART7 serial driver identifier.*/
#if TIVA_SERIAL_USE_UART7 || defined(__DOXYGEN__)
SerialDriver SD8;
#endif
@@ -94,14 +78,14 @@ SerialDriver SD8;
/* Driver local variables. */
/*===========================================================================*/
-/**
- * @brief Driver default configuration.
- */
+/** @brief Driver default configuration.*/
static const SerialConfig sd_default_config =
{
SERIAL_DEFAULT_BITRATE,
- TIVA_LCRH_FEN | TIVA_LCRH_WLEN_8,
- TIVA_IFLS_TXIFLSEL_1_8_F | TIVA_IFLS_RXIFLSEL_1_8_E
+ 0,
+ UART_LCRH_FEN | UART_LCRH_WLEN_8,
+ UART_IFLS_TX4_8 | UART_IFLS_RX7_8,
+ UART_CC_CS_SYSCLK
};
/*===========================================================================*/
@@ -111,23 +95,55 @@ static const SerialConfig sd_default_config =
/**
* @brief UART initialization.
*
- * @param[in] sdp communication channel associated to the UART
+ * @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration
*/
static void uart_init(SerialDriver *sdp, const SerialConfig *config)
{
uint32_t u = sdp->uart;
- uint32_t div; /* baud rate divisor */
+ uint32_t brd;
+ uint32_t speed = config->speed;
+ uint32_t clock_source;
+
+ if (config->ctl & UART_CTL_HSE) {
+ /* High speed mode is enabled, half the baud rate to compensate
+ * for high speed mode.*/
+ speed = (speed + 1) / 2;
+ }
- /* disable the UART before any of the control registers are reprogrammed */
- HWREG(u + UART_O_CTL) &= ~TIVA_CTL_UARTEN;
- div = (((TIVA_SYSCLK * 8) / config->sc_speed) + 1) / 2;
- HWREG((u) + UART_O_IBRD) = div / 64; /* integer portion of the baud rate divisor */
- HWREG((u) + UART_O_FBRD) = div % 64; /* fractional portion of the baud rate divisor */
- HWREG((u) + UART_O_LCRH) = config->sc_lcrh; /* set data format */
- HWREG((u) + UART_O_IFLS) = config->sc_ifls;
- HWREG((u) + UART_O_CTL) |= TIVA_CTL_TXE | TIVA_CTL_RXE | TIVA_CTL_UARTEN;
- HWREG((u) + UART_O_IM) |= TIVA_IM_RXIM | TIVA_IM_TXIM | TIVA_IM_RTIM; /* interrupts enable */
+ if ((config->cc & UART_CC_CS_SYSCLK) == UART_CC_CS_SYSCLK) {
+ /* UART is clocked using the SYSCLK.*/
+ clock_source = TIVA_SYSCLK * 8;
+ }
+ else {
+ /* UART is clocked using the PIOSC.*/
+ clock_source = 16000000 * 8;
+ }
+
+ /* Calculate the baud rate divisor */
+ brd = ((clock_source / speed) + 1) / 2;
+
+ /* Disable UART.*/
+ HWREG(u + UART_O_CTL) &= ~UART_CTL_UARTEN;
+
+ /* Set baud rate.*/
+ HWREG(u + UART_O_IBRD) = brd / 64;
+ HWREG(u + UART_O_FBRD) = brd % 64;
+
+ /* Line control/*/
+ HWREG(u + UART_O_LCRH) = config->lcrh;
+
+ /* Select clock source.*/
+ HWREG(u + UART_O_CC) = config->cc & UART_CC_CS_M;
+
+ /* FIFO configuration.*/
+ HWREG(u + UART_O_IFLS) = config->ifls & (UART_IFLS_RX_M | UART_IFLS_TX_M);
+
+ /* Note that some bits are enforced.*/
+ HWREG(u + UART_O_CTL) = config->ctl | UART_CTL_RXE | UART_CTL_TXE | UART_CTL_UARTEN;
+
+ /* Enable interrupts.*/
+ HWREG(u + UART_O_IM) = TIVA_IM_RXIM | TIVA_IM_TXIM | TIVA_IM_RTIM;
}
/**
@@ -137,7 +153,7 @@ static void uart_init(SerialDriver *sdp, const SerialConfig *config)
*/
static void uart_deinit(uint32_t u)
{
- HWREG((u) + UART_O_CTL) &= ~TIVA_CTL_UARTEN;
+ HWREG(u + UART_O_CTL) &= ~TIVA_CTL_UARTEN;
}
/**
@@ -175,9 +191,9 @@ static void set_error(SerialDriver *sdp, uint16_t err)
static void serial_serve_interrupt(SerialDriver *sdp)
{
uint32_t u = sdp->uart;
- uint16_t mis = HWREG((u) + UART_O_MIS);
+ uint16_t mis = HWREG(u + UART_O_MIS);
- HWREG((u) + UART_O_ICR) = mis; /* clear interrupts */
+ HWREG(u + UART_O_ICR) = mis; /* clear interrupts */
if (mis & (TIVA_MIS_FEMIS | TIVA_MIS_PEMIS | TIVA_MIS_BEMIS | TIVA_MIS_OEMIS)) {
set_error(sdp, mis);
@@ -189,9 +205,9 @@ static void serial_serve_interrupt(SerialDriver *sdp)
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
}
osalSysUnlockFromISR();
- while ((HWREG((u) + UART_O_FR) & TIVA_FR_RXFE) == 0) {
+ while ((HWREG(u + UART_O_FR) & TIVA_FR_RXFE) == 0) {
osalSysLockFromISR();
- if (iqPutI(&sdp->iqueue, HWREG((u) + UART_O_DR)) < Q_OK) {
+ if (iqPutI(&sdp->iqueue, HWREG(u + UART_O_DR)) < Q_OK) {
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
}
osalSysUnlockFromISR();
@@ -199,19 +215,19 @@ static void serial_serve_interrupt(SerialDriver *sdp)
}
if (mis & TIVA_MIS_TXMIS) {
- while ((HWREG((u) + UART_O_FR) & TIVA_FR_TXFF) == 0) {
+ while ((HWREG(u + UART_O_FR) & TIVA_FR_TXFF) == 0) {
msg_t b;
osalSysLockFromISR();
b = oqGetI(&sdp->oqueue);
osalSysUnlockFromISR();
if (b < Q_OK) {
- HWREG((u) + UART_O_IM) &= ~TIVA_IM_TXIM;
+ HWREG(u + UART_O_IM) &= ~TIVA_IM_TXIM;
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
break;
}
- HWREG((u) + UART_O_DR) = b;
+ HWREG(u + UART_O_DR) = b;
}
}
}
@@ -223,15 +239,16 @@ static void fifo_load(SerialDriver *sdp)
{
uint32_t u = sdp->uart;
- while ((HWREG((u) + UART_O_FR) & TIVA_FR_TXFF) == 0) {
+ while ((HWREG(u + UART_O_FR) & TIVA_FR_TXFF) == 0) {
msg_t b = oqGetI(&sdp->oqueue);
if (b < Q_OK) {
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
return;
}
- HWREG((u) + UART_O_DR) = b;
+ HWREG(u + UART_O_DR) = b;
}
- HWREG((u) + UART_O_IM) |= TIVA_IM_TXIM; /* transmit interrupt enable */
+
+ HWREG(u + UART_O_IM) |= TIVA_IM_TXIM; /* transmit interrupt enable */
}
/**
@@ -577,7 +594,7 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config)
#endif
#if TIVA_SERIAL_USE_UART7
if (&SD8 == sdp) {
- HWREG)SYSCTL_RCGCUART) |= (1 << 7);
+ HWREG(SYSCTL_RCGCUART) |= (1 << 7);
while (!(HWREG(SYSCTL_PRUART) & (1 << 7)))
;
diff --git a/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.h b/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.h
index a6968cd..49239fb 100644
--- a/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.h
+++ b/os/hal/ports/TIVA/LLD/UART/hal_serial_lld.h
@@ -388,22 +388,32 @@
* @brief Tiva 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.
+ * @note This structure content is architecture dependent, each driver
+ * implementation defines its own version and the custom static
+ * initializers.
*/
typedef struct {
/**
* @brief Bit rate.
*/
- uint32_t sc_speed;
+ uint32_t speed;
/* End of the mandatory fields. */
/**
- * @brief Initialization value for the LCRH (Line Control) register.
+ * @brief Initialization value for the CTL register.
*/
- uint32_t sc_lcrh;
+ uint16_t ctl;
/**
- * @brief Initialization value for the IFLS (Interrupt FIFO Level Select)
- * register.
+ * @brief Initialization value for the LCRH register.
*/
- uint32_t sc_ifls;
+ uint8_t lcrh;
+ /**
+ * @brief Initialization value for the IFLS register.
+ */
+ uint8_t ifls;
+ /**
+ * @brief Initialization value for the CC register.
+ */
+ uint8_t cc;
} SerialConfig;
/**