UART + Serial Driver
This commit is contained in:
parent
feb46948da
commit
dae27fbf5f
|
@ -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 -----
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue