MIMXRT1062/LLD/UARTv1: implement hal_serial_lld for MIMXRT1062

This commit is contained in:
Michael Stapelberg 2021-03-26 11:05:45 +01:00
parent b8a449cb51
commit b11181c154
4 changed files with 198 additions and 453 deletions

View File

@ -401,7 +401,7 @@
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#define SERIAL_DEFAULT_BITRATE 115200
#endif
/**

View File

@ -1,9 +1,16 @@
UARTSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1/hal_serial_lld.c \
${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpuart/fsl_lpuart.c \
${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1062/drivers/fsl_clock.c
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1/hal_serial_lld.c
PLATFORMSRC_CONTRIB += $(UARTSRC)
endif
else
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1/hal_serial_lld.c
PLATFORMSRC_CONTRIB += $(UARTSRC)
endif
PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1
PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1 \
${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/common \
${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpuart \
${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1062

View File

@ -26,6 +26,13 @@
#include "osal.h"
#include "hal.h"
#include "fsl_lpuart.h"
#define printf_init()
#define printf(...)
#define printf_debug_init()
#define printf_debug(...)
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
/*===========================================================================*/
@ -39,27 +46,27 @@
/**
* @brief SD1 driver identifier.
*/
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART0 || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART1 || defined(__DOXYGEN__)
SerialDriver SD2;
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART2 || defined(__DOXYGEN__)
SerialDriver SD3;
#endif
#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART3 || defined(__DOXYGEN__)
SerialDriver SD4;
#endif
#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART4 || defined(__DOXYGEN__)
SerialDriver SD5;
#endif
#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART5 || defined(__DOXYGEN__)
SerialDriver SD6;
#endif
@ -71,7 +78,7 @@ SerialDriver SD6;
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {
38400
SERIAL_DEFAULT_BITRATE
};
/*===========================================================================*/
@ -83,17 +90,21 @@ static const SerialConfig default_config = {
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] isr UART s1 register value
*/
static void set_error(SerialDriver *sdp, uint8_t s1) {
static void set_error(SerialDriver *sdp, uint32_t flags) {
eventflags_t sts = 0;
if (s1 & UARTx_S1_OR)
if (flags & kLPUART_RxOverrunFlag) {
sts |= SD_OVERRUN_ERROR;
if (s1 & UARTx_S1_PF)
}
if (flags & kLPUART_ParityErrorFlag) {
sts |= SD_PARITY_ERROR;
if (s1 & UARTx_S1_FE)
}
if (flags & kLPUART_FramingErrorFlag) {
sts |= SD_FRAMING_ERROR;
if (s1 & UARTx_S1_NF)
}
if (flags & kLPUART_NoiseErrorFlag) {
sts |= SD_NOISE_ERROR;
}
osalSysLockFromISR();
chnAddFlagsI(sdp, sts);
osalSysUnlockFromISR();
@ -106,40 +117,16 @@ static void set_error(SerialDriver *sdp, uint8_t s1) {
*/
static void serve_error_interrupt(SerialDriver *sdp) {
UART_w_TypeDef *u = &(sdp->uart);
uint8_t s1 = *(u->s1_p);
const uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p);
/* Clearing on K20x, K60x, and KL2x/UART>0 is done by reading S1 and
* then reading D.*/
if(s1 & UARTx_S1_IDLE) {
(void)*(u->d_p);
if (flags & kLPUART_IdleLineFlag) {
}
if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
set_error(sdp, s1);
(void)*(u->d_p);
if (flags & (kLPUART_RxOverrunFlag | kLPUART_NoiseErrorFlag | kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag)) {
set_error(sdp, flags);
}
}
#if defined(KL2x) && KINETIS_SERIAL_USE_UART0
static void serve_error_interrupt_uart0(void) {
SerialDriver *sdp = &SD1;
UART_w_TypeDef *u = &(sdp->uart);
uint8_t s1 = *(u->s1_p);
/* S1 bits are write-1-to-clear for UART0 on KL2x. */
if(s1 & UARTx_S1_IDLE) {
*(u->s1_p) |= UARTx_S1_IDLE;
}
if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
set_error(sdp, s1);
*(u->s1_p) |= UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF;
}
}
#endif /* KL2x && KINETIS_SERIAL_USE_UART0 */
/**
* @brief Common IRQ handler.
* @note Tries hard to clear all the pending interrupt sources, we don't
@ -150,18 +137,21 @@ static void serve_error_interrupt_uart0(void) {
*/
static void serve_interrupt(SerialDriver *sdp) {
UART_w_TypeDef *u = &(sdp->uart);
uint8_t s1 = *(u->s1_p);
if (s1 & UARTx_S1_RDRF) {
const uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p);
if (flags & kLPUART_RxDataRegFullFlag) {
osalSysLockFromISR();
if (iqIsEmptyI(&sdp->iqueue))
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
if (iqPutI(&sdp->iqueue, *(u->d_p)) < Q_OK)
uint8_t b;
LPUART_ReadBlocking(u->lpuart_p, &b, 1);
if (iqPutI(&sdp->iqueue, b) < Q_OK)
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
osalSysUnlockFromISR();
}
if (s1 & UARTx_S1_TDRE) {
if (flags & kLPUART_TxDataRegEmptyFlag) {
msg_t b;
osalSysLockFromISR();
@ -172,19 +162,15 @@ static void serve_interrupt(SerialDriver *sdp) {
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
*(u->c2_p) &= ~UARTx_C2_TIE;
// Disable Transfer Interrupt
LPUART_DisableInterrupts(u->lpuart_p, kLPUART_TxDataRegEmptyInterruptEnable);
} else {
*(u->d_p) = b;
LPUART_WriteBlocking(u->lpuart_p, (const uint8_t*)&b, 1);
}
}
#if defined(KL2x) && KINETIS_SERIAL_USE_UART0
if (sdp == &SD1) {
serve_error_interrupt_uart0();
return;
}
#endif
serve_error_interrupt(sdp);
LPUART_ClearStatusFlags(u->lpuart_p, flags);
}
/**
@ -192,15 +178,16 @@ static void serve_interrupt(SerialDriver *sdp) {
*/
static void preload(SerialDriver *sdp) {
UART_w_TypeDef *u = &(sdp->uart);
uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p);
if (*(u->s1_p) & UARTx_S1_TDRE) {
if (flags & kLPUART_TxDataRegEmptyFlag) {
msg_t b = oqGetI(&sdp->oqueue);
if (b < Q_OK) {
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
return;
}
*(u->d_p) = b;
*(u->c2_p) |= UARTx_C2_TIE;
LPUART_WriteBlocking(u->lpuart_p, (const uint8_t*)&b, 1);
LPUART_EnableInterrupts(u->lpuart_p, kLPUART_TxDataRegEmptyInterruptEnable);
}
}
@ -215,193 +202,64 @@ static void notify(io_queue_t *qp)
/**
* @brief Common driver initialization, except LP.
*/
static void sd_lld_init_driver(SerialDriver *SDn, UART_TypeDef *UARTn) {
static void sd_lld_init_driver(SerialDriver *SDn, LPUART_Type *UARTn) {
/* Driver initialization.*/
sdObjectInit(SDn, NULL, notify);
SDn->uart.bdh_p = &(UARTn->BDH);
SDn->uart.bdl_p = &(UARTn->BDL);
SDn->uart.c1_p = &(UARTn->C1);
SDn->uart.c2_p = &(UARTn->C2);
SDn->uart.c3_p = &(UARTn->C3);
SDn->uart.c4_p = &(UARTn->C4);
SDn->uart.s1_p = (volatile uint8_t *)&(UARTn->S1);
SDn->uart.s2_p = &(UARTn->S2);
SDn->uart.d_p = &(UARTn->D);
SDn->uart.uart_p = UARTn;
}
/**
* @brief Common UART configuration.
*
*/
static void configure_uart(SerialDriver *sdp, const SerialConfig *config) {
UART_w_TypeDef *uart = &(sdp->uart);
uint32_t divisor;
/* Discard any incoming data. */
while (*(uart->s1_p) & UARTx_S1_RDRF) {
(void)*(uart->d_p);
}
/* Disable UART while configuring */
*(uart->c2_p) &= ~(UARTx_C2_RE | UARTx_C2_TE);
/* The clock sources for various UARTs can be different. */
divisor=KINETIS_BUSCLK_FREQUENCY;
#if defined(KL2x)
#if KINETIS_SERIAL_USE_UART0
if (sdp == &SD1) {
/* UART0 can be clocked from several sources on KL2x. */
divisor = KINETIS_UART0_CLOCK_FREQ;
/* FIXME: change fixed OSR = 16 to dynamic value based on baud */
/* Note: OSR only works on KL2x/UART0; further UARTs have fixed 16. */
*(uart->c4_p) = UARTx_C4_OSR(16 - 1);
}
#endif /* KINETIS_SERIAL_USE_UART0 */
#elif defined(K20x) || defined(K60x) || defined(MK66F18) /* KL2x */
/* UARTs 0 and 1 are clocked from SYSCLK, others from BUSCLK on K20x and K60x. */
#if KINETIS_SERIAL_USE_UART0
if(sdp == &SD1)
divisor = KINETIS_SYSCLK_FREQUENCY;
#endif /* KINETIS_SERIAL_USE_UART0 */
#if KINETIS_SERIAL_USE_UART1
if(sdp == &SD2)
divisor = KINETIS_SYSCLK_FREQUENCY;
#endif /* KINETIS_SERIAL_USE_UART1 */
#else /* K20x */
#error Baud rate selection not implemented for this MCU type
#endif /* K20x */
divisor = (divisor * 2 + 1) / config->sc_speed;
*(uart->bdh_p) = UARTx_BDH_SBR(divisor >> 13) | (*(uart->bdh_p) & ~UARTx_BDH_SBR_MASK);
*(uart->bdl_p) = UARTx_BDL_SBR(divisor >> 5);
#if defined(K20x) || defined(K60x)
*(uart->c4_p) = UARTx_C4_BRFA(divisor) | (*(uart->c4_p) & ~UARTx_C4_BRFA_MASK);
#endif /* K20x, K60x */
/* Line settings. */
*(uart->c1_p) = 0;
/* Enable error event interrupts (overrun, noise, framing, parity) */
*(uart->c3_p) = UARTx_C3_ORIE | UARTx_C3_NEIE | UARTx_C3_FEIE | UARTx_C3_PEIE;
/* Enable the peripheral; including receive interrupts. */
*(uart->c2_p) |= UARTx_C2_RE | UARTx_C2_RIE | UARTx_C2_TE;
SDn->uart.lpuart_p = UARTn;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL0_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART0 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL0_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD1);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL1_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART1 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD2);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL2_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART2 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL2_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD3);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL3_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART3 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL3_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD4);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL4_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART4 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL4_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD5);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL5_IRQ_VECTOR) {
#if MIMXRT1062_SERIAL_USE_UART5 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(MIMXRT1062_SERIAL5_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_interrupt(&SD6);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_HAS_SERIAL_ERROR_IRQ
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL0_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
#if defined(KL2x)
serve_error_interrupt_uart0();
#else
serve_error_interrupt(&SD1);
#endif
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL1_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_error_interrupt(&SD2);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL2_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_error_interrupt(&SD3);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL3_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_error_interrupt(&SD4);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL4_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_error_interrupt(&SD5);
OSAL_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(KINETIS_SERIAL5_ERROR_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
serve_error_interrupt(&SD6);
OSAL_IRQ_EPILOGUE();
}
#endif
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@ -413,71 +271,47 @@ OSAL_IRQ_HANDLER(KINETIS_SERIAL5_ERROR_IRQ_VECTOR) {
*/
void sd_lld_init(void) {
#if KINETIS_SERIAL_USE_UART0
#if MIMXRT1062_SERIAL_USE_UART0
/* Driver initialization.*/
#if ! KINETIS_SERIAL0_IS_LPUART
sd_lld_init_driver(&SD1, (UART_TypeDef *)UART0);
#else /* ! KINETIS_SERIAL0_IS_LPUART */
/* little endian! */
sdObjectInit(&SD1, NULL, notify);
SD1.uart.bdh_p = ((uint8_t *)&(LPUART0->BAUD)) + 1; /* BDH: BAUD, byte 3 */
SD1.uart.bdl_p = ((uint8_t *)&(LPUART0->BAUD)) + 0; /* BDL: BAUD, byte 4 */
SD1.uart.c1_p = ((uint8_t *)&(LPUART0->CTRL)) + 0; /* C1: CTRL, byte 4 */
SD1.uart.c2_p = ((uint8_t *)&(LPUART0->CTRL)) + 2; /* C2: CTRL, byte 2 */
SD1.uart.c3_p = ((uint8_t *)&(LPUART0->CTRL)) + 3; /* C3: CTRL, byte 1 */
SD1.uart.c4_p = ((uint8_t *)&(LPUART0->BAUD)) + 3; /* C4: BAUD, byte 1 */
SD1.uart.s1_p = ((uint8_t *)&(LPUART0->STAT)) + 2; /* S1: STAT, byte 2 */
SD1.uart.s2_p = ((uint8_t *)&(LPUART0->STAT)) + 3; /* S2: STAT, byte 1 */
SD1.uart.d_p = ((uint8_t *)&(LPUART0->DATA)) + 0; /* D: DATA, byte 4 */
#endif /* ! KINETIS_SERIAL0_IS_LPUART */
#if KINETIS_SERIAL0_IS_UARTLP
SD1.uart.c4_p = &(UART0->C4); /* fix up misconfigured C4 register */
SD1.uart.uartlp_p = UART0;
SD1.uart.uart_p = NULL;
#elif KINETIS_SERIAL0_IS_LPUART
SD1.uart.lpuart_p = LPUART0;
SD1.uart.uart_p = NULL;
#else /* KINETIS_SERIAL0_IS_LPUART */
SD1.uart.uart_p = UART0;
#endif /* KINETIS_SERIAL0_IS_LPUART */
#endif /* KINETIS_SERIAL_USE_UART0 */
sd_lld_init_driver(&SD1, LPUART1);
#endif /* MIMXRT1062_SERIAL_USE_UART0 */
#if KINETIS_SERIAL_USE_UART1
/* Driver initialization.*/
#if ! KINETIS_SERIAL1_IS_LPUART
sd_lld_init_driver(&SD2, UART1);
#else /* ! KINETIS_SERIAL1_IS_LPUART */
/* little endian! */
sdObjectInit(&SD2, NULL, notify);
SD2.uart.bdh_p = ((uint8_t *)&(LPUART1->BAUD)) + 1; /* BDH: BAUD, byte 3 */
SD2.uart.bdl_p = ((uint8_t *)&(LPUART1->BAUD)) + 0; /* BDL: BAUD, byte 4 */
SD2.uart.c1_p = ((uint8_t *)&(LPUART1->CTRL)) + 0; /* C1: CTRL, byte 4 */
SD2.uart.c2_p = ((uint8_t *)&(LPUART1->CTRL)) + 2; /* C2: CTRL, byte 2 */
SD2.uart.c3_p = ((uint8_t *)&(LPUART1->CTRL)) + 3; /* C3: CTRL, byte 1 */
SD2.uart.c4_p = ((uint8_t *)&(LPUART1->BAUD)) + 3; /* C4: BAUD, byte 1 */
SD2.uart.s1_p = ((uint8_t *)&(LPUART1->STAT)) + 2; /* S1: STAT, byte 2 */
SD2.uart.s2_p = ((uint8_t *)&(LPUART1->STAT)) + 3; /* S2: STAT, byte 1 */
SD2.uart.d_p = ((uint8_t *)&(LPUART1->DATA)) + 0; /* D: DATA, byte 4 */
SD2.uart.lpuart_p = LPUART1;
SD2.uart.uart_p = NULL;
#endif /* ! KINETIS_SERIAL1_IS_LPUART */
#endif /* KINETIS_SERIAL_USE_UART1 */
#if MIMXRT1062_SERIAL_USE_UART1
sd_lld_init_driver(&SD2, LPUART2);
#endif /* MIMXRT1062_SERIAL_USE_UART1 */
#if KINETIS_SERIAL_USE_UART2
sd_lld_init_driver(&SD3, UART2);
#endif /* KINETIS_SERIAL_USE_UART2 */
#if MIMXRT1062_SERIAL_USE_UART2
sd_lld_init_driver(&SD3, LPUART3);
#endif /* MIMXRT1062_SERIAL_USE_UART2 */
#if KINETIS_SERIAL_USE_UART3
sd_lld_init_driver(&SD4, UART3);
#endif /* KINETIS_SERIAL_USE_UART3 */
#if MIMXRT1062_SERIAL_USE_UART3
sd_lld_init_driver(&SD4, LPUART4);
#endif /* MIMXRT1062_SERIAL_USE_UART3 */
#if KINETIS_SERIAL_USE_UART4
sd_lld_init_driver(&SD5, UART4);
#endif /* KINETIS_SERIAL_USE_UART4 */
#if MIMXRT1062_SERIAL_USE_UART4
sd_lld_init_driver(&SD5, LPUART5);
#endif /* MIMXRT1062_SERIAL_USE_UART4 */
#if KINETIS_SERIAL_USE_UART5
sd_lld_init_driver(&SD6, UART5);
#endif /* KINETIS_SERIAL_USE_UART5 */
#if MIMXRT1062_SERIAL_USE_UART5
sd_lld_init_driver(&SD6, LPUART6);
#endif /* MIMXRT1062_SERIAL_USE_UART5 */
}
// See also:
// https://github.com/adafruit/circuitpython/blob/main/ports/mimxrt10xx/supervisor/serial.c
static uint32_t UartSrcFreq(void) {
uint32_t freq;
/* To make it simple, we assume default PLL and divider settings, and the only variable
from application is use PLL3 source or OSC source */
/* PLL3 div6 80M */
if (CLOCK_GetMux(kCLOCK_UartMux) == 0) {
freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
} else {
freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
}
return freq;
}
/**
@ -498,98 +332,55 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
if (sdp->state == SD_STOP) {
/* Enables the peripheral.*/
#if KINETIS_SERIAL_USE_UART0
lpuart_config_t uconfig;
LPUART_GetDefaultConfig(&uconfig);
uconfig.baudRate_Bps = config->sc_speed;
uconfig.enableTx = true;
uconfig.enableRx = true;
#if MIMXRT1062_SERIAL_USE_UART0
if (sdp == &SD1) {
#if KINETIS_SERIAL0_IS_LPUART
SIM->SCGC5 |= SIM_SCGC5_LPUART0;
SIM->SOPT2 =
(SIM->SOPT2 & ~SIM_SOPT2_LPUART0SRC_MASK) |
SIM_SOPT2_LPUART0SRC(KINETIS_UART0_CLOCK_SRC);
#else /* KINETIS_SERIAL0_IS_LPUART */
SIM->SCGC4 |= SIM_SCGC4_UART0;
#endif /* KINETIS_SERIAL0_IS_LPUART */
#if KINETIS_SERIAL0_IS_UARTLP
SIM->SOPT2 =
(SIM->SOPT2 & ~SIM_SOPT2_UART0SRC_MASK) |
SIM_SOPT2_UART0SRC(KINETIS_UART0_CLOCK_SRC);
#endif /* KINETIS_SERIAL0_IS_UARTLP */
configure_uart(sdp, config);
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicEnableVector(UART0Status_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
nvicEnableVector(UART0Error_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL0_IS_LPUART
nvicEnableVector(LPUART0_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
#else /* KINETIS_SERIAL0_IS_LPUART */
nvicEnableVector(UART0_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
#endif /* KINETIS_SERIAL0_IS_LPUART */
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
}
#endif /* KINETIS_SERIAL_USE_UART0 */
LPUART_Init(LPUART1, &uconfig, UartSrcFreq());
IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12] = 2; // Arduino pin 24
IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13] = 2; // Arduino pin 25
#if KINETIS_SERIAL_USE_UART1
nvicEnableVector(LPUART1_IRQn, MIMXRT1062_SERIAL_UART0_PRIORITY);
LPUART_EnableInterrupts(LPUART1, kLPUART_RxDataRegFullInterruptEnable);
}
#endif /* MIMXRT1062_SERIAL_USE_UART0 */
#if MIMXRT1062_SERIAL_USE_UART1
if (sdp == &SD2) {
#if KINETIS_SERIAL1_IS_LPUART
SIM->SCGC5 |= SIM_SCGC5_LPUART1;
SIM->SOPT2 =
(SIM->SOPT2 & ~SIM_SOPT2_LPUART1SRC_MASK) |
SIM_SOPT2_LPUART1SRC(KINETIS_UART1_CLOCK_SRC);
#else /* KINETIS_SERIAL1_IS_LPUART */
SIM->SCGC4 |= SIM_SCGC4_UART1;
#endif /* KINETIS_SERIAL1_IS_LPUART */
configure_uart(sdp, config);
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicEnableVector(UART1Status_IRQn, KINETIS_SERIAL_UART1_PRIORITY);
nvicEnableVector(UART1Error_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL1_IS_LPUART
nvicEnableVector(LPUART1_IRQn, KINETIS_SERIAL_UART1_PRIORITY);
#else /* KINETIS_SERIAL1_IS_LPUART */
nvicEnableVector(UART1_IRQn, KINETIS_SERIAL_UART1_PRIORITY);
#endif /* KINETIS_SERIAL1_IS_LPUART */
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
LPUART_Init(LPUART2, &uconfig, UartSrcFreq());
}
#endif /* KINETIS_SERIAL_USE_UART1 */
#endif /* MIMXRT1062_SERIAL_USE_UART1 */
#if KINETIS_SERIAL_USE_UART2
#if MIMXRT1062_SERIAL_USE_UART2
if (sdp == &SD3) {
SIM->SCGC4 |= SIM_SCGC4_UART2;
configure_uart(sdp, config);
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicEnableVector(UART2Status_IRQn, KINETIS_SERIAL_UART2_PRIORITY);
nvicEnableVector(UART2Error_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
nvicEnableVector(UART2_IRQn, KINETIS_SERIAL_UART2_PRIORITY);
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
LPUART_Init(LPUART3, &uconfig, UartSrcFreq());
IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06] = 2; // Arduino pin 17
}
#endif /* KINETIS_SERIAL_USE_UART2 */
#endif /* MIMXRT1062_SERIAL_USE_UART2 */
#if KINETIS_SERIAL_USE_UART3
#if MIMXRT1062_SERIAL_USE_UART3
if (sdp == &SD4) {
SIM->SCGC4 |= SIM_SCGC4_UART3;
configure_uart(sdp, config);
nvicEnableVector(UART3Status_IRQn, KINETIS_SERIAL_UART3_PRIORITY);
nvicEnableVector(UART3Error_IRQn, KINETIS_SERIAL_UART3_PRIORITY);
LPUART_Init(LPUART4, &uconfig, UartSrcFreq());
}
#endif /* KINETIS_SERIAL_USE_UART3 */
#endif /* MIMXRT1062_SERIAL_USE_UART3 */
#if KINETIS_SERIAL_USE_UART4
#if MIMXRT1062_SERIAL_USE_UART4
if (sdp == &SD5) {
SIM->SCGC1 |= SIM_SCGC1_UART4;
configure_uart(sdp, config);
nvicEnableVector(UART4Status_IRQn, KINETIS_SERIAL_UART4_PRIORITY);
nvicEnableVector(UART4Error_IRQn, KINETIS_SERIAL_UART4_PRIORITY);
LPUART_Init(LPUART4, &uconfig, UartSrcFreq());
}
#endif /* KINETIS_SERIAL_USE_UART4 */
#endif /* MIMXRT1062_SERIAL_USE_UART4 */
#if KINETIS_SERIAL_USE_UART5
#if MIMXRT1062_SERIAL_USE_UART5
if (sdp == &SD6) {
SIM->SCGC1 |= SIM_SCGC1_UART5;
configure_uart(sdp, config);
nvicEnableVector(UART5Status_IRQn, KINETIS_SERIAL_UART5_PRIORITY);
nvicEnableVector(UART5Error_IRQn, KINETIS_SERIAL_UART5_PRIORITY);
LPUART_Init(LPUART5, &uconfig, UartSrcFreq());
}
#endif /* KINETIS_SERIAL_USE_UART5 */
#endif /* MIMXRT1062_SERIAL_USE_UART5 */
}
/* Configures the peripheral.*/
@ -608,81 +399,41 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
void sd_lld_stop(SerialDriver *sdp) {
if (sdp->state == SD_READY) {
/* TODO: Resets the peripheral.*/
#if KINETIS_SERIAL_USE_UART0
#if MIMXRT1062_SERIAL_USE_UART0
if (sdp == &SD1) {
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicDisableVector(UART0Status_IRQn);
nvicDisableVector(UART0Error_IRQn);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL0_IS_LPUART
nvicDisableVector(LPUART0_IRQn);
#else /* KINETIS_SERIAL0_IS_LPUART */
nvicDisableVector(UART0_IRQn);
#endif /* KINETIS_SERIAL0_IS_LPUART */
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL0_IS_LPUART
SIM->SCGC5 &= ~SIM_SCGC5_LPUART0;
#else /* KINETIS_SERIAL0_IS_LPUART */
SIM->SCGC4 &= ~SIM_SCGC4_UART0;
#endif /* KINETIS_SERIAL0_IS_LPUART */
}
#endif
#if KINETIS_SERIAL_USE_UART1
if (sdp == &SD2) {
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicDisableVector(UART1Status_IRQn);
nvicDisableVector(UART1Error_IRQn);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL1_IS_LPUART
nvicDisableVector(LPUART1_IRQn);
#else /* KINETIS_SERIAL1_IS_LPUART */
nvicDisableVector(UART1_IRQn);
#endif /* KINETIS_SERIAL1_IS_LPUART */
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
#if KINETIS_SERIAL1_IS_LPUART
SIM->SCGC5 &= ~SIM_SCGC5_LPUART1;
#else /* KINETIS_SERIAL1_IS_LPUART */
SIM->SCGC4 &= ~SIM_SCGC4_UART1;
#endif /* KINETIS_SERIAL1_IS_LPUART */
LPUART_Deinit(LPUART1);
}
#endif
#if KINETIS_SERIAL_USE_UART2
#if MIMXRT1062_SERIAL_USE_UART1
if (sdp == &SD2) {
LPUART_Deinit(LPUART2);
}
#endif
#if MIMXRT1062_SERIAL_USE_UART2
if (sdp == &SD3) {
#if KINETIS_HAS_SERIAL_ERROR_IRQ
nvicDisableVector(UART2Status_IRQn);
nvicDisableVector(UART2Error_IRQn);
#else /* KINETIS_HAS_SERIAL_ERROR_IRQ */
nvicDisableVector(UART2_IRQn);
#endif /* KINETIS_HAS_SERIAL_ERROR_IRQ */
SIM->SCGC4 &= ~SIM_SCGC4_UART2;
LPUART_Deinit(LPUART3);
}
#endif
#if KINETIS_SERIAL_USE_UART3
#if MIMXRT1062_SERIAL_USE_UART3
if (sdp == &SD4) {
nvicDisableVector(UART3Status_IRQn);
nvicDisableVector(UART3Error_IRQn);
SIM->SCGC4 &= ~SIM_SCGC4_UART3;
LPUART_Deinit(LPUART4);
}
#endif
#if KINETIS_SERIAL_USE_UART4
#if MIMXRT1062_SERIAL_USE_UART4
if (sdp == &SD5) {
nvicDisableVector(UART4Status_IRQn);
nvicDisableVector(UART4Error_IRQn);
SIM->SCGC1 &= ~SIM_SCGC1_UART4;
LPUART_Deinit(LPUART5);
}
#endif
#if KINETIS_SERIAL_USE_UART5
#if MIMXRT1062_SERIAL_USE_UART5
if (sdp == &SD6) {
nvicDisableVector(UART5Status_IRQn);
nvicDisableVector(UART5Error_IRQn);
SIM->SCGC1 &= ~SIM_SCGC1_UART5;
LPUART_Deinit(LPUART6);
}
#endif
}

View File

@ -27,6 +27,8 @@
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
#include "fsl_lpuart.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
@ -43,99 +45,99 @@
* @brief SD1 driver enable switch.
* @details If set to @p TRUE the support for SD1 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART0) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART0 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART0) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART0 TRUE
#endif
/**
* @brief SD2 driver enable switch.
* @details If set to @p TRUE the support for SD2 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART1 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART1 FALSE
#endif
/**
* @brief SD3 driver enable switch.
* @details If set to @p TRUE the support for SD3 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART2) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART2 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART2) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART2 TRUE
#endif
/**
* @brief SD4 driver enable switch.
* @details If set to @p TRUE the support for SD4 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART3) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART3 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART3) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART3 TRUE
#endif
/**
* @brief SD5 driver enable switch.
* @details If set to @p TRUE the support for SD5 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART4) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART4 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART4) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART4 FALSE
#endif
/**
* @brief SD6 driver enable switch.
* @details If set to @p TRUE the support for SD6 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART5) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART5 FALSE
#if !defined(MIMXRT1062_SERIAL_USE_UART5) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_USE_UART5 FALSE
#endif
/**
* @brief UART0 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART0_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART0_PRIORITY 12
#endif
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART1_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART1_PRIORITY 12
#endif
/**
* @brief UART2 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART2_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART2_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART2_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART2_PRIORITY 12
#endif
/**
* @brief UART3 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART3_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART3_PRIORITY 12
#endif
/**
* @brief UART4 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART4_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART4_PRIORITY 12
#endif
/**
* @brief UART5 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART5_PRIORITY 12
#if !defined(MIMXRT1062_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
#define MIMXRT1062_SERIAL_UART5_PRIORITY 12
#endif
/**
* @brief UART0 clock source.
*/
#if !defined(KINETIS_UART0_CLOCK_SRC) || defined(__DOXYGEN__)
#define KINETIS_UART0_CLOCK_SRC 1 /* MCGFLLCLK clock, or MCGPLLCLK/2; or IRC48M */
#if !defined(MIMXRT1062_UART0_CLOCK_SRC) || defined(__DOXYGEN__)
#define MIMXRT1062_UART0_CLOCK_SRC 1 /* MCGFLLCLK clock, or MCGPLLCLK/2; or IRC48M */
#endif
/**
* @brief UART1 clock source.
*/
#if !defined(KINETIS_UART1_CLOCK_SRC) || defined(__DOXYGEN__)
#define KINETIS_UART1_CLOCK_SRC 1 /* IRC48M */
#if !defined(MIMXRT1062_UART1_CLOCK_SRC) || defined(__DOXYGEN__)
#define MIMXRT1062_UART1_CLOCK_SRC 1 /* IRC48M */
#endif
/** @} */
@ -145,33 +147,33 @@
/*===========================================================================*/
/** @brief error checks */
#if KINETIS_SERIAL_USE_UART0 && !KINETIS_HAS_SERIAL0
#if MIMXRT1062_SERIAL_USE_UART0 && !MIMXRT1062_HAS_SERIAL0
#error "UART0 not present in the selected device"
#endif
#if KINETIS_SERIAL_USE_UART1 && !KINETIS_HAS_SERIAL1
#if MIMXRT1062_SERIAL_USE_UART1 && !MIMXRT1062_HAS_SERIAL1
#error "UART1 not present in the selected device"
#endif
#if KINETIS_SERIAL_USE_UART2 && !KINETIS_HAS_SERIAL2
#if MIMXRT1062_SERIAL_USE_UART2 && !MIMXRT1062_HAS_SERIAL2
#error "UART2 not present in the selected device"
#endif
#if KINETIS_SERIAL_USE_UART3 && !KINETIS_HAS_SERIAL3
#if MIMXRT1062_SERIAL_USE_UART3 && !MIMXRT1062_HAS_SERIAL3
#error "UART3 not present in the selected device"
#endif
#if KINETIS_SERIAL_USE_UART4 && !KINETIS_HAS_SERIAL4
#if MIMXRT1062_SERIAL_USE_UART4 && !MIMXRT1062_HAS_SERIAL4
#error "UART4 not present in the selected device"
#endif
#if KINETIS_SERIAL_USE_UART5 && !KINETIS_HAS_SERIAL5
#if MIMXRT1062_SERIAL_USE_UART5 && !MIMXRT1062_HAS_SERIAL5
#error "UART5 not present in the selected device"
#endif
#if !(KINETIS_SERIAL_USE_UART0 || KINETIS_SERIAL_USE_UART1 || \
KINETIS_SERIAL_USE_UART2 || KINETIS_SERIAL_USE_UART3 || \
KINETIS_SERIAL_USE_UART4 || KINETIS_SERIAL_USE_UART5)
#if !(MIMXRT1062_SERIAL_USE_UART0 || MIMXRT1062_SERIAL_USE_UART1 || \
MIMXRT1062_SERIAL_USE_UART2 || MIMXRT1062_SERIAL_USE_UART3 || \
MIMXRT1062_SERIAL_USE_UART4 || MIMXRT1062_SERIAL_USE_UART5)
#error "Serial driver activated but no UART peripheral assigned"
#endif
@ -200,23 +202,8 @@ typedef struct {
*/
typedef struct {
volatile uint8_t* bdh_p;
volatile uint8_t* bdl_p;
volatile uint8_t* c1_p;
volatile uint8_t* c2_p;
volatile uint8_t* c3_p;
volatile uint8_t* c4_p;
volatile uint8_t* s1_p;
volatile uint8_t* s2_p;
volatile uint8_t* d_p;
UART_TypeDef *uart_p;
#if KINETIS_SERIAL_USE_UART0 && KINETIS_SERIAL0_IS_UARTLP
UARTLP_TypeDef *uartlp_p;
#endif /* KINETIS_SERIAL_USE_UART0 && KINETIS_SERIAL0_IS_UARTLP */
#if (KINETIS_SERIAL_USE_UART0 && KINETIS_SERIAL0_IS_LPUART) \
|| (KINETIS_SERIAL_USE_UART1 && KINETIS_SERIAL1_IS_LPUART)
LPUART_TypeDef *lpuart_p;
#endif /* KINETIS_SERIAL_USE_UART0 && KINETIS_SERIAL0_IS_LPUART */
LPUART_Type *lpuart_p;
lpuart_handle_t handle;
} UART_w_TypeDef;
/**
@ -246,27 +233,27 @@ typedef struct {
/* External declarations. */
/*===========================================================================*/
#if KINETIS_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#if KINETIS_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
extern SerialDriver SD2;
#endif
#if KINETIS_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
extern SerialDriver SD3;
#endif
#if KINETIS_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
extern SerialDriver SD4;
#endif
#if KINETIS_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
extern SerialDriver SD5;
#endif
#if KINETIS_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
#if MIMXRT1062_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
extern SerialDriver SD6;
#endif