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;
|
__IO uint32_t SYNCCTRL;
|
||||||
} LPC_USART_Type;
|
} 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 -----
|
// ----- 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_HAS_USB TRUE
|
||||||
#define LPC_USB_IRQ_VECTOR Vector98
|
#define LPC_USB_IRQ_VECTOR Vector98
|
||||||
|
|
||||||
|
|
||||||
#define LPC_SSP0_IRQ_VECTOR Vector90
|
#define LPC_SSP0_IRQ_VECTOR Vector90
|
||||||
#define LPC_SSP1_IRQ_VECTOR Vector78
|
#define LPC_SSP1_IRQ_VECTOR Vector78
|
||||||
|
|
||||||
|
#define LPC_UART_IRQ_VECTOR Vector94
|
||||||
|
|
||||||
#endif
|
#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/GPIO/driver.mk
|
||||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/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/SPI/driver.mk
|
||||||
|
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/UART/driver.mk
|
||||||
|
|
||||||
# Shared variables
|
# Shared variables
|
||||||
ALLCSRC += $(PLATFORMSRC)
|
ALLCSRC += $(PLATFORMSRC)
|
||||||
|
|
Loading…
Reference in New Issue