From c4eb6b4901da49fa69f2d5778ee9b32d7b9a126f Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Fri, 8 Dec 2017 19:42:13 -0800 Subject: Added support for additional UARTs (up to six on the K64F). Also moved some code that is duplicated per-UART into local functions to reduce the amount of duplication. --- os/hal/ports/KINETIS/LLD/hal_serial_lld.c | 251 +++++++++++++++++++++--------- os/hal/ports/KINETIS/LLD/hal_serial_lld.h | 69 +++++++- 2 files changed, 248 insertions(+), 72 deletions(-) (limited to 'os/hal') diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c index c80cf22..c92fa5c 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c @@ -1,5 +1,6 @@ /* ChibiOS - Copyright (C) 2013-2015 Fabio Utzig + Copyright (C) 2017 Wim Lewis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -50,6 +51,18 @@ SerialDriver SD2; SerialDriver SD3; #endif +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ @@ -95,33 +108,37 @@ static void serve_error_interrupt(SerialDriver *sdp) { UART_w_TypeDef *u = &(sdp->uart); uint8_t s1 = *(u->s1_p); - /* S1 bits are write-1-to-clear for UART0 on KL2x. */ - /* Clearing on K20x and KL2x/UART>0 is done by reading S1 and + /* Clearing on K20x, K60x, and KL2x/UART>0 is done by reading S1 and * then reading D.*/ -#if defined(KL2x) && KINETIS_SERIAL_USE_UART0 - if(sdp == &SD1) { - if(s1 & UARTx_S1_IDLE) { - *(u->s1_p) |= UARTx_S1_IDLE; - } + if(s1 & UARTx_S1_IDLE) { + (void)*(u->d_p); + } - 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; - } - return; + if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) { + set_error(sdp, s1); + (void)*(u->d_p); } -#endif /* KL2x && KINETIS_SERIAL_USE_UART0 */ +} + +#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) { - (void)*(u->d_p); + *(u->s1_p) |= UARTx_S1_IDLE; } if(s1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) { set_error(sdp, s1); - (void)*(u->d_p); + *(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. @@ -161,6 +178,12 @@ static void serve_interrupt(SerialDriver *sdp) { } } +#if defined(KL2x) && KINETIS_SERIAL_USE_UART0 + if (sdp == &SD1) { + serve_error_interrupt_uart0(); + return; + } +#endif serve_error_interrupt(sdp); } @@ -184,29 +207,28 @@ static void preload(SerialDriver *sdp) { /** * @brief Driver output notification. */ -#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__) -static void notify1(io_queue_t *qp) +static void notify(io_queue_t *qp) { - (void)qp; - preload(&SD1); + preload(qp->q_link); } -#endif -#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__) -static void notify2(io_queue_t *qp) -{ - (void)qp; - preload(&SD2); -} -#endif - -#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__) -static void notify3(io_queue_t *qp) -{ - (void)qp; - preload(&SD3); +/** + * @brief Common driver initialization, except LP. + */ +static void sd_lld_init_driver(SerialDriver *SDn, UART_TypeDef *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; } -#endif /** * @brief Common UART configuration. @@ -240,9 +262,9 @@ static void configure_uart(SerialDriver *sdp, const SerialConfig *config) { } #endif /* KINETIS_SERIAL_USE_UART0 */ -#elif defined(K20x) /* KL2x */ +#elif defined(K20x) || defined(K60x) /* KL2x */ - /* UARTs 0 and 1 are clocked from SYSCLK, others from BUSCLK on K20x. */ + /* 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; @@ -260,9 +282,9 @@ static void configure_uart(SerialDriver *sdp, const SerialConfig *config) { *(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) +#if defined(K20x) || defined(K60x) *(uart->c4_p) = UARTx_C4_BRFA(divisor) | (*(uart->c4_p) & ~UARTx_C4_BRFA_MASK); -#endif /* K20x */ +#endif /* K20x, K60x */ /* Line settings. */ *(uart->c1_p) = 0; @@ -300,12 +322,40 @@ OSAL_IRQ_HANDLER(KINETIS_SERIAL2_IRQ_VECTOR) { } #endif +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(KINETIS_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) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD5); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(KINETIS_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 @@ -326,6 +376,30 @@ OSAL_IRQ_HANDLER(KINETIS_SERIAL2_ERROR_IRQ_VECTOR) { } #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 */ /*===========================================================================*/ @@ -341,19 +415,11 @@ void sd_lld_init(void) { #if KINETIS_SERIAL_USE_UART0 /* Driver initialization.*/ - sdObjectInit(&SD1, NULL, notify1); #if ! KINETIS_SERIAL0_IS_LPUART - SD1.uart.bdh_p = &(UART0->BDH); - SD1.uart.bdl_p = &(UART0->BDL); - SD1.uart.c1_p = &(UART0->C1); - SD1.uart.c2_p = &(UART0->C2); - SD1.uart.c3_p = &(UART0->C3); - SD1.uart.c4_p = &(UART0->C4); - SD1.uart.s1_p = (volatile uint8_t *)&(UART0->S1); - SD1.uart.s2_p = &(UART0->S2); - SD1.uart.d_p = &(UART0->D); + sd_lld_init_driver(&SD1, 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 */ @@ -377,20 +443,11 @@ void sd_lld_init(void) { #if KINETIS_SERIAL_USE_UART1 /* Driver initialization.*/ - sdObjectInit(&SD2, NULL, notify2); #if ! KINETIS_SERIAL1_IS_LPUART - SD2.uart.bdh_p = &(UART1->BDH); - SD2.uart.bdl_p = &(UART1->BDL); - SD2.uart.c1_p = &(UART1->C1); - SD2.uart.c2_p = &(UART1->C2); - SD2.uart.c3_p = &(UART1->C3); - SD2.uart.c4_p = &(UART1->C4); - SD2.uart.s1_p = (volatile uint8_t *)&(UART1->S1); - SD2.uart.s2_p = &(UART1->S2); - SD2.uart.d_p = &(UART1->D); - SD2.uart.uart_p = UART1; + 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 */ @@ -406,19 +463,20 @@ void sd_lld_init(void) { #endif /* KINETIS_SERIAL_USE_UART1 */ #if KINETIS_SERIAL_USE_UART2 - /* Driver initialization.*/ - sdObjectInit(&SD3, NULL, notify3); - SD3.uart.bdh_p = &(UART2->BDH); - SD3.uart.bdl_p = &(UART2->BDL); - SD3.uart.c1_p = &(UART2->C1); - SD3.uart.c2_p = &(UART2->C2); - SD3.uart.c3_p = &(UART2->C3); - SD3.uart.c4_p = &(UART2->C4); - SD3.uart.s1_p = (volatile uint8_t *)&(UART2->S1); - SD3.uart.s2_p = &(UART2->S2); - SD3.uart.d_p = &(UART2->D); - SD3.uart.uart_p = UART2; + sd_lld_init_driver(&SD3, UART2); #endif /* KINETIS_SERIAL_USE_UART2 */ + +#if KINETIS_SERIAL_USE_UART3 + sd_lld_init_driver(&SD4, UART3); +#endif /* KINETIS_SERIAL_USE_UART3 */ + +#if KINETIS_SERIAL_USE_UART4 + sd_lld_init_driver(&SD5, UART4); +#endif /* KINETIS_SERIAL_USE_UART4 */ + +#if KINETIS_SERIAL_USE_UART5 + sd_lld_init_driver(&SD6, UART5); +#endif /* KINETIS_SERIAL_USE_UART5 */ } /** @@ -505,6 +563,33 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { } #endif /* KINETIS_SERIAL_USE_UART2 */ +#if KINETIS_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); + } +#endif /* KINETIS_SERIAL_USE_UART3 */ + +#if KINETIS_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); + } +#endif /* KINETIS_SERIAL_USE_UART4 */ + +#if KINETIS_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); + } +#endif /* KINETIS_SERIAL_USE_UART5 */ + } /* Configures the peripheral.*/ @@ -575,6 +660,30 @@ void sd_lld_stop(SerialDriver *sdp) { SIM->SCGC4 &= ~SIM_SCGC4_UART2; } #endif + +#if KINETIS_SERIAL_USE_UART3 + if (sdp == &SD4) { + nvicDisableVector(UART3Status_IRQn); + nvicDisableVector(UART3Error_IRQn); + SIM->SCGC4 &= ~SIM_SCGC4_UART3; + } +#endif + +#if KINETIS_SERIAL_USE_UART4 + if (sdp == &SD5) { + nvicDisableVector(UART4Status_IRQn); + nvicDisableVector(UART4Error_IRQn); + SIM->SCGC1 &= ~SIM_SCGC1_UART4; + } +#endif + +#if KINETIS_SERIAL_USE_UART5 + if (sdp == &SD6) { + nvicDisableVector(UART5Status_IRQn); + nvicDisableVector(UART5Error_IRQn); + SIM->SCGC1 &= ~SIM_SCGC1_UART5; + } +#endif } } diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h index f11c063..3cb6d2b 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h @@ -60,6 +60,27 @@ #if !defined(KINETIS_SERIAL_USE_UART2) || defined(__DOXYGEN__) #define KINETIS_SERIAL_USE_UART2 FALSE #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 +#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 +#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 +#endif /** * @brief UART0 interrupt priority level setting. @@ -82,6 +103,27 @@ #define KINETIS_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 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(KINETIS_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_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 +#endif + /** * @brief UART0 clock source. */ @@ -115,8 +157,21 @@ #error "UART2 not present in the selected device" #endif +#if KINETIS_SERIAL_USE_UART3 && !KINETIS_HAS_SERIAL3 +#error "UART3 not present in the selected device" +#endif + +#if KINETIS_SERIAL_USE_UART4 && !KINETIS_HAS_SERIAL4 +#error "UART4 not present in the selected device" +#endif + +#if KINETIS_SERIAL_USE_UART5 && !KINETIS_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_UART2 || KINETIS_SERIAL_USE_UART3 || \ + KINETIS_SERIAL_USE_UART4 || KINETIS_SERIAL_USE_UART5) #error "Serial driver activated but no UART peripheral assigned" #endif @@ -203,6 +258,18 @@ extern SerialDriver SD2; extern SerialDriver SD3; #endif +#if KINETIS_SERIAL_USE_UART3 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif + +#if KINETIS_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif + +#if KINETIS_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.2.3