UART + Serial Driver

This commit is contained in:
codetector 2020-12-03 22:31:21 -05:00
parent feb46948da
commit dae27fbf5f
No known key found for this signature in database
GPG Key ID: 7D42AB4D2C7B40A4
8 changed files with 876 additions and 1 deletions

View File

@ -200,6 +200,42 @@ typedef struct { /*!< (@ 0x40008000) USART Structure
__IO uint32_t SYNCCTRL;
} LPC_USART_Type;
#define USART_FCR_FIFOEN (1U << 0U)
#define USART_FCR_RX_RST (1U << 1U)
#define USART_FCR_TX_RST (1U << 2U)
#define USART_FCR_RXTL_POS (6U)
#define USART_FCR_RXTL_1B (0x0 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_4B (0x1 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_8B (0x2 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_14B (0x3 << USART_FCR_RXTL_POS)
#define USART_FCR_RXTL_MASK (0x3 << USART_FCR_RXTL_POS)
#define USART_LCR_WLS_POS (0U)
#define USART_LCR_WLS_5B (0x0U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_6B (0x1U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_7B (0x2U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_8B (0x3U << USART_LCR_WLS_POS)
#define USART_LCR_WLS_MASK (0x3U << USART_LCR_WLS_POS)
#define USART_LCR_SBS_POS (2U)
#define USART_LCR_SBS_1B (0U << USART_LCR_SBS_POS)
#define USART_LCR_SBS_2B (0U << USART_LCR_SBS_POS)
#define USART_LCR_SBS_MASK (0x1 << USART_LCR_SBS_POS)
#define USART_LCR_PE (1U << 3U)
#define USART_LCR_PS_POS (4U)
#define USART_LCR_PS_ODD (0x0U << USART_LCR_PS_POS)
#define USART_LCR_PS_EVEN (0x1U << USART_LCR_PS_POS)
#define USART_LCR_PS_F1 (0x2U << USART_LCR_PS_POS)
#define USART_LCR_PS_F0 (0x3U << USART_LCR_PS_POS)
#define USART_LCR_PS_MASK (0x3U << USART_LCR_PS_POS)
#define USART_LCR_DLAB (1U << 7U)
#define USART_LSR_RDR (1U << 0U)
#define USART_LSR_THRE (1U << 5U)
#define USART_TER_TXEN (1U << 7U)
#define USART_IER_RBRINTEN (1U << 0U) // Rx Has Data
#define USART_IER_THRINTEN (1U << 1U) // Tx Empty
// ------------------------------------------------------------------------------------------------
// ----- Timer -----

View File

@ -0,0 +1,4 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/hal_uart_lld.c \
$(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/hal_serial_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART

View File

@ -0,0 +1,208 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_serial_lld.c
* @brief LPC11Uxx serial subsystem low level driver source.
*
* @addtogroup SERIAL
* @{
*/
#include "hal.h"
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief USART1 serial driver identifier.*/
#if (LPC_SERIAL_USE_UART1 == TRUE) || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {
9600
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void load(SerialDriver *sdp) {
if (&SD1 == sdp) {
if (LPC_USART->LSR & USART_LSR_THRE) {
msg_t b;
osalSysLock();
b = oqGetI(&sdp->oqueue);
osalSysUnlock();
if (b >= MSG_OK) {
LPC_USART->THR = b;
}
}
LPC_USART->IER |= USART_IER_THRINTEN; // Enable Tx Empty
}
}
#if LPC_SERIAL_USE_UART1 == TRUE
static void notify1(io_queue_t *qp) {
(void)qp;
load(&SD1);
}
#endif
static void serial_interrupt(SerialDriver *sdp) {
if (LPC_USART->LSR & USART_LSR_RDR) {
// Rx Pending
osalSysLockFromISR();
if (iqIsEmptyI(&sdp->iqueue)) {
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
}
osalSysUnlockFromISR();
while(LPC_USART->LSR & USART_LSR_RDR) {
osalSysLockFromISR();
if (iqPutI(&sdp->iqueue, LPC_USART->RBR) < MSG_OK) {
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
}
osalSysUnlockFromISR();
}
}
if (LPC_USART->LSR & USART_LSR_THRE) {
msg_t b;
osalSysLockFromISR();
b = oqGetI(&sdp->oqueue);
osalSysUnlockFromISR();
if (b >= MSG_OK) {
LPC_USART->THR = b;
} else {
LPC_USART->IER &= ~USART_IER_THRINTEN;
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
}
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (LPC_SERIAL_USE_UART1 == TRUE) || defined(__DOXYGEN__)
CH_IRQ_HANDLER(LPC_UART_IRQ_VECTOR) {
CH_IRQ_PROLOGUE();
serial_interrupt(&SD1);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
#if LPC_SERIAL_USE_UART1 == TRUE
sdObjectInit(&SD1, NULL, notify1);
LPC_SYSCON->UARTCLKDIV = LPC_UART_PCLK_DIV; // Set Proper Clock Divider
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_USART; // Enable USART Clock
#endif
}
/**
* @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.
*
* @notapi
*/
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
if (config == NULL) {
config = &default_config;
}
if (sdp->state == SD_STOP) {
#if LPC_SERIAL_USE_UART1 == TRUE
if (&SD1 == sdp) {
// Disable Auto Baudrate. Not helpful
LPC_USART->ACR = 0;
LPC_USART->TER = USART_TER_TXEN;
/* Clock should be set to 16x baudrate */
uint16_t uart_div = (LPC_UART_PCLK_FREQUENCY / 16) / config->speed;
LPC_USART->LCR = USART_LCR_DLAB;
LPC_USART->DLL = (uint8_t)uart_div;
LPC_USART->DLM = (uint8_t)(uart_div >> 8);
// TODO: Support user configurable Parity and word length.
LPC_USART->LCR = USART_LCR_WLS_8B;
// FIFO Reset & Enable
LPC_USART->FCR = USART_FCR_FIFOEN | USART_FCR_TX_RST | USART_FCR_RX_RST |
USART_FCR_RXTL_1B;
#if !defined(LPC_UART_UART1_IRQ_PRIORITY)
#error "LPC_UART_UART1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(UART_IRQn, LPC_UART_UART1_IRQ_PRIORITY);
LPC_USART->IER = USART_IER_RBRINTEN;
}
#endif
}
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*
* @notapi
*/
void sd_lld_stop(SerialDriver *sdp) {
if (sdp->state == SD_READY) {
#if LPC_SERIAL_USE_UART1 == TRUE
if (&SD1 == sdp) {
nvicDisableVector(UART_IRQn);
LPC_USART->IER = 0;
}
#endif
}
}
#endif /* HAL_USE_SERIAL == TRUE */
/** @} */

View File

@ -0,0 +1,134 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_serial_lld.h
* @brief PLATFORM serial subsystem low level driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef HAL_SERIAL_LLD_H
#define HAL_SERIAL_LLD_H
#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name LPC Serial configuration options
* @{
*/
/**
* @brief UART1 driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define LPC_SERIAL_USE_UART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if LPC_SERIAL_USE_UART1 == TRUE
/**
* @brief UART PCLK DIVIDER setting.
* @details If this is not set, then we default to generate a PCLK as close to
* 1.8432MHz as possible. This is the standard clock to a 16550.
* The LPC UART is pretty much a 16550 if you look at the registers.
*/
#if !defined(LPC_UART_PCLK_DIV) || defined(__DOXYGEN__)
#define LPC_UART_PCLK_DIV (LPC_MAINCLK_FREQUENCY / 1843200)
#endif
#define LPC_UART_PCLK_FREQUENCY \
(LPC_MAINCLK_FREQUENCY / LPC_UART_PCLK_DIV)
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief PLATFORM 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 speed;
/* End of the mandatory fields.*/
} SerialConfig;
/**
* @brief @p SerialDriver specific data.
*/
#define _serial_driver_data \
_base_asynchronous_channel_data \
/* Driver state.*/ \
sdstate_t state; \
/* Input queue.*/ \
input_queue_t iqueue; \
/* Output queue.*/ \
output_queue_t oqueue; \
/* Input circular buffer.*/ \
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
/* Output circular buffer.*/ \
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
/* End of the mandatory fields.*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_SERIAL_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SERIAL == TRUE */
#endif /* HAL_SERIAL_LLD_H */
/** @} */

View File

@ -0,0 +1,276 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_uart_lld.c
* @brief LPC11Uxx UART subsystem low level driver source.
*
* @addtogroup UART
* @{
*/
#include "hal.h"
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief UART1 driver identifier.
*/
#if (LPC_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
UARTDriver UARTD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
#define uart_enter_rx_idle_loop(uartp) (void)uartp
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if LPC_UART_USE_UART1 == TRUE
#ifndef LPC_UART_IRQ_VECTOR
#error "LPC_UART_IRQ_VECTOR not defined"
#endif
OSAL_IRQ_HANDLER(LPC_UART_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
// UARTDriver *uartp = &UARTD1;
// // Pending Recieve
// while ((uartp->rx_cnt < uartp->rx_size) &&
// (LPC_USART->LSR & USART_LSR_RDR))
// {
// uint8_t tmp = LPC_USART->RBR;
// if (uartp->rxbuf != NULL) {
// uartp->rxbuf[uartp->rx_cnt] = tmp;
// }
// uartp->rx_cnt++;
// }
// if (uartp->rx_size > 0 && uartp->rx_cnt >= uartp->rx_size) {
// uartp->rx_cnt = 0;
// uartp->rx_size = 0;
// LPC_USART->IER &= ~USART_IER_RBRINTEN; // Disable Rx Interrupt
// _uart_rx_complete_isr_code(uartp);
// }
// // Check if a pending transimit
// while ((uartp->txbuf != NULL) && // have a buffer to Tx
// (uartp->tx_cnt < uartp->tx_size) && // More bytes needs to be sent
// (LPC_USART->LSR & USART_LSR_THRE)) // have space in buffer
// {
// LPC_USART->THR = uartp->txbuf[uartp->tx_cnt];
// uartp->tx_cnt++;
// }
// if (uartp->tx_size > 0 && uartp->tx_cnt >= uartp->tx_size) {
// uartp->tx_cnt = 0;
// uartp->tx_size = 0;
// uartp->txbuf = NULL;
// LPC_USART->IER &= ~USART_IER_THRINTEN; // Disable Tx Interrupt
// _uart_tx1_isr_code(uartp);
// }
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level UART driver initialization.
*
* @notapi
*/
void uart_lld_init(void) {
#if LPC_UART_USE_UART1 == TRUE
/* Driver initialization.*/
uartObjectInit(&UARTD1);
/* Initialize Clock */
LPC_SYSCON->UARTCLKDIV = LPC_UART_PCLK_DIV; // Set Proper Clock Divider
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_USART; // Enable USART Clock
#endif
}
/**
* @brief Configures and activates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
void uart_lld_start(UARTDriver *uartp) {
if (uartp->state == UART_STOP) {
/* Enables the peripheral.*/
#if LPC_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
// Disable Auto Baudrate. Not helpful
LPC_USART->ACR = 0;
LPC_USART->TER = USART_TER_TXEN;
/* Clock should be set to 16x baudrate */
uint16_t uart_div = (LPC_UART_PCLK_FREQUENCY / 16) / uartp->config->baudrate;
LPC_USART->LCR = USART_LCR_DLAB;
LPC_USART->DLL = (uint8_t)uart_div;
LPC_USART->DLM = (uint8_t)(uart_div >> 8);
// TODO: Support user configurable Parity and word length.
LPC_USART->LCR = USART_LCR_WLS_8B;
// FIFO Reset & Enable
LPC_USART->FCR = USART_FCR_FIFOEN | USART_FCR_TX_RST | USART_FCR_RX_RST |
USART_FCR_RXTL_1B;
#if !defined(LPC_UART_UART1_IRQ_PRIORITY)
#error "LPC_UART_UART1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(UART_IRQn, LPC_UART_UART1_IRQ_PRIORITY);
LPC_USART->IER = USART_IER_RBRINTEN;
}
#endif
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the UART peripheral.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @notapi
*/
void uart_lld_stop(UARTDriver *uartp) {
if (uartp->state == UART_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if LPC_UART_USE_UART1 == TRUE
if (&UARTD1 == uartp) {
LPC_USART->IER = 0;
nvicDisableVector(UART_IRQn);
}
#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
*
* @notapi
*/
void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
const uint8_t* buf = txbuf;
if (buf == NULL) {
return;
}
size_t i = 0;
while(n > 0) {
if(LPC_USART->LSR & USART_LSR_THRE) {
LPC_USART->THR = buf[i++];
n--;
}
}
}
/**
* @brief Stops any ongoing transmission.
* @note Stopping a transmission also suppresses the transmission callbacks.
*
* @param[in] uartp pointer to the @p UARTDriver object
*
* @return The number of data frames not transmitted by the
* stopped transmit operation.
*
* @notapi
*/
size_t uart_lld_stop_send(UARTDriver *uartp) {
(void)uartp;
return 0;
}
/**
* @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[out] rxbuf the pointer to the receive buffer
*
* @notapi
*/
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
const uint8_t* buf = rxbuf;
if (buf == NULL) {
return;
}
size_t i = 0;
while(n > 0) {
if(LPC_USART->LSR & USART_LSR_RDR) {
buf[i++] = LPC_USART->RBR;
n--;
}
}
}
/**
* @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
*
* @return The number of data frames not received by the
* stopped receive operation.
*
* @notapi
*/
size_t uart_lld_stop_receive(UARTDriver *uartp) {
(void)uartp;
return 0;
}
#endif /* HAL_USE_UART == TRUE */
/** @} */

View File

@ -0,0 +1,216 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_uart_lld.h
* @brief LPC11Uxx UART subsystem low level driver header.
*
* @addtogroup UART
* @{
*/
#ifndef HAL_UART_LLD_H
#define HAL_UART_LLD_H
#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name LPC11Uxx configuration options
* @{
*/
/**
* @brief UART driver enable switch.
* @details If set to @p TRUE the support for UART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_UART_USE_UART1) || defined(__DOXYGEN__)
#define LPC_UART_USE_UART1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/**
* @brief UART PCLK DIVIDER setting.
* @details If this is not set, then we default to generate a PCLK as close to
* 1.8432MHz as possible. This is the standard clock to a 16550.
* The LPC UART is pretty much a 16550 if you look at the registers.
*/
#if !defined(LPC_UART_PCLK_DIV) || defined(__DOXYGEN__)
#define LPC_UART_PCLK_DIV (LPC_MAINCLK_FREQUENCY / 1843200)
#endif
#define LPC_UART_PCLK_FREQUENCY \
(LPC_MAINCLK_FREQUENCY / LPC_UART_PCLK_DIV)
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief UART driver condition flags type.
*/
typedef uint32_t uartflags_t;
/**
* @brief Type of structure representing an UART driver.
*/
typedef struct UARTDriver UARTDriver;
/**
* @brief Generic UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object
*/
typedef void (*uartcb_t)(UARTDriver *uartp);
/**
* @brief Character received UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object triggering the
* callback
* @param[in] c received character
*/
typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
/**
* @brief Receive error UART notification callback type.
*
* @param[in] uartp pointer to the @p UARTDriver object triggering the
* callback
* @param[in] e receive error mask
*/
typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
/**
* @brief Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
/**
* @brief End of transmission buffer callback.
*/
uartcb_t txend1_cb;
/**
* @brief Physical end of transmission callback.
*/
uartcb_t txend2_cb;
/**
* @brief Receive buffer filled callback.
*/
uartcb_t rxend_cb;
/**
* @brief Character received while out of the @p UART_RECEIVE state.
*/
uartccb_t rxchar_cb;
/**
* @brief Receive error callback.
*/
uartecb_t rxerr_cb;
/* End of the mandatory fields.*/
uint32_t baudrate;
} UARTConfig;
/**
* @brief Structure representing an UART driver.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
struct UARTDriver {
/**
* @brief Driver state.
*/
uartstate_t state;
/**
* @brief Transmitter state.
*/
uarttxstate_t txstate;
/**
* @brief Receiver state.
*/
uartrxstate_t rxstate;
/**
* @brief Current configuration data.
*/
const UARTConfig *config;
#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Synchronization flag for transmit operations.
*/
bool early;
/**
* @brief Waiting thread on RX.
*/
thread_reference_t threadrx;
/**
* @brief Waiting thread on TX.
*/
thread_reference_t threadtx;
#endif /* UART_USE_WAIT */
#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* UART_USE_MUTUAL_EXCLUSION */
#if defined(UART_DRIVER_EXT_FIELDS)
UART_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_UART_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
extern UARTDriver UARTD1;
#endif
#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);
size_t uart_lld_stop_send(UARTDriver *uartp);
void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
size_t uart_lld_stop_receive(UARTDriver *uartp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_UART == TRUE */
#endif /* HAL_UART_LLD_H */
/** @} */

View File

@ -41,10 +41,10 @@ defined(__DOXYGEN__)
#define LPC_HAS_USB TRUE
#define LPC_USB_IRQ_VECTOR Vector98
#define LPC_SSP0_IRQ_VECTOR Vector90
#define LPC_SSP1_IRQ_VECTOR Vector78
#define LPC_UART_IRQ_VECTOR Vector94
#endif

View File

@ -10,6 +10,7 @@ include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/STM/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/SPI/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)