diff --git a/arch/arm/include/kinetis/chip.h b/arch/arm/include/kinetis/chip.h index d7293d30992..5c6cc76a082 100644 --- a/arch/arm/include/kinetis/chip.h +++ b/arch/arm/include/kinetis/chip.h @@ -1427,7 +1427,8 @@ # define KINETIS_NUSBDEV 1 /* One USB device controller */ # define KINETIS_NSDHC 1 /* SD host controller */ # define KINETIS_NI2C 4 /* Four I2C modules */ -# define KINETIS_NUART 5 /* Five UART modues */ +# define KINETIS_NUART 5 /* Five UART modules */ +# define KINETIS_NLPUART 1 /* One LPUART modules */ # define KINETIS_NSPI 3 /* Three SPI modules */ # define KINETIS_NCAN 2 /* Two CAN controllers */ # define KINETIS_NI2S 1 /* One I2S modules */ diff --git a/arch/arm/src/kinetis/Kconfig b/arch/arm/src/kinetis/Kconfig index 04d0df453be..e1cd2506f97 100644 --- a/arch/arm/src/kinetis/Kconfig +++ b/arch/arm/src/kinetis/Kconfig @@ -220,27 +220,60 @@ config ARCH_CHIP_MK66FN2M0VLQ18 endchoice +# These "hidden" settings determine is a peripheral option is available for +# the selection MCU + +config KINETIS_HAVE_UART5 + bool + default n + +config KINETIS_HAVE_LPUART0 + bool + default n + +config KINETIS_HAVE_LPUART1 + bool + default n + +# When there are multiple instances of a device, these "hidden" settings +# will automatically be selected and will represent the 'OR' of the +# instances selected. + +config KINETIS_LPUART + bool + default n + +config KINETIS_UART + bool + default n + select MCU_SERIAL + # Chip families config ARCH_FAMILY_K20 bool default n + select KINETIS_HAVE_UART5 config ARCH_FAMILY_K40 bool default n + select KINETIS_HAVE_UART5 config ARCH_FAMILY_K60 bool default n + select KINETIS_HAVE_UART5 config ARCH_FAMILY_K64 bool default n + select KINETIS_HAVE_UART5 config ARCH_FAMILY_K66 bool default n + select KINETIS_HAVE_LPUART0 menu "Kinetis Peripheral Support" @@ -280,6 +313,7 @@ config KINETIS_UART0 bool "UART0" default n select UART0_SERIALDRIVER + select KINETIS_UART ---help--- Support UART0 @@ -287,6 +321,7 @@ config KINETIS_UART1 bool "UART1" default n select UART1_SERIALDRIVER + select KINETIS_UART ---help--- Support UART1 @@ -294,6 +329,7 @@ config KINETIS_UART2 bool "UART2" default n select UART2_SERIALDRIVER + select KINETIS_UART ---help--- Support UART2 @@ -301,6 +337,7 @@ config KINETIS_UART3 bool "UART3" default n select UART3_SERIALDRIVER + select KINETIS_UART ---help--- Support UART3 @@ -308,16 +345,37 @@ config KINETIS_UART4 bool "UART4" default n select UART4_SERIALDRIVER + select KINETIS_UART ---help--- Support UART4 config KINETIS_UART5 bool "UART5" default n + depends on KINETIS_HAVE_UART5 select UART5_SERIALDRIVER + select KINETIS_UART ---help--- Support UART5 +config KINETIS_LPUART0 + bool "Low power LPUART0" + default n + depends on KINETIS_HAVE_LPUART0 + select OTHER_UART_SERIALDRIVER + select KINETIS_LPUART + ---help--- + Support the low power UART0 + +config KINETIS_LPUART1 + bool "Low power LPUART1" + default n + depends on KINETIS_HAVE_LPUART1 + select OTHER_UART_SERIALDRIVER + select KINETIS_LPUART + ---help--- + Support the low power UART1 + config KINETIS_ENET bool "Ethernet" default n @@ -839,6 +897,10 @@ config KINETIS_SD4BIT_FREQ endif endmenu # Kinetis SDHC Configuration +# +# MCU serial peripheral driver? +# + menu "Kinetis UART Configuration" config KINETIS_UARTFIFOS @@ -847,3 +909,159 @@ config KINETIS_UARTFIFOS depends on KINETIS_UART0 endmenu # Kinetis UART Configuration + +menu "Kinetis LPUART0 Configuration" + depends on KINETIS_LPUART0 + +config LPUART0_RXBUFSIZE + int "Receive buffer size" + default 256 + ---help--- + Characters are buffered as they are received. This specifies + the size of the receive buffer. + +config LPUART0_TXBUFSIZE + int "Transmit buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specifies + the size of the transmit buffer. + +config LPUART0_BAUD + int "BAUD rate" + default 115200 + ---help--- + The configured BAUD of the UART. + +config LPUART0_BITS + int "Character size" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config LPUART0_PARITY + int "Parity setting" + range 0 2 + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config LPUART0_2STOP + int "use 2 stop bits" + default 0 + ---help--- + 1=Two stop bits + +config LPUART0_IFLOWCONTROL + bool "LPUART0 RTS flow control" + default n + select SERIAL_IFLOWCONTROL + ---help--- + Enable LPUART0 RTS flow control + +config LPUART0_OFLOWCONTROL + bool "LPUART0 CTS flow control" + default n + select SERIAL_OFLOWCONTROL + ---help--- + Enable LPUART0 CTS flow control + +config LPUART0_DMA + bool "LPUART0 DMA support" + default n + select SERIAL_DMA + ---help--- + Enable DMA transfers on LPUART0 + +endmenu # Kinetis LPUART0 Configuration + +menu "Kinetis LPUART1 Configuration" + depends on KINETIS_LPUART1 + +config LPUART1_RXBUFSIZE + int "Receive buffer size" + default 256 + ---help--- + Characters are buffered as they are received. This specifies + the size of the receive buffer. + +config LPUART1_TXBUFSIZE + int "Transmit buffer size" + default 256 + ---help--- + Characters are buffered before being sent. This specifies + the size of the transmit buffer. + +config LPUART1_BAUD + int "BAUD rate" + default 115200 + ---help--- + The configured BAUD of the UART. + +config LPUART1_BITS + int "Character size" + default 8 + ---help--- + The number of bits. Must be either 7 or 8. + +config LPUART1_PARITY + int "Parity setting" + range 0 2 + default 0 + ---help--- + 0=no parity, 1=odd parity, 2=even parity + +config LPUART1_2STOP + int "use 2 stop bits" + default 0 + ---help--- + 1=Two stop bits + +config LPUART1_IFLOWCONTROL + bool "LPUART1 RTS flow control" + default n + select SERIAL_IFLOWCONTROL + ---help--- + Enable LPUART1 RTS flow control + +config LPUART1_OFLOWCONTROL + bool "LPUART1 CTS flow control" + default n + select SERIAL_OFLOWCONTROL + ---help--- + Enable LPUART1 CTS flow control + +config LPUART1_DMA + bool "LPUART1 DMA support" + default n + select SERIAL_DMA + ---help--- + Enable DMA transfers on LPUART1 + +endmenu # Kinetis LPUART1 Configuration + +choice + prompt "Kinetis LPUART Serial Console" + default NO_LPUART_SERIAL_CONSOLE + depends on DEV_CONSOLE && KINETIS_LPUART + +config LPUART0_SERIAL_CONSOLE + bool "Use LPUART0 as the serial console" + depends on KINETIS_LPUART0 + select OTHER_SERIAL_CONSOLE + ---help--- + Use the LPUART0 device as the serial console + +config LPUART1_SERIAL_CONSOLE + bool "Use LPUART1 as the serial console" + depends on KINETIS_LPUART1 + select OTHER_SERIAL_CONSOLE + ---help--- + Use the LPUART1 device as the serial console + +config NO_LPUART_SERIAL_CONSOLE + bool "No LPUART serial console" + ---help--- + No serial LPUART based console OR some other serial device provides the serial console + +endchoice # Kinetis LPUART Serial Console diff --git a/arch/arm/src/kinetis/Make.defs b/arch/arm/src/kinetis/Make.defs index bd4eed06484..a484a8fe4e9 100644 --- a/arch/arm/src/kinetis/Make.defs +++ b/arch/arm/src/kinetis/Make.defs @@ -162,6 +162,10 @@ ifeq ($(CONFIG_I2C),y) CHIP_CSRCS += kinetis_i2c.c endif +ifeq ($(CONFIG_KINETIS_LPUART),y) +CHIP_CSRCS += kinetis_lpserial.c +endif + ifeq ($(CONFIG_RTC),y) CHIP_CSRCS += kinetis_rtc.c ifeq ($(CONFIG_RTC_DRIVER),y) diff --git a/arch/arm/src/kinetis/chip/kinetis_lpuart.h b/arch/arm/src/kinetis/chip/kinetis_lpuart.h new file mode 100644 index 00000000000..eafd18f122c --- /dev/null +++ b/arch/arm/src/kinetis/chip/kinetis_lpuart.h @@ -0,0 +1,222 @@ +/**************************************************************************************************** + * arch/arm/src/kinetis/chip/kinetis_lpuart.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_KINETIS_CHIP_KINETIS_LPUART_H +#define __ARCH_ARM_SRC_KINETIS_CHIP_KINETIS_LPUART_H + +/**************************************************************************************************** + * Included Files + ****************************************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************************************** + * Pre-processor Definitions + ****************************************************************************************************/ + +/* Register Offsets *********************************************************************************/ + +#define KINETIS_LPUART_BAUD_OFFSET 0x0000 /* Low Power UART Baud Rate Register */ +#define KINETIS_LPUART_STAT_OFFSET 0x0004 /* Low Power UART Status Register */ +#define KINETIS_LPUART_CTRL_OFFSET 0x0008 /* Low Power UART Control Register */ +#define KINETIS_LPUART_DATA_OFFSET 0x000c /* Low Power UART Data Register */ +#define KINETIS_LPUART_MATCH_OFFSET 0x000c /* Low Power UART Match Address Register */ +#define KINETIS_LPUART_MODIR_OFFSET 0x000c /* Low Power UART Modem IrDA Register */ + +/* Register Addresses *******************************************************************************/ + +#define KINETIS_LPUART0_BAUD (KINETIS_LPUART0_BASE+KINETIS_LPUART_BAUD_OFFSET) +#define KINETIS_LPUART0_STAT (KINETIS_LPUART0_BASE+KINETIS_LPUART_STAT_OFFSET) +#define KINETIS_LPUART0_CTRL (KINETIS_LPUART0_BASE+KINETIS_LPUART_CTRL_OFFSET) +#define KINETIS_LPUART0_DATA (KINETIS_LPUART0_BASE+KINETIS_LPUART_DATA_OFFSET) +#define KINETIS_LPUART0_MATCH (KINETIS_LPUART0_BASE+KINETIS_LPUART_MATCH_OFFSET) +#define KINETIS_LPUART0_MODIR (KINETIS_LPUART0_BASE+KINETIS_LPUART_MODIR_OFFSET) + +/* Register Bit Definitions *************************************************************************/ + +/* Low Power UART Baud Rate Register */ + +#define LPUART_BAUD_SBR_SHIFT (0) /* Bits 0-12: Baud Rate Modulo Divisor */ +#define LPUART_BAUD_SBR_MASK (0x1fff << LPUART_BAUD_SBR_SHIFT) +# define LPUART_BAUD_SBR(n) (((n) & 0x1fff) << LPUART_BAUD_SBR_SHIFT) /* n= 1..8191*/ +#define LPUART_BAUD_SBNS (1 << 13) /* Bit 13: Stop Bit Number Select */ +#define LPUART_BAUD_RXEDGIE (1 << 14) /* Bit 14: RX Input Active Edge Interrupt Enable */ +#define LPUART_BAUD_LBKDIE (1 << 15) /* Bit 15: LIN Break Detect Interrupt Enable */ +#define LPUART_BAUD_RESYNCDIS (1 << 16) /* Bit 16: Resynchronizations Disable */ +#define LPUART_BAUD_BOTHEDGE (1 << 17) /* Bit 17: Both Edge Sampling */ +#define LPUART_BAUD_MATCFG_SHIFT (18) /* Bits 18-19: Match Configuration */ +#define LPUART_BAUD_MATCFG_MASK (3 << LPUART_BAUD_MATCFG_SHIFT) +# define LPUART_BAUD_MATCFG_AMW (0 << LPUART_BAUD_MATCFG_SHIFT) /* Address Match Wakeup */ +# define LPUART_BAUD_MATCFG_IMW (1 << LPUART_BAUD_MATCFG_SHIFT) /* Idle Match Wakeup */ +# define LPUART_BAUD_MATCFG_MONOFF (2 << LPUART_BAUD_MATCFG_SHIFT) /* Match On and Match Off */ +# define LPUART_BAUD_MATCFG_RWU (3 << LPUART_BAUD_MATCFG_SHIFT) /* Enables RWU on Data Match and Match On/Off for transmitter CTS input */ + /* Bit 20: Reserved */ +#define LPUART_BAUD_RDMAE (1 << 21) /* Bit 21: Receiver Full DMA Enable */ + /* Bit 22: Reserved */ +#define LPUART_BAUD_TDMAE (1 << 23) /* Bit 23: Transmitter DMA Enable */ +#define LPUART_BAUD_OSR_SHIFT (24) /* Bits 24-28: Over Sampling Ratio */ +#define LPUART_BAUD_OSR_MASK (0x1f << LPUART_BAUD_OSR_SHIFT) +#define LPUART_BAUD_OSR(n) ((((n)-1) & 0x1f) << LPUART_BAUD_OSR_SHIFT) /* n=4..32 */ +#define LPUART_BAUD_M10 (1 << 29) /* Bit 29: 10-bit Mode select */ +#define LPUART_BAUD_MAEN2 (1 << 30) /* Bit 30: Match Address Mode Enable 2 */ +#define LPUART_BAUD_MAEN1 (1 << 31) /* Bit 31: Match Address Mode Enable 1 */ + +/* Low Power UART Status Register */ + + /* Bits 0-13: Reserved */ +#define LPUART_STAT_MA2F (1 << 14) /* Match 2 Flag */ +#define LPUART_STAT_MA1F (1 << 15) /* Match 1 Flag */ +#define LPUART_STAT_PF (1 << 16) /* Parity Error Flag */ +#define LPUART_STAT_FE (1 << 17) /* Framing Error Flag */ +#define LPUART_STAT_NF (1 << 18) /* Noise Flag */ +#define LPUART_STAT_OR (1 << 19) /* Receiver Overrun Flag */ +#define LPUART_STAT_IDLE (1 << 20) /* Idle Line Flag */ +#define LPUART_STAT_RDRF (1 << 21) /* Receive Data Register Full Flag */ +#define LPUART_STAT_TC (1 << 22) /* Transmission Complete Flag */ +#define LPUART_STAT_TDRE (1 << 23) /* Transmit Data Register Empty Flag */ +#define LPUART_STAT_RAF (1 << 24) /* Receiver Active Flag */ +#define LPUART_STAT_LBKDE (1 << 25) /* LIN Break Detection Enable */ +#define LPUART_STAT_BRK13 (1 << 26) /* Break Character Generation Length */ +#define LPUART_STAT_RWUID (1 << 27) /* Receive Wake Up Idle Detect */ +#define LPUART_STAT_RXINV (1 << 28) /* Receive Data Inversion */ +#define LPUART_STAT_MSBF (1 << 29) /* MSB First */ +#define LPUART_STAT_RXEDGIF (1 << 30) /* LPUART_RX Pin Active Edge Interrupt Flag */ +#define LPUART_STAT_LBKDIF (1 << 31) /* LIN Break Detect Interrupt Flag */ + +/* Low Power UART Control Register */ + +#define LPUART_CTRL_PT (1 << 0) /* Bit 0: Parity Type */ +#define LPUART_CTRL_PE (1 << 1) /* Bit 1: Parity Enable */ +#define LPUART_CTRL_ILT (1 << 2) /* Bit 2: Idle Line Type Select */ +#define LPUART_CTRL_WAKE (1 << 3) /* Bit 3: Receiver Wakeup Method Select */ +#define LPUART_CTRL_M (1 << 4) /* Bit 4: 9-Bit or 8-Bit Mode Select */ +#define LPUART_CTRL_RSRC (1 << 5) /* Bit 5: Receiver Source Select */ +#define LPUART_CTRL_DOZEEN (1 << 6) /* Bit 6: Doze Enable */ +#define LPUART_CTRL_LOOPS (1 << 7) /* Bit 7: Loop Mode Select */ +#define LPUART_CTRL_IDLECFG_SHIFT (8) /* Bits 8-10: Idle Configuration */ +#define LPUART_CTRL_IDLECFG_MASK (3 << LPUART_CTRL_IDLECFG_SHIFT) +# define LPUART_CTRL_IDLECFG_1 (0 << LPUART_CTRL_IDLECFG_SHIFT) /* 1 idle character */ +# define LPUART_CTRL_IDLECFG_2 (1 << LPUART_CTRL_IDLECFG_SHIFT) /* 2 idle characters */ +# define LPUART_CTRL_IDLECFG_4 (2 << LPUART_CTRL_IDLECFG_SHIFT) /* 4 idle characters */ +# define LPUART_CTRL_IDLECFG_8 (3 << LPUART_CTRL_IDLECFG_SHIFT) /* 8 idle characters */ +# define LPUART_CTRL_IDLECFG_16 (4 << LPUART_CTRL_IDLECFG_SHIFT) /* 16 idle characters */ +# define LPUART_CTRL_IDLECFG_32 (5 << LPUART_CTRL_IDLECFG_SHIFT) /* 32 idle characters */ +# define LPUART_CTRL_IDLECFG_64 (6 << LPUART_CTRL_IDLECFG_SHIFT) /* 64 idle characters */ +# define LPUART_CTRL_IDLECFG_128 (7 << LPUART_CTRL_IDLECFG_SHIFT) /* 128 idle characters */ + /* Bits 11-13: Reserved */ +#define LPUART_CTRL_MA2IE (1 << 14) /* Bit 14: Match 2 Interrupt Enable */ +#define LPUART_CTRL_MA1IE (1 << 15) /* Bit 15: Match 1 Interrupt Enable */ +#define LPUART_CTRL_SBK (1 << 16) /* Bit 16: Send Break */ +#define LPUART_CTRL_RWU (1 << 17) /* Bit 17: Receiver Wakeup Control */ +#define LPUART_CTRL_RE (1 << 18) /* Bit 18: Receiver Enable */ +#define LPUART_CTRL_TE (1 << 19) /* Bit 19: Transmitter Enable */ +#define LPUART_CTRL_ILIE (1 << 20) /* Bit 20: Idle Line Interrupt Enable */ +#define LPUART_CTRL_RIE (1 << 21) /* Bit 21: Receiver Interrupt Enable */ +#define LPUART_CTRL_TCIE (1 << 22) /* Bit 22: Transmission Complete Interrupt Enable for */ +#define LPUART_CTRL_TIE (1 << 23) /* Bit 23: Transmit Interrupt Enable */ +#define LPUART_CTRL_PEIE (1 << 24) /* Bit 24: Parity Error Interrupt Enable */ +#define LPUART_CTRL_FEIE (1 << 25) /* Bit 25: Framing Error Interrupt Enable */ +#define LPUART_CTRL_NEIE (1 << 26) /* Bit 26: Noise Error Interrupt Enable */ +#define LPUART_CTRL_ORIE (1 << 27) /* Bit 27: Overrun Interrupt Enable */ +#define LPUART_CTRL_TXINV (1 << 28) /* Bit 28: Transmit Data Inversion */ +#define LPUART_CTRL_TXDIR (1 << 29) /* Bit 29: LPUART_TX Pin Direction in Single-Wire Mode */ +#define LPUART_CTRL_R9T8 (1 << 30) /* Bit 30: Receive Bit 9 / Transmit Bit 8 */ +#define LPUART_CTRL_R8T9 (1 << 31) /* Bit 31: Receive Bit 8 / Transmit Bit 9 */ + +/* Low Power UART Data Register */ + +#define LPUART_DATA_SHIFT (0) /* Bits 0-9: Read receive/ write transmit data */ +#define LPUART_DATA_MASK (0x3ff << LPUART_DATA_SHIFT) +#define LPUART_DATA8(n) (((n) & 0xff) << LPUART_DATA_SHIFT) +#define LPUART_DATA9(n) (((n) & 0x1ff) << LPUART_DATA_SHIFT) +#define LPUART_DATA10(n) (((n) & 0x3ff) << LPUART_DATA_SHIFT) +#define LPUART_DATA_R0T0 (1 << 0) /* Bit 0: Read receive data buffer 0 or write transmit data buffer 0 */ +#define LPUART_DATA_R1T1 (1 << 1) /* Bit 1: Read receive data buffer 1 or write transmit data buffer 1 */ +#define LPUART_DATA_R2T2 (1 << 2) /* Bit 2: Read receive data buffer 2 or write transmit data buffer 2 */ +#define LPUART_DATA_R3T3 (1 << 3) /* Bit 3: Read receive data buffer 3 or write transmit data buffer 3 */ +#define LPUART_DATA_R4T4 (1 << 4) /* Bit 4: Read receive data buffer 4 or write transmit data buffer 4 */ +#define LPUART_DATA_R5T5 (1 << 5) /* Bit 5: Read receive data buffer 5 or write transmit data buffer 5 */ +#define LPUART_DATA_R6T6 (1 << 6) /* Bit 6: Read receive data buffer 6 or write transmit data buffer 6 */ +#define LPUART_DATA_R7T7 (1 << 7) /* Bit 7: Read receive data buffer 7 or write transmit data buffer 7 */ +#define LPUART_DATA_R8T8 (1 << 8) /* Bit 8: Read receive data buffer 8 or write transmit data buffer 8 */ +#define LPUART_DATA_R9T9 (1 << 9) /* Bit 9: Read receive data buffer 9 or write transmit data buffer 9 */ + /* Bit 10: Reserved */ +#define LPUART_DATA_IDLINE (1 << 11) /* Bit 11: Idle Line */ +#define LPUART_DATA_RXEMPT (1 << 12) /* Bit 12: Receive Buffer Empty */ +#define LPUART_DATA_FRETSC (1 << 13) /* Bit 13: Frame Error / Transmit Special Character */ +#define LPUART_DATA_PARITYE (1 << 14) /* Bit 14: The current received dataword contained in DATA[R9:R0] was received with a parity error */ +#define LPUART_DATA_NOISY (1 << 15) /* Bit 15: The current received dataword contained in DATA[R9:R0] was received with noise */ + /* Bits 16-31: This field is reserved */ + +/* Low Power UART Match Address Register */ + +#define LPUART_MATCH_MA1_SHIFT (0) /* Bits 0-9: Match Address 1 */ +#define LPUART_MATCH_MA1_MASK (0x3ff << LPUART_MATCH_MA1_SHIFT) + /* Bits 10-15: Reserved */ +#define LPUART_MATCH_MA2_SHIFT (16) /* Bits 16-25: Match Address 2 */ +#define LPUART_MATCH_MA2_MASK (0x3ff << LPUART_MATCH_MA2_SHIFT) + /* Bits 26-31: Reserved */ + +/* Low Power UART Modem IrDA Register */ + +#define LPUART_MODIR_TXCTSE (1 << 0) /* Bit 0: Transmitter clear-to-send enable */ +#define LPUART_MODIR_TXRTSE (1 << 1) /* Bit 1: Transmitter request-to-send enable */ +#define LPUART_MODIR_TXRTSPOL (1 << 2) /* Bit 2: Transmitter request-to-send polarity */ +#define LPUART_MODIR_RXRTSE (1 << 3) /* Bit 3: Receiver request-to-send enable */ +#define LPUART_MODIR_TXCTSC (1 << 4) /* Bit 4: Transmit CTS Configuration */ +#define LPUART_MODIR_TXCTSSRC (1 << 5) /* Bit 5: Transmit CTS Source */ + /* Bits 6-15: Reserved */ +#define LPUART_MODIR_TNP_SHIFT (16) /* Bits 16-17: Transmitter narrow pulse */ +#define LPUART_MODIR_TNP_MASK (3 << LPUART_MODIR_TNP_SHIFT) +# define LPUART_MODIR_TNP(n) (((n)-1) << LPUART_MODIR_TNP_SHIFT) /* n=1-4 */ +#define LPUART_MODIR_IREN (1 << 18) /* Bit 18: Infrared enable */ + /* Bits 19-31: Reserved */ + +/**************************************************************************************************** + * Public Types + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Data + ****************************************************************************************************/ + +/**************************************************************************************************** + * Public Functions + ****************************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_KINETIS_CHIP_KINETIS_LPUART_H */ diff --git a/arch/arm/src/kinetis/chip/kinetis_sim.h b/arch/arm/src/kinetis/chip/kinetis_sim.h index d1a98b3b5a1..3e6cb6a6efb 100644 --- a/arch/arm/src/kinetis/chip/kinetis_sim.h +++ b/arch/arm/src/kinetis/chip/kinetis_sim.h @@ -1140,19 +1140,25 @@ /* System Clock Divider Register 2 */ #if defined(KINETIS_SIM_HAS_CLKDIV2_USBFRAC) -# define SIM_CLKDIV2_USBFRAC (1 << 0) /* Bit 0: USB clock divider fraction */ +# define SIM_CLKDIV2_USBFRAC_SHIFT (0) /* Bit 0: USB clock divider fraction */ +# define SIM_CLKDIV2_USBFRAC_MASK (1 << SIM_CLKDIV2_USBFRAC_SHIFT) +# define SIM_CLKDIV2_USBFRAC(n) ((((n)-1) & 1) << SIM_CLKDIV2_USBFRAC_SHIFT) /* n=1..2 */ #endif #if defined(KINETIS_SIM_HAS_CLKDIV2_USBDIV) # define SIM_CLKDIV2_USBDIV_SHIFT (1) /* Bits 1-3: USB clock divider divisor */ # define SIM_CLKDIV2_USBDIV_MASK (7 << SIM_CLKDIV2_USBDIV_SHIFT) +# define SIM_CLKDIV2_USBDIV(n) ((((n)-1) & 7) << SIM_CLKDIV2_USBDIV_SHIFT) /* n=1..8 */ #endif /* Bits 4-7: Reserved */ #if defined(KINETIS_SIM_HAS_CLKDIV2_USBHSFRAC) -# define SIM_CLKDIV2_USBHSFRAC (1 << 8) /* Bit 8: USB HS clock divider fraction */ +# define SIM_CLKDIV2_USBHSFRAC_SHIFT (8) /* Bit 8: USB HS clock divider fraction */ +# define SIM_CLKDIV2_USBHSFRAC_MASK (1 << SIM_CLKDIV2_USBHSFRAC_SHIFT) +# define SIM_CLKDIV2_USBHSFRAC(n) ((((n)-1) & 1) << SIM_CLKDIV2_USBHSFRAC_SHIFT) /* n=1..2 */ #endif #if defined(KINETIS_SIM_HAS_CLKDIV2_USBHSDIV) # define SIM_CLKDIV2_USBHSDIV_SHIFT (9) /* Bits 1-3: USB HS clock divider divisor */ # define SIM_CLKDIV2_USBHSDIV_MASK (7 << SIM_CLKDIV2_USBHSDIV_SHIFT) +# define SIM_CLKDIV2_USBHSDIV(n) ((((n)-1) & 7) << SIM_CLKDIV2_USBHSDIV_SHIFT) /* n=1..8 */ #endif #if defined(KINETIS_SIM_HAS_CLKDIV2_I2SFRAC) # define SIM_CLKDIV2_I2SFRAC_SHIFT (8) /* Bits 8-15: I2S clock divider fraction */ @@ -1259,7 +1265,9 @@ /* System Clock Divider Register 3 */ # if defined(KINETIS_SIM_HAS_CLKDIV3_PLLFLLFRAC) -# define SIM_CLKDIV3_PLLFLLFRAC (1 << 0) /* Bit 0: PLLFLL clock divider fraction */ +# define SIM_CLKDIV3_PLLFLLFRAC_SHIFT (0) /* Bit 0: PLLFLL clock divider fraction */ +# define SIM_CLKDIV3_PLLFLLFRAC_MASK (1 << SIM_CLKDIV3_PLLFLLFRAC_SHIFT) +# define SIM_CLKDIV3_PLLFLLFRAC(n) ((((n)-1) & 1) << SIM_CLKDIV3_PLLFLLFRAC_SHIFT) /* n=1..2 */ # endif # if defined(KINETIS_SIM_HAS_CLKDIV3_PLLFLLDIV) # define SIM_CLKDIV3_PLLFLLDIV_SHIFT (1) /* Bits 1-3: PLLFLL clock divider divisor */ @@ -1271,7 +1279,9 @@ /* System Clock Divider Register 4 */ # if defined(KINETIS_SIM_HAS_CLKDIV4_TRACEFRAC) -# define SIM_CLKDIV4_TRACEFRAC (1 << 0) /* Bit 0: Trace clock divider fraction */ +# define SIM_CLKDIV4_TRACEFRAC_SHIFTS (0) /* Bit 0: Trace clock divider fraction */ +# define SIM_CLKDIV4_TRACEFRAC_MASK (1 << SIM_CLKDIV4_TRACEFRAC_SHIFTS) +# define SIM_CLKDIV4_TRACEFRAC(n) ((((n)-1) & 1) << SIM_CLKDIV4_TRACEFRAC_SHIFTS) /* n=1..2 */ # endif # if defined(KINETIS_SIM_HAS_CLKDIV4_TRACEDIV) # define SIM_CLKDIV4_TRACEDIV_SHIFT (1) /* Bits 1-3: Trace clock divider divisor */ diff --git a/arch/arm/src/kinetis/chip/kinetis_uart.h b/arch/arm/src/kinetis/chip/kinetis_uart.h index 537332ee786..d7296ce7066 100644 --- a/arch/arm/src/kinetis/chip/kinetis_uart.h +++ b/arch/arm/src/kinetis/chip/kinetis_uart.h @@ -1,8 +1,9 @@ /************************************************************************************ * arch/arm/src/kinetis/chip/kinetis_uart.h * - * Copyright (C) 2011, 2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011, 2016-2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -293,7 +294,7 @@ #define UART_BDH_SBR_SHIFT (0) /* Bits 0-4: MS Bits 8-13 of the UART Baud Rate Bits */ #define UART_BDH_SBR_MASK (31 << UART_BDH_SBR_SHIFT) - /* Bit 5: Reserved */ +#define UART_BDH_SBNS (1 << 5) /* Bit 5: Stop Bit Number Select */ #define UART_BDH_RXEDGIE (1 << 6) /* Bit 6: RxD Input Active Edge Interrupt Enable */ #define UART_BDH_LBKDIE (1 << 7) /* Bit 7: LIN Break Detect Interrupt Enable */ diff --git a/arch/arm/src/kinetis/kinetis.h b/arch/arm/src/kinetis/kinetis.h index b4832274c33..1688014592c 100644 --- a/arch/arm/src/kinetis/kinetis.h +++ b/arch/arm/src/kinetis/kinetis.h @@ -1,8 +1,9 @@ /************************************************************************************ * arch/arm/src/kinetis/kinetis.h * - * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011, 2013, 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -364,6 +365,18 @@ void kinetis_lowsetup(void); void kinetis_uartreset(uintptr_t uart_base); #endif +/**************************************************************************** + * Name: kinetis_lpuartreset + * + * Description: + * Reset a UART. + * + ****************************************************************************/ + +#ifdef HAVE_LPUART_DEVICE +void kinetis_lpuartreset(uintptr_t uart_base); +#endif + /**************************************************************************** * Name: kinetis_uartconfigure * @@ -374,7 +387,22 @@ void kinetis_uartreset(uintptr_t uart_base); #ifdef HAVE_UART_DEVICE void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud, uint32_t clock, - unsigned int parity, unsigned int nbits); + unsigned int parity, unsigned int nbits, + unsigned int stop2); +#endif + +/**************************************************************************** + * Name: kinetis_lpuartconfigure + * + * Description: + * Configure a UART as a RS-232 UART. + * + ****************************************************************************/ + +#ifdef HAVE_LPUART_DEVICE +void kinetis_lpuartconfigure(uintptr_t uart_base, uint32_t baud, uint32_t clock, + unsigned int parity, unsigned int nbits, + unsigned int stop2); #endif /************************************************************************************ diff --git a/arch/arm/src/kinetis/kinetis_clockconfig.c b/arch/arm/src/kinetis/kinetis_clockconfig.c index f4852dbb007..eba8b4fc651 100644 --- a/arch/arm/src/kinetis/kinetis_clockconfig.c +++ b/arch/arm/src/kinetis/kinetis_clockconfig.c @@ -2,7 +2,8 @@ * arch/arm/src/kinetis/kinetis_clockconfig.c * * Copyright (C) 2011, 2016-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -192,7 +193,8 @@ static inline void kinesis_portclocks(void) void kinetis_pllconfig(void) { -#if defined(SIM_SCGC4_LLWU) +#if defined(SIM_SCGC4_LLWU) || defined(BOARD_SOPT2_PLLFLLSEL) || \ + defined(BOARD_SIM_CLKDIV3_FREQ) uint32_t regval32; #endif uint8_t regval8; @@ -346,6 +348,27 @@ void kinetis_pllconfig(void) while ((getreg8(KINETIS_MCG_S) & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL); /* We are now running in PLL Engaged External (PEE) mode. */ + + /* Do we have BOARD_SOPT2_PLLFLLSEL */ + +#if defined(BOARD_SOPT2_PLLFLLSEL) + /* Set up the SOPT2[PLLFLLSEL] */ + + regval32 = getreg32(KINETIS_SIM_SOPT2); + regval32 &= ~SIM_SOPT2_PLLFLLSEL_MASK; + regval32 |= BOARD_SOPT2_PLLFLLSEL; + putreg32(regval32, KINETIS_SIM_SOPT2); +#endif + +#if defined(BOARD_SIM_CLKDIV3_FREQ) + /* Set up the SIM_CLKDIV3 [PLLFLLFRAC, PLLFLLDIV] */ + + regval32 = getreg32(KINETIS_SIM_CLKDIV3); + regval32 &= ~(SIM_CLKDIV3_PLLFLLFRAC_MASK | SIM_CLKDIV3_PLLFLLDIV_MASK); + regval32 |= (SIM_CLKDIV3_PLLFLLFRAC(BOARD_SIM_CLKDIV3_PLLFLLFRAC) | + SIM_CLKDIV3_PLLFLLDIV(BOARD_SIM_CLKDIV3_PLLFLLDIV)); + putreg32(regval32, KINETIS_SIM_CLKDIV3); +#endif } /**************************************************************************** diff --git a/arch/arm/src/kinetis/kinetis_config.h b/arch/arm/src/kinetis/kinetis_config.h index 9ace28b7438..bb134ed5f87 100644 --- a/arch/arm/src/kinetis/kinetis_config.h +++ b/arch/arm/src/kinetis/kinetis_config.h @@ -1,8 +1,9 @@ /************************************************************************************ * arch/arm/src/kinetis/kinetis_config.h * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,7 +51,11 @@ ************************************************************************************/ /* Configuration *********************************************************************/ -/* Make that no unsupported UARTs are enabled */ +/* Make sure that no unsupported UARTs are enabled */ + +#ifndef KINETIS_NLPUART +# define KINETIS_NLPUART 0 +#endif #ifndef KINETIS_NISO7816 # define KINETIS_NISO7816 0 @@ -75,69 +80,127 @@ # endif #endif +#if KINETIS_NLPUART < 1 +# undef CONFIG_KINETIS_LPUART0 +#endif + /* Are any UARTs enabled? */ #undef HAVE_UART_DEVICE #if defined(CONFIG_KINETIS_UART0) || defined(CONFIG_KINETIS_UART1) || \ defined(CONFIG_KINETIS_UART2) || defined(CONFIG_KINETIS_UART3) || \ - defined(CONFIG_KINETIS_UART4) || defined(CONFIG_KINETIS_UART5) + defined(CONFIG_KINETIS_UART4) || defined(CONFIG_KINETIS_UART5) || \ + defined(CONFIG_KINETIS_LPUART0) # define HAVE_UART_DEVICE 1 #endif +#undef HAVE_LPUART_DEVICE +#if defined(CONFIG_KINETIS_LPUART0) +# define HAVE_LPUART_DEVICE 1 +#endif + /* Is there a serial console? There should be at most one defined. It could be on * any UARTn, n=0,1,2,3,4,5 */ -#if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART0) -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 -#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART1) -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 -#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART2) -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 -#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART3) -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 -#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART4) -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 -#elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART5) -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# define HAVE_SERIAL_CONSOLE 1 +#undef HAVE_UART_CONSOLE +#undef HAVE_LPUART_CONSOLE + +#if defined(CONFIG_CONSOLE_SYSLOG) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE #else -# undef CONFIG_UART0_SERIAL_CONSOLE -# undef CONFIG_UART1_SERIAL_CONSOLE -# undef CONFIG_UART2_SERIAL_CONSOLE -# undef CONFIG_UART3_SERIAL_CONSOLE -# undef CONFIG_UART4_SERIAL_CONSOLE -# undef CONFIG_UART5_SERIAL_CONSOLE -# undef HAVE_SERIAL_CONSOLE +# if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART0) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART1) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART2) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART3) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART4) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_UART5) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_UART_CONSOLE 1 +# elif defined(CONFIG_LPUART0_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_LPUART0) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# define HAVE_LPUART_CONSOLE 1 +# elif defined(CONFIG_LPUART1_SERIAL_CONSOLE) && defined(CONFIG_KINETIS_LPUART1) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# define HAVE_LPUART_CONSOLE 1 +# else +# ifdef CONFIG_DEV_CONSOLE +# warning "No valid CONFIG_[LP]UART[n]_SERIAL_CONSOLE Setting" +# endif +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_LPUART0_SERIAL_CONSOLE +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# endif #endif /* Check UART flow control (Not yet supported) */ @@ -148,6 +211,8 @@ # undef CONFIG_UART3_FLOWCONTROL # undef CONFIG_UART4_FLOWCONTROL # undef CONFIG_UART5_FLOWCONTROL +# undef CONFIG_LPUART0_FLOWCONTROL +# undef CONFIG_LPUART1_FLOWCONTROL /* UART FIFO support is not fully implemented. * @@ -183,6 +248,12 @@ #ifndef CONFIG_KINETIS_UART5PRIO # define CONFIG_KINETIS_UART5PRIO NVIC_SYSH_PRIORITY_DEFAULT #endif +#ifndef CONFIG_KINETIS_LPUART0PRIO +# define CONFIG_KINETIS_LPUART0PRIO NVIC_SYSH_PRIORITY_DEFAULT +#endif +#ifndef CONFIG_KINETIS_LPUART1PRIO +# define CONFIG_KINETIS_LPUART1PRIO NVIC_SYSH_PRIORITY_DEFAULT +#endif /* Ethernet controller configuration */ diff --git a/arch/arm/src/kinetis/kinetis_lowputc.c b/arch/arm/src/kinetis/kinetis_lowputc.c index ec85713c933..0eee3c2fe53 100644 --- a/arch/arm/src/kinetis/kinetis_lowputc.c +++ b/arch/arm/src/kinetis/kinetis_lowputc.c @@ -1,8 +1,9 @@ /**************************************************************************** * arch/arm/src/kinetis/kinetis_lowputc.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,6 +51,7 @@ #include "kinetis_config.h" #include "kinetis.h" #include "chip/kinetis_uart.h" +#include "chip/kinetis_lpuart.h" #include "chip/kinetis_sim.h" #include "chip/kinetis_pinmux.h" @@ -59,46 +61,85 @@ /* Select UART parameters for the selected console */ -#if defined(CONFIG_UART0_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART0_BASE -# define CONSOLE_FREQ BOARD_CORECLK_FREQ -# define CONSOLE_BAUD CONFIG_UART0_BAUD -# define CONSOLE_BITS CONFIG_UART0_BITS -# define CONSOLE_PARITY CONFIG_UART0_PARITY -#elif defined(CONFIG_UART1_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART1_BASE -# define CONSOLE_FREQ BOARD_CORECLK_FREQ -# define CONSOLE_BAUD CONFIG_UART1_BAUD -# define CONSOLE_BITS CONFIG_UART1_BITS -# define CONSOLE_PARITY CONFIG_UART1_PARITY -#elif defined(CONFIG_UART2_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART2_BASE -# define CONSOLE_FREQ BOARD_BUS_FREQ -# define CONSOLE_BAUD CONFIG_UART2_BAUD -# define CONSOLE_BITS CONFIG_UART2_BITS -# define CONSOLE_PARITY CONFIG_UART2_PARITY -#elif defined(CONFIG_UART3_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART3_BASE -# define CONSOLE_FREQ BOARD_BUS_FREQ -# define CONSOLE_BAUD CONFIG_UART3_BAUD -# define CONSOLE_BITS CONFIG_UART3_BITS -# define CONSOLE_PARITY CONFIG_UART3_PARITY -#elif defined(CONFIG_UART4_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART4_BASE -# define CONSOLE_FREQ BOARD_BUS_FREQ -# define CONSOLE_BAUD CONFIG_UART4_BAUD -# define CONSOLE_BITS CONFIG_UART4_BITS -# define CONSOLE_PARITY CONFIG_UART4_PARITY -#elif defined(CONFIG_UART5_SERIAL_CONSOLE) -# define CONSOLE_BASE KINETIS_UART5_BASE -# define CONSOLE_FREQ BOARD_BUS_FREQ -# define CONSOLE_BAUD CONFIG_UART5_BAUD -# define CONSOLE_BITS CONFIG_UART5_BITS -# define CONSOLE_PARITY CONFIG_UART5_PARITY -#elif defined(HAVE_SERIAL_CONSOLE) -# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" -#endif +#if defined(HAVE_UART_CONSOLE) +# if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART0_BASE +# define CONSOLE_FREQ BOARD_CORECLK_FREQ +# define CONSOLE_BAUD CONFIG_UART0_BAUD +# define CONSOLE_BITS CONFIG_UART0_BITS +# define CONSOLE_2STOP CONFIG_UART0_2STOP +# define CONSOLE_PARITY CONFIG_UART0_PARITY +# elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART1_BASE +# define CONSOLE_FREQ BOARD_CORECLK_FREQ +# define CONSOLE_BAUD CONFIG_UART1_BAUD +# define CONSOLE_BITS CONFIG_UART1_BITS +# define CONSOLE_2STOP CONFIG_UART1_2STOP +# define CONSOLE_PARITY CONFIG_UART1_PARITY +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART2_BASE +# define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_BAUD CONFIG_UART2_BAUD +# define CONSOLE_BITS CONFIG_UART2_BITS +# define CONSOLE_2STOP CONFIG_UART2_2STOP +# define CONSOLE_PARITY CONFIG_UART2_PARITY +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART3_BASE +# define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_BAUD CONFIG_UART3_BAUD +# define CONSOLE_BITS CONFIG_UART3_BITS +# define CONSOLE_2STOP CONFIG_UART3_2STOP +# define CONSOLE_PARITY CONFIG_UART3_PARITY +# elif defined(CONFIG_UART4_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART4_BASE +# define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_BAUD CONFIG_UART4_BAUD +# define CONSOLE_BITS CONFIG_UART4_BITS +# define CONSOLE_2STOP CONFIG_UART4_2STOP +# define CONSOLE_PARITY CONFIG_UART4_PARITY +# elif defined(CONFIG_UART5_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_UART5_BASE +# define CONSOLE_FREQ BOARD_BUS_FREQ +# define CONSOLE_BAUD CONFIG_UART5_BAUD +# define CONSOLE_BITS CONFIG_UART5_BITS +# define CONSOLE_2STOP CONFIG_UART5_2STOP +# define CONSOLE_PARITY CONFIG_UART5_PARITY +# elif defined(HAVE_UART_CONSOLE) +# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +# endif +#elif defined(HAVE_LPUART_CONSOLE) +# if defined(CONFIG_LPUART0_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_LPUART0_BASE +# define CONSOLE_FREQ BOARD_LPUART0_FREQ +# define CONSOLE_BAUD CONFIG_LPUART0_BAUD +# define CONSOLE_PARITY CONFIG_LPUART0_PARITY +# define CONSOLE_BITS CONFIG_LPUART0_BITS +# define CONSOLE_2STOP CONFIG_LPUART0_2STOP +# elif defined(CONFIG_LPUART1_SERIAL_CONSOLE) +# define CONSOLE_BASE KINETIS_LPUART1_BASE +# define CONSOLE_FREQ BOARD_LPUART1_FREQ +# define CONSOLE_BAUD CONFIG_LPUART1_BAUD +# define CONSOLE_PARITY CONFIG_LPUART1_PARITY +# define CONSOLE_BITS CONFIG_LPUART1_BITS +# define CONSOLE_2STOP CONFIG_LPUART1_2STOP +# else +# error "No LPUART console is selected" +# endif +#endif /* HAVE_UART_CONSOLE */ + +#if defined(HAVE_LPUART_CONSOLE) +# if ((CONSOLE_FREQ / (CONSOLE_BAUD * 32)) > (LPUART_BAUD_SBR_MASK >> LPUART_BAUD_SBR_SHIFT)) +# error "LPUART Console: Baud rate not obtainable with this input clock!" +# endif +# define LPUART_BAUD_INIT (LPUART_BAUD_SBR_MASK | LPUART_BAUD_SBNS | \ + LPUART_BAUD_RXEDGIE | LPUART_BAUD_LBKDIE | \ + LPUART_BAUD_RESYNCDIS |LPUART_BAUD_BOTHEDGE | \ + LPUART_BAUD_MATCFG_MASK | LPUART_BAUD_RDMAE | \ + LPUART_BAUD_TDMAE | LPUART_BAUD_OSR_MASK | \ + LPUART_BAUD_M10 | LPUART_BAUD_MAEN2 | \ + LPUART_BAUD_MAEN2) +#endif /**************************************************************************** * Private Types ****************************************************************************/ @@ -141,20 +182,20 @@ static uint8_t g_sizemap[8] = {1, 4, 8, 16, 32, 64, 128, 0}; void up_lowputc(char ch) { -#if defined HAVE_UART_DEVICE && defined HAVE_SERIAL_CONSOLE -#ifdef CONFIG_KINETIS_UARTFIFOS +#if defined(HAVE_UART_CONSOLE) +# ifdef CONFIG_KINETIS_UARTFIFOS /* Wait until there is space in the TX FIFO: Read the number of bytes * currently in the FIFO and compare that to the size of the FIFO. If * there are fewer bytes in the FIFO than the size of the FIFO, then we * are able to transmit. */ -# error "Missing logic" -#else +# error "Missing logic" +# else /* Wait until the transmit data register is "empty" (TDRE). This state * depends on the TX watermark setting and may not mean that the transmit * buffer is truly empty. It just means that we can now add another - * characterto the transmit buffer without exceeding the watermark. + * character to the transmit buffer without exceeding the watermark. * * NOTE: UART0 has an 8-byte deep FIFO; the other UARTs have no FIFOs * (1-deep). There appears to be no way to know when the FIFO is not @@ -167,11 +208,18 @@ void up_lowputc(char ch) */ while ((getreg8(CONSOLE_BASE+KINETIS_UART_S1_OFFSET) & UART_S1_TDRE) == 0); -#endif +# endif /* Then write the character to the UART data register */ putreg8((uint8_t)ch, CONSOLE_BASE+KINETIS_UART_D_OFFSET); +} +#elif defined(HAVE_LPUART_CONSOLE) + while ((getreg32(CONSOLE_BASE + KINETIS_LPUART_STAT_OFFSET) & LPUART_STAT_TDRE) == 0); + + /* Then send the character */ + + putreg32((uint32_t)ch, CONSOLE_BASE + KINETIS_LPUART_DATA_OFFSET); #endif } @@ -180,7 +228,7 @@ void up_lowputc(char ch) * * Description: * This performs basic initialization of the UART used for the serial - * console. Its purpose is to get the console output availabe as soon + * console. Its purpose is to get the console output available as soon * as possible. * ****************************************************************************/ @@ -194,77 +242,113 @@ void kinetis_lowsetup(void) * 0-3 is enabled in the SCGC4 register. */ -#if defined(CONFIG_KINETIS_UART0) || defined(CONFIG_KINETIS_UART1) || \ - defined(CONFIG_KINETIS_UART2) || defined(CONFIG_KINETIS_UART3) +# if defined(CONFIG_KINETIS_UART0) || defined(CONFIG_KINETIS_UART1) || \ + defined(CONFIG_KINETIS_UART2) || defined(CONFIG_KINETIS_UART3) regval = getreg32(KINETIS_SIM_SCGC4); -# ifdef CONFIG_KINETIS_UART0 +# ifdef CONFIG_KINETIS_UART0 regval |= SIM_SCGC4_UART0; -# endif -# ifdef CONFIG_KINETIS_UART1 +# endif +# ifdef CONFIG_KINETIS_UART1 regval |= SIM_SCGC4_UART1; -# endif -# ifdef CONFIG_KINETIS_UART2 +# endif +# ifdef CONFIG_KINETIS_UART2 regval |= SIM_SCGC4_UART2; -# endif -# ifdef CONFIG_KINETIS_UART3 +# endif +# ifdef CONFIG_KINETIS_UART3 regval |= SIM_SCGC4_UART3; -# endif +# endif putreg32(regval, KINETIS_SIM_SCGC4); -#endif +# endif /* Clocking for UARTs 4-5 is enabled in the SCGC1 register. */ -#if defined(CONFIG_KINETIS_UART4) || defined(CONFIG_KINETIS_UART5) +# if defined(CONFIG_KINETIS_UART4) || defined(CONFIG_KINETIS_UART5) regval = getreg32(KINETIS_SIM_SCGC1); -# ifdef CONFIG_KINETIS_UART4 +# ifdef CONFIG_KINETIS_UART4 regval |= SIM_SCGC1_UART4; -# endif -# ifdef CONFIG_KINETIS_UART5 +# endif +# ifdef CONFIG_KINETIS_UART5 regval |= SIM_SCGC1_UART5; -# endif +# endif putreg32(regval, KINETIS_SIM_SCGC1); -#endif +# endif /* Configure UART pins for the all enabled UARTs */ -#ifdef CONFIG_KINETIS_UART0 +# ifdef CONFIG_KINETIS_UART0 kinetis_pinconfig(PIN_UART0_TX); kinetis_pinconfig(PIN_UART0_RX); -#endif -#ifdef CONFIG_KINETIS_UART1 +# endif +# ifdef CONFIG_KINETIS_UART1 kinetis_pinconfig(PIN_UART1_TX); kinetis_pinconfig(PIN_UART1_RX); -#endif -#ifdef CONFIG_KINETIS_UART2 +# endif +# ifdef CONFIG_KINETIS_UART2 kinetis_pinconfig(PIN_UART2_TX); kinetis_pinconfig(PIN_UART2_RX); -#endif -#ifdef CONFIG_KINETIS_UART3 +# endif +# ifdef CONFIG_KINETIS_UART3 kinetis_pinconfig(PIN_UART3_TX); kinetis_pinconfig(PIN_UART3_RX); -#endif -#ifdef CONFIG_KINETIS_UART4 +# endif +# ifdef CONFIG_KINETIS_UART4 kinetis_pinconfig(PIN_UART4_TX); kinetis_pinconfig(PIN_UART4_RX); -#endif -#ifdef CONFIG_KINETIS_UART5 +# endif +# ifdef CONFIG_KINETIS_UART5 kinetis_pinconfig(PIN_UART5_TX); kinetis_pinconfig(PIN_UART5_RX); -#endif +# endif /* Configure the console (only) now. Other UARTs will be configured * when the serial driver is opened. */ -#if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) +# if defined(HAVE_UART_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) - kinetis_uartconfigure(CONSOLE_BASE, CONSOLE_BAUD, CONSOLE_FREQ, - CONSOLE_PARITY, CONSOLE_BITS); -#endif + kinetis_uartconfigure(CONSOLE_BASE, CONSOLE_BAUD, CONSOLE_FREQ, \ + CONSOLE_PARITY, CONSOLE_BITS, CONSOLE_2STOP); +# endif +#endif /* HAVE_UART_DEVICE */ +#if HAVE_LPUART_DEVICE + + /* Clocking Source for LPUARTs 0 selected in SIM_SOPT2 */ + +# if defined(CONFIG_KINETIS_LPUART0) + regval = getreg32(KINETIS_SIM_SOPT2); + regval &= ~(SIM_SOPT2_LPUARTSRC_MASK); + regval |= BOARD_LPUART0_CLKSRC; + putreg32(regval, KINETIS_SIM_SOPT2); + + /* Clocking for LPUARTs 0-1 is enabled in the SCGC2 register. */ + + regval = getreg32(KINETIS_SIM_SCGC2); + regval |= SIM_SCGC2_LPUART0; + putreg32(regval, KINETIS_SIM_SCGC2); + +# endif + + /* Configure UART pins for the all enabled UARTs */ + +# ifdef CONFIG_KINETIS_LPUART0 + kinetis_pinconfig(PIN_LPUART0_TX); + kinetis_pinconfig(PIN_LPUART0_RX); +# endif + +# ifdef CONFIG_KINETIS_LPUART1 + kinetis_pinconfig(PIN_LPUART1_TX); + kinetis_pinconfig(PIN_LPUART1_RX); +# endif + +# if defined(HAVE_LPUART_CONSOLE) && !defined(CONFIG_SUPPRESS_LPUART_CONFIG) + + kinetis_lpuartconfigure(CONSOLE_BASE, CONSOLE_BAUD, CONSOLE_FREQ, \ + CONSOLE_PARITY, CONSOLE_BITS, CONSOLE_2STOP); +# endif #endif /* HAVE_UART_DEVICE */ } @@ -289,6 +373,27 @@ void kinetis_uartreset(uintptr_t uart_base) } #endif +/**************************************************************************** + * Name: kinetis_lpuartreset + * + * Description: + * Reset a UART. + * + ****************************************************************************/ + +#ifdef HAVE_LPUART_DEVICE +void kinetis_lpuartreset(uintptr_t uart_base) +{ + uint32_t regval; + + /* Just disable the transmitter and receiver */ + + regval = getreg32(uart_base+KINETIS_LPUART_CTRL_OFFSET); + regval &= ~(LPUART_CTRL_RE | LPUART_CTRL_TE); + putreg32(regval, uart_base+KINETIS_LPUART_CTRL_OFFSET); +} +#endif + /**************************************************************************** * Name: kinetis_uartconfigure * @@ -300,7 +405,7 @@ void kinetis_uartreset(uintptr_t uart_base) #ifdef HAVE_UART_DEVICE void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud, uint32_t clock, unsigned int parity, - unsigned int nbits) + unsigned int nbits, unsigned int stop2) { uint32_t sbr; uint32_t brfa; @@ -362,11 +467,16 @@ void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud, sbr = clock / (baud << 4); DEBUGASSERT(sbr < 0x2000); - /* Save the new baud divisor, retaining other bits in the UARTx_BDH - * register. + /* Save the new baud divisor and stop bits, retaining other bits in the + * UARTx_BDH register. */ - regval = getreg8(uart_base+KINETIS_UART_BDH_OFFSET) & UART_BDH_SBR_MASK; + regval = getreg8(uart_base+KINETIS_UART_BDH_OFFSET); + regval &= ~(UART_BDH_SBR_MASK | UART_BDH_SBNS); + if (stop2) + { + regval |= UART_BDH_SBNS; + } tmp = sbr >> 8; regval |= (((uint8_t)tmp) << UART_BDH_SBR_SHIFT) & UART_BDH_SBR_MASK; putreg8(regval, uart_base+KINETIS_UART_BDH_OFFSET); @@ -378,7 +488,7 @@ void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud, * The fractional divider, BRFA, is a 5 bit fractional value that is * logically added to the SBR: * - * UART baud rate = clock / (16 × (SBR + BRFD)) + * UART baud rate = clock / (16 � (SBR + BRFD)) * * The BRFA the remainder. This will be a non-negative value since the SBR * was calculated by truncation. @@ -448,3 +558,169 @@ void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud, } #endif +/**************************************************************************** + * Name: kinetis_lpuartconfigure + * + * Description: + * Configure a LPUART as a RS-232 UART. + * + ****************************************************************************/ + +#ifdef HAVE_LPUART_DEVICE +void kinetis_lpuartconfigure(uintptr_t uart_base, uint32_t baud, + uint32_t clock, unsigned int parity, + unsigned int nbits, unsigned int stop2) +{ + uint32_t sbrreg; + uint32_t osrreg; + uint32_t sbr; + uint32_t osr; + uint32_t actual_baud; + uint32_t current_baud; + uint32_t baud_error; + uint32_t min_baud_error; + uint32_t regval; + + /* General note: LPART block input clock can be sourced by + * SIM_CLKDIV3[PLLFLLFRAC, PLLFLLDIV] since this can be shared with TPM, we + * would ideally want to maximize the input frequency. This also helps to + * maximize the oversampling. + * + * We would like to maximize oversample and minimize the baud rate error + * + * USART baud is generated according to: + * + * baud = clock / (SBR[0:12] * (OSR +1 )) + * + * Or, equivalently: + * + * SBR = clock / (baud * (OSR + 1)) + * OSR = clock / (baud * SBR) -1 + * + * SBR must be 1..8191 + * OSR must be 3..31 (macro value 4..32) + */ + + min_baud_error = baud; + sbrreg = 0; + osrreg = 0; + + /* While maximizing OSR look for a SBR that minimizes the difference + * between actual baud and requested baud rate + */ + + for (osr = 32; osr >= 4; osr--) + { + sbr = clock / (baud * osr); + + /* Ensure the minimum SBR */ + + if (sbr == 0) + { + sbr++; + } + + /* Calculate the actual baud rate */ + + current_baud = clock / (sbr * osr); + + /* look at the deviation of current baud to requested */ + + baud_error = current_baud - baud; + if (baud_error <= min_baud_error) + { + min_baud_error = baud_error; + actual_baud = current_baud; + sbrreg = sbr; + osrreg = osr; + } + } + UNUSED(actual_baud); + DEBUGASSERT(actual_baud-baud < (baud /100) * 2); + DEBUGASSERT(sbrreg != 0 && sbrreg < 8192); + DEBUGASSERT(osrreg != 0); + + /* Disable the transmitter and receiver throughout the reconfiguration */ + + regval = getreg32(uart_base+KINETIS_LPUART_CTRL_OFFSET); + regval &= ~(LPUART_CTRL_RE | LPUART_CTRL_TE); + putreg32(regval, uart_base+KINETIS_LPUART_CTRL_OFFSET); + + /* Reset the BAUD register */ + + regval = getreg32(uart_base+KINETIS_LPUART_BAUD_OFFSET); + regval &= ~(LPUART_BAUD_INIT); + + /* Set the Baud rate, nbits and stop bits */ + + regval |= LPUART_BAUD_OSR(osrreg); + regval |= LPUART_BAUD_SBR(sbrreg); + + /* Set the 10 bit mode */ + + if (nbits == 10) + { + regval |= LPUART_BAUD_M10; + } + + /* Set the 2 stop bit mode */ + + if (stop2) + { + regval |= LPUART_BAUD_SBNS; + } + + /* BOTHEDG needs to be turned on for 4X-7X */ + + if (osrreg >= 4 && osrreg <= 7) + { + regval |= LPUART_BAUD_BOTHEDGE; + } + + putreg32(regval, uart_base+KINETIS_LPUART_BAUD_OFFSET); + + /* Configure number of bits and parity */ + + regval = 0; + + /* Check for odd parity */ + + if (parity == 1) + { + regval |= (LPUART_CTRL_PE | LPUART_CTRL_PT); /* Enable + odd parity type */ + } + + /* Check for even parity */ + + else if (parity == 2) + { + regval |= LPUART_CTRL_PE; /* Enable (even parity default) */ + } + + /* The only other option is no parity */ + + else + { + DEBUGASSERT(parity == 0); + } + + /* Check for 9-bit operation */ + + if (nbits == 9) + { + regval |= LPUART_CTRL_M; + } + + /* The only other option is 8-bit operation */ + + else + { + DEBUGASSERT(nbits == 8); + } + + /* Now we can (re-)enable the transmitter and receiver */ + + regval |= (LPUART_CTRL_RE | LPUART_CTRL_TE); + putreg32(regval, uart_base+KINETIS_LPUART_CTRL_OFFSET); +} +#endif diff --git a/arch/arm/src/kinetis/kinetis_lpserial.c b/arch/arm/src/kinetis/kinetis_lpserial.c new file mode 100644 index 00000000000..695db308723 --- /dev/null +++ b/arch/arm/src/kinetis/kinetis_lpserial.c @@ -0,0 +1,901 @@ +/**************************************************************************** + * arch/mips/src/kinetis/kinetis_lpserial.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "kinetis_config.h" +#include "chip.h" +#include "chip/kinetis_lpuart.h" +#include "kinetis.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Some sanity checks *******************************************************/ +/* Is there at least one LPUART enabled and configured as a RS-232 device? */ + +#ifndef HAVE_LPUART_DEVICE +# warning "No LPUARTs enabled" +#endif + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#ifdef USE_SERIALDRIVER + +/* Which LPUART with be tty0/console and which tty1? The console will always + * be ttyS0. If there is no console then will use the lowest numbered LPUART. + */ + +/* First pick the console and ttys0. This could be any of LPUART0-1 */ + +#if defined(CONFIG_LPUART0_SERIAL_CONSOLE) +# define CONSOLE_DEV g_lpuart0port /* LPUART0 is console */ +# define TTYS0_DEV g_lpuart0port /* LPUART0 is ttyS0 */ +# define LPUART0_ASSIGNED 1 +#elif defined(CONFIG_LPUART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_lpuart1port /* LPUART1 is console */ +# define TTYS0_DEV g_lpuart1port /* LPUART1 is ttyS0 */ +# define LPUART1_ASSIGNED 1 +#else +# undef CONSOLE_DEV /* No console */ +# if defined(CONFIG_KINETIS_LPUART0) +# define TTYS0_DEV g_lpuart0port /* LPUART0 is ttyS0 */ +# define LPUART0_ASSIGNED 1 +# elif defined(CONFIG_KINETIS_LPUART1) +# define TTYS0_DEV g_lpuart1port /* LPUART1 is ttyS0 */ +# define LPUART1_ASSIGNED 1 +# endif +#endif + +/* Pick ttys1. This could be any of LPUART0-1 excluding the console LPUART. */ + +#if defined(CONFIG_KINETIS_LPUART0) && !defined(LPUART0_ASSIGNED) +# define TTYS1_DEV g_lpuart0port /* LPUART0 is ttyS1 */ +# define LPUART0_ASSIGNED 1 +#elif defined(CONFIG_KINETIS_LPUART1) && !defined(LPUART1_ASSIGNED) +# define TTYS1_DEV g_lpuart1port /* LPUART1 is ttyS1 */ +# define LPUART1_ASSIGNED 1 +#endif + +#define LPUART_CTRL_ERROR_INTS (LPUART_CTRL_ORIE | LPUART_CTRL_FEIE | \ + LPUART_CTRL_NEIE | LPUART_CTRL_PEIE) + +#define LPUART_CTRL_RX_INTS LPUART_CTRL_RIE + +#define LPUART_CTRL_TX_INTS LPUART_CTRL_TIE + +#define LPUART_CTRL_ALL_INTS (LPUART_CTRL_TX_INTS | LPUART_CTRL_RX_INTS | \ + LPUART_CTRL_MA1IE | LPUART_CTRL_MA1IE | \ + LPUART_CTRL_ILIE | LPUART_CTRL_TCIE) + +#define LPUART_STAT_ERRORS (LPUART_STAT_OR | LPUART_STAT_FE | \ + LPUART_STAT_PF | LPUART_STAT_NF) + + +/* The LPUART does not have an common set of aligned bits for the interrupt + * enable and the status. So map the ctrl to the stat bits + */ + +#define LPUART_CTRL_TR_INTS (LPUART_CTRL_TX_INTS | LPUART_CTRL_RX_INTS) +#define LPUART_CTRL2STAT(c) ((((c) & LPUART_CTRL_ERROR_INTS) >> 8) | \ + ((c) & (LPUART_CTRL_TR_INTS))) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct kinetis_dev_s +{ + uintptr_t uartbase; /* Base address of LPUART registers */ + uint32_t baud; /* Configured baud */ + uint32_t clock; /* Clocking frequency of the LPUART module */ + uint32_t ie; /* Interrupts enabled */ + uint8_t irq; /* IRQ associated with this LPUART (for enable) */ + uint8_t irqprio; /* Interrupt priority */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (8 or 9) */ + uint8_t stop2; /* Use 2 stop bits */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int kinetis_setup(struct uart_dev_s *dev); +static void kinetis_shutdown(struct uart_dev_s *dev); +static int kinetis_attach(struct uart_dev_s *dev); +static void kinetis_detach(struct uart_dev_s *dev); +static int kinetis_interrupt(int irq, void *context); +static int kinetis_ioctl(struct file *filep, int cmd, unsigned long arg); +static int kinetis_receive(struct uart_dev_s *dev, uint32_t *status); +static void kinetis_rxint(struct uart_dev_s *dev, bool enable); +static bool kinetis_rxavailable(struct uart_dev_s *dev); +static void kinetis_send(struct uart_dev_s *dev, int ch); +static void kinetis_txint(struct uart_dev_s *dev, bool enable); +static bool kinetis_txready(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_lpuart_ops = +{ + .setup = kinetis_setup, + .shutdown = kinetis_shutdown, + .attach = kinetis_attach, + .detach = kinetis_detach, + .ioctl = kinetis_ioctl, + .receive = kinetis_receive, + .rxint = kinetis_rxint, + .rxavailable = kinetis_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = kinetis_send, + .txint = kinetis_txint, + .txready = kinetis_txready, + .txempty = kinetis_txready, +}; + +/* I/O buffers */ + +#ifdef CONFIG_KINETIS_LPUART0 +static char g_lpuart0rxbuffer[CONFIG_LPUART0_RXBUFSIZE]; +static char g_lpuart0txbuffer[CONFIG_LPUART0_TXBUFSIZE]; +#endif +#ifdef CONFIG_KINETIS_LPUART1 +static char g_lpuart1rxbuffer[CONFIG_LPUART1_RXBUFSIZE]; +static char g_lpuart1txbuffer[CONFIG_LPUART1_TXBUFSIZE]; +#endif + +/* This describes the state of the Kinetis LPUART0 port. */ + +#ifdef CONFIG_KINETIS_LPUART0 +static struct kinetis_dev_s g_lpuart0priv = +{ + .uartbase = KINETIS_LPUART0_BASE, + .clock = BOARD_LPUART0_FREQ, + .baud = CONFIG_LPUART0_BAUD, + .irq = KINETIS_IRQ_LPUART0, + .irqprio = CONFIG_KINETIS_LPUART0PRIO, + .parity = CONFIG_LPUART0_PARITY, + .bits = CONFIG_LPUART0_BITS, + .stop2 = CONFIG_LPUART0_2STOP, +}; + +static uart_dev_t g_lpuart0port = +{ + .recv = + { + .size = CONFIG_LPUART0_RXBUFSIZE, + .buffer = g_lpuart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_LPUART0_TXBUFSIZE, + .buffer = g_lpuart0txbuffer, + }, + .ops = &g_lpuart_ops, + .priv = &g_lpuart0priv, +}; +#endif + +/* This describes the state of the Kinetis LPUART1 port. */ + +#ifdef CONFIG_KINETIS_LPUART1 +static struct kinetis_dev_s g_lpuart1priv = +{ + .uartbase = KINETIS_LPUART1_BASE, + .clock = BOARD_CORECLK_FREQ, + .baud = BOARD_LPUART1_FREQ, + .irq = KINETIS_IRQ_LPUART1, + .irqprio = CONFIG_KINETIS_LPUART1PRIO, + .parity = CONFIG_LPUART1_PARITY, + .bits = CONFIG_LPUART1_BITS, + .stop2 = CONFIG_LPUART1_2STOP, +}; + +static uart_dev_t g_lpuart1port = +{ + .recv = + { + .size = CONFIG_LPUART1_RXBUFSIZE, + .buffer = g_lpuart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_LPUART1_TXBUFSIZE, + .buffer = g_lpuart1txbuffer, + }, + .ops = &g_lpuart_ops, + .priv = &g_lpuart1priv, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: kinetis_serialin + ****************************************************************************/ + +static inline uint32_t kinetis_serialin(struct kinetis_dev_s *priv, int offset) +{ + return getreg32(priv->uartbase + offset); +} + +/**************************************************************************** + * Name: kinetis_serialout + ****************************************************************************/ + +static inline void kinetis_serialout(struct kinetis_dev_s *priv, int offset, uint32_t value) +{ + putreg32(value, priv->uartbase + offset); +} + +/**************************************************************************** + * Name: kinetis_setuartint + ****************************************************************************/ + +static void kinetis_setuartint(struct kinetis_dev_s *priv) +{ + irqstate_t flags; + uint32_t regval; + + /* Re-enable/re-disable interrupts corresponding to the state of bits in ie */ + + flags = enter_critical_section(); + regval = kinetis_serialin(priv, KINETIS_LPUART_CTRL_OFFSET); + regval &= ~LPUART_CTRL_ALL_INTS; + regval |= priv->ie; + kinetis_serialout(priv, KINETIS_LPUART_CTRL_OFFSET, regval); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: kinetis_restoreuartint + ****************************************************************************/ + +static void kinetis_restoreuartint(struct kinetis_dev_s *priv, uint32_t ie) +{ + irqstate_t flags; + + /* Re-enable/re-disable interrupts corresponding to the state of bits in ie */ + + flags = enter_critical_section(); + priv->ie = ie & LPUART_CTRL_ALL_INTS; + kinetis_setuartint(priv); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: kinetis_disableuartint + ****************************************************************************/ + +static void kinetis_disableuartint(struct kinetis_dev_s *priv, uint32_t *ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + if (ie) + { + *ie = priv->ie; + } + + kinetis_restoreuartint(priv, 0); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: kinetis_setup + * + * Description: + * Configure the LPUART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int kinetis_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_LPUART_CONFIG + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + + /* Configure the LPUART as an RS-232 UART */ + + kinetis_lpuartconfigure(priv->uartbase, priv->baud, priv->clock, + priv->parity, priv->bits, priv->stop2); +#endif + + /* Make sure that all interrupts are disabled */ + + kinetis_restoreuartint(priv, 0); + +#ifdef CONFIG_ARCH_IRQPRIO + /* Set up the interrupt priority */ + + up_prioritize_irq(priv->irq, priv->irqprio); +#endif + + return OK; +} + +/**************************************************************************** + * Name: kinetis_shutdown + * + * Description: + * Disable the LPUART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void kinetis_shutdown(struct uart_dev_s *dev) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + + /* Disable interrupts */ + + kinetis_restoreuartint(priv, 0); + + /* Reset hardware and disable Rx and Tx */ + + kinetis_uartreset(priv->uartbase); +} + +/**************************************************************************** + * Name: kinetis_attach + * + * Description: + * Configure the LPUART to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are called. + * + ****************************************************************************/ + +static int kinetis_attach(struct uart_dev_s *dev) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ(s). The interrupts are (probably) still + * disabled in the LPUART_CTRL register. + */ + + ret = irq_attach(priv->irq, kinetis_interrupt); + if (ret == OK) + { + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: kinetis_detach + * + * Description: + * Detach LPUART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception + * is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void kinetis_detach(struct uart_dev_s *dev) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + + /* Disable interrupts */ + + kinetis_restoreuartint(priv, 0); + up_disable_irq(priv->irq); + + /* Detach from the interrupt(s) */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: kinetis_interrupts + * + * Description: + * This is the LPUART status interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * Appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int kinetis_interrupt(int irq, void *context) +{ + struct uart_dev_s *dev = NULL; + struct kinetis_dev_s *priv; + uint32_t stat; + uint32_t ctrl; + +#ifdef CONFIG_KINETIS_LPUART0 + if (g_lpuart0priv.irq == irq) + { + dev = &g_lpuart0port; + } + else +#endif +#ifdef CONFIG_KINETIS_LPUART1 + if (g_lpuart1priv.irq == irq) + { + dev = &g_lpuart1port; + } + else +#endif + { + PANIC(); + } + + priv = (struct kinetis_dev_s *)dev->priv; + DEBUGASSERT(priv); + + /* Read status register and qualify it with STAT bit corresponding CTRL IE bits */ + + stat = kinetis_serialin(priv, KINETIS_LPUART_STAT_OFFSET); + ctrl = kinetis_serialin(priv, KINETIS_LPUART_CTRL_OFFSET); + stat &= LPUART_CTRL2STAT(ctrl); + do + { + + /* Handle errors. This interrupt may be caused by: + * + * OR: Receiver Overrun Flag. To clear OR, when STAT read with OR set, + * write STAT with OR set; + * FE: Framing error. To clear FE, when STAT read with FE set, read the + * data to discard it and write STAT with FE set; + * NF: Noise flag. To clear NF, when STAT read with EE set, read the + * data to discard it and write STAT with NE set; + * PF: Parity error flag. To clear PF, when STAT read with PE set, read + * the data to discard it and write STAT with PE set; + */ + + if (stat & LPUART_STAT_ERRORS) + { + + /* Only Overrun error does not need a read operation */ + + if ((stat & LPUART_STAT_OR) != LPUART_STAT_OR) + { + (void) kinetis_serialin(priv, KINETIS_LPUART_DATA_OFFSET); + } + + /* Reset any Errors */ + + kinetis_serialout(priv, KINETIS_LPUART_STAT_OFFSET, stat & LPUART_STAT_ERRORS); + return OK; + } + + /* Handle incoming, receive bytes + * + * Check if the receive data register is full (RDRF). + * + * The RDRF status indication is cleared when the data is read from + * the RX data register. + */ + + if (stat & LPUART_STAT_RDRF) + { + uart_recvchars(dev); + } + + /* Handle outgoing, transmit bytes + * + * Check if the transmit data register is "empty." + * + * The TDRE status indication is cleared when the data is written to + * the TX data register. + */ + + if (stat & LPUART_STAT_TDRE) + { + uart_xmitchars(dev); + } + + /* Read status register and requalify it with STAT bit corresponding CTRL IE bits */ + + stat = kinetis_serialin(priv, KINETIS_LPUART_STAT_OFFSET); + ctrl = kinetis_serialin(priv, KINETIS_LPUART_CTRL_OFFSET); + stat &= LPUART_CTRL2STAT(ctrl); + } while(stat != 0); + + return OK; +} + +/**************************************************************************** + * Name: kinetis_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int kinetis_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#if 0 /* Reserved for future growth */ + struct inode *inode; + struct uart_dev_s *dev; + struct kinetis_dev_s *priv; + int ret = OK; + + DEBUGASSERT(filep, filep->f_inode); + inode = filep->f_inode; + dev = inode->i_private; + + DEBUGASSERT(dev, dev->priv); + priv = (struct kinetis_dev_s *)dev->priv; + + switch (cmd) + { + case xxx: /* Add commands here */ + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +#else + return -ENOTTY; +#endif +} + +/**************************************************************************** + * Name: kinetis_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the LPUART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int kinetis_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + uint32_t regval; + int data; + /* Get error status information: + * + * OR: Receiver Overrun Flag. To clear OR, when STAT read with OR set, + * write STAT with OR set; + * FE: Framing error. To clear FE, when STAT read with FE set, read the + * data to discard it and write STAT with FE set; + * NF: Noise flag. To clear NF, when STAT read with EE set, read the + * data to discard it and write STAT with NE set; + * PF: Parity error flag. To clear PF, when STAT read with PE set, read + * the data to discard it and write STAT with PE set; + */ + + regval = kinetis_serialin(priv, KINETIS_LPUART_STAT_OFFSET); + + /* Return status information */ + + if (status) + { + *status = regval; + } + + /* Then return the actual received byte. Read DATA. Then if + * there were any errors write 1 to them to clear the RX errors. + */ + + data = (int)kinetis_serialin(priv, KINETIS_LPUART_DATA_OFFSET); + regval &= LPUART_STAT_ERRORS; + if (regval) + { + kinetis_serialout(priv, KINETIS_LPUART_STAT_OFFSET, regval); + } + return data; +} + +/**************************************************************************** + * Name: kinetis_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void kinetis_rxint(struct uart_dev_s *dev, bool enable) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Receive an interrupt when their is anything in the Rx data register (or an Rx + * related error occurs). + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ie |= (LPUART_CTRL_RX_INTS | LPUART_CTRL_ERROR_INTS); + kinetis_setuartint(priv); +#endif + } + else + { + priv->ie &= ~(LPUART_CTRL_RX_INTS | LPUART_CTRL_ERROR_INTS); + kinetis_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: kinetis_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool kinetis_rxavailable(struct uart_dev_s *dev) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + + /* Return true if the receive data register is full (RDRF). + */ + + return (kinetis_serialin(priv, KINETIS_LPUART_STAT_OFFSET) & LPUART_STAT_RDRF) != 0; +} + +/**************************************************************************** + * Name: kinetis_send + * + * Description: + * This method will send one byte on the LPUART. + * + ****************************************************************************/ + +static void kinetis_send(struct uart_dev_s *dev, int ch) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + kinetis_serialout(priv, KINETIS_LPUART_DATA_OFFSET, ch); +} + +/**************************************************************************** + * Name: kinetis_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void kinetis_txint(struct uart_dev_s *dev, bool enable) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Enable the TX interrupt */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ie |= LPUART_CTRL_TX_INTS; + kinetis_setuartint(priv); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + priv->ie &= ~LPUART_CTRL_TX_INTS; + kinetis_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: kinetis_txready + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool kinetis_txready(struct uart_dev_s *dev) +{ + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev->priv; + + /* Return true if the transmit data register is "empty." */ + + return (kinetis_serialin(priv, KINETIS_LPUART_STAT_OFFSET) & LPUART_STAT_TDRE) != 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_earlyserialinit + * + * Description: + * Performs the low level LPUART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before up_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in kinetis_lowsetup() and main clock initialization + * performed in up_clkinitialize(). + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ + /* Disable interrupts from all LPUARTS. The console is enabled in + * kinetis_setup() + */ + + kinetis_restoreuartint(TTYS0_DEV.priv, 0); +#ifdef TTYS1_DEV + kinetis_restoreuartint(TTYS1_DEV.priv, 0); +#endif + + /* Configuration whichever one is the console */ + +#ifdef HAVE_LPUART_CONSOLE + CONSOLE_DEV.isconsole = true; + kinetis_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ + /* Register the console */ + +#ifdef HAVE_LPUART_CONSOLE + (void)uart_register("/dev/console", &CONSOLE_DEV); +#endif + + /* Register all LPUARTs */ + + (void)uart_register("/dev/ttyLP0", &TTYS0_DEV); +#ifdef TTYS1_DEV + (void)uart_register("/dev/ttyLP1", &TTYS1_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_LPUART_CONSOLE + struct kinetis_dev_s *priv = (struct kinetis_dev_s *)CONSOLE_DEV.priv; + uint32_t ie; + + kinetis_disableuartint(priv, &ie); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + kinetis_restoreuartint(priv, ie); +#endif + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_LPUART_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ + diff --git a/arch/arm/src/kinetis/kinetis_serial.c b/arch/arm/src/kinetis/kinetis_serial.c index 94966f72a27..b6d0c369cf7 100644 --- a/arch/arm/src/kinetis/kinetis_serial.c +++ b/arch/arm/src/kinetis/kinetis_serial.c @@ -1,8 +1,9 @@ /**************************************************************************** * arch/mips/src/kinetis/kinetis_serial.c * - * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * David Sidrane * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -240,6 +241,7 @@ struct up_dev_s uint8_t ie; /* Interrupts enabled */ uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (8 or 9) */ + uint8_t stop2; /* Use 2 stop bits */ }; /**************************************************************************** @@ -334,6 +336,7 @@ static struct up_dev_s g_uart0priv = .irqprio = CONFIG_KINETIS_UART0PRIO, .parity = CONFIG_UART0_PARITY, .bits = CONFIG_UART0_BITS, + .stop2 = CONFIG_UART0_2STOP, }; static uart_dev_t g_uart0port = @@ -368,6 +371,7 @@ static struct up_dev_s g_uart1priv = .irqprio = CONFIG_KINETIS_UART1PRIO, .parity = CONFIG_UART1_PARITY, .bits = CONFIG_UART1_BITS, + .stop2 = CONFIG_UART1_2STOP, }; static uart_dev_t g_uart1port = @@ -402,6 +406,7 @@ static struct up_dev_s g_uart2priv = .irqprio = CONFIG_KINETIS_UART2PRIO, .parity = CONFIG_UART2_PARITY, .bits = CONFIG_UART2_BITS, + .stop2 = CONFIG_UART2_2STOP, }; static uart_dev_t g_uart2port = @@ -436,6 +441,7 @@ static struct up_dev_s g_uart3priv = .irqprio = CONFIG_KINETIS_UART3PRIO, .parity = CONFIG_UART3_PARITY, .bits = CONFIG_UART3_BITS, + .stop2 = CONFIG_UART3_2STOP, }; static uart_dev_t g_uart3port = @@ -470,6 +476,7 @@ static struct up_dev_s g_uart4priv = .irqprio = CONFIG_KINETIS_UART4PRIO, .parity = CONFIG_UART4_PARITY, .bits = CONFIG_UART4_BITS, + .stop2 = CONFIG_UART4_2STOP, }; static uart_dev_t g_uart4port = @@ -504,6 +511,7 @@ static struct up_dev_s g_uart5priv = .irqprio = CONFIG_KINETIS_UART5PRIO, .parity = CONFIG_UART5_PARITY, .bits = CONFIG_UART5_BITS, + .stop2 = CONFIG_UART5_2STOP, }; static uart_dev_t g_uart5port = @@ -615,7 +623,7 @@ static int up_setup(struct uart_dev_s *dev) /* Configure the UART as an RS-232 UART */ kinetis_uartconfigure(priv->uartbase, priv->baud, priv->clock, - priv->parity, priv->bits); + priv->parity, priv->bits, priv->stop2); #endif /* Make sure that all interrupts are disabled */ @@ -1256,7 +1264,7 @@ void up_earlyserialinit(void) /* Configuration whichever one is the console */ -#ifdef HAVE_SERIAL_CONSOLE +#ifdef HAVE_UART_CONSOLE CONSOLE_DEV.isconsole = true; up_setup(&CONSOLE_DEV); #endif @@ -1275,7 +1283,7 @@ void up_serialinit(void) { /* Register the console */ -#ifdef HAVE_SERIAL_CONSOLE +#ifdef HAVE_UART_CONSOLE (void)uart_register("/dev/console", &CONSOLE_DEV); #endif @@ -1309,7 +1317,7 @@ void up_serialinit(void) int up_putc(int ch) { -#ifdef HAVE_SERIAL_CONSOLE +#ifdef HAVE_UART_CONSOLE struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv; uint8_t ie; @@ -1342,7 +1350,7 @@ int up_putc(int ch) int up_putc(int ch) { -#ifdef HAVE_SERIAL_CONSOLE +#ifdef HAVE_UART_CONSOLE /* Check for LF */ if (ch == '\n') diff --git a/configs/freedom-k66f/include/board.h b/configs/freedom-k66f/include/board.h index 97d3bf4122e..7e5cbf50b51 100644 --- a/configs/freedom-k66f/include/board.h +++ b/configs/freedom-k66f/include/board.h @@ -42,11 +42,12 @@ ************************************************************************************/ #include - #ifndef __ASSEMBLY__ # include #endif +#include "chip.h" + /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ @@ -62,7 +63,7 @@ * */ -#define BOARD_EXTAL_LP 1 +#define BOARD_EXTAL_LP 1 #define BOARD_EXTAL_FREQ 12000000 /* 12MHz Oscillator */ #define BOARD_XTAL32_FREQ 32768 /* 32KHz RTC Oscillator */ @@ -103,6 +104,46 @@ #define BOARD_FLEXBUS_FREQ (BOARD_MCG_FREQ / BOARD_OUTDIV3) #define BOARD_FLASHCLK_FREQ (BOARD_MCG_FREQ / BOARD_OUTDIV4) +/* Use BOARD_MCG_FREQ as the output SIM_SOPT2 MUX selected by + * SIM_SOPT2[PLLFLLSEL] + */ + +#define BOARD_SOPT2_PLLFLLSEL SIM_SOPT2_PLLFLLSEL_MCGPLLCLK +#define BOARD_SOPT2_FREQ BOARD_MCG_FREQ + +/* N.B. The above BOARD_SOPT2_FREQ precludes use of USB with a 12 Mhz Xtal + * Divider output clock = Divider input clock × [ (USBFRAC+1) / (USBDIV+1) ] + * SIM_CLKDIV2_FREQ = BOARD_SOPT2_FREQ × [ (USBFRAC+1) / (USBDIV+1) ] + * 48Mhz = 168Mhz X [(1 + 1) / (6 + 1)] + * 48Mhz = 168Mhz / (6 + 1) * (1 + 1) + */ + +#if (BOARD_MCG_FREQ == 168000000L) +# define BOARD_SIM_CLKDIV2_USBFRAC 2 +# define BOARD_SIM_CLKDIV2_USBDIV 7 +# define BOARD_SIM_CLKDIV2_FREQ (BOARD_SOPT2_FREQ / \ + BOARD_SIM_CLKDIV2_USBDIV * \ + BOARD_SIM_CLKDIV2_USBFRAC) +#endif + +/* Divider output clock = Divider input clock * ((PLLFLLFRAC+1)/(PLLFLLDIV+1)) + * SIM_CLKDIV3_FREQ = BOARD_SOPT2_FREQ × [ (PLLFLLFRAC+1) / (PLLFLLDIV+1)] + * 90 Mhz = 180 Mhz X [(0 + 1) / (1 + 1)] + * 90 Mhz = 180 Mhz / (1 + 1) * (0 + 1) + */ + +#define BOARD_SIM_CLKDIV3_PLLFLLFRAC 1 +#define BOARD_SIM_CLKDIV3_PLLFLLDIV 2 +#define BOARD_SIM_CLKDIV3_FREQ (BOARD_SOPT2_FREQ / \ + BOARD_SIM_CLKDIV3_PLLFLLDIV * \ + BOARD_SIM_CLKDIV3_PLLFLLFRAC) + +#define BOARD_LPUART0_CLKSRC SIM_SOPT2_LPUARTSRC_MCGCLK +#define BOARD_LPUART0_FREQ BOARD_SIM_CLKDIV3_FREQ + +#define BOARD_TPM_CLKSRC SIM_SOPT2_TPMSRC_MCGCLK +#define BOARD_TPM_FREQ BOARD_SIM_CLKDIV3_FREQ + /* SDHC clocking ********************************************************************/ /* SDCLK configurations corresponding to various modes of operation. Formula is: @@ -276,6 +317,18 @@ #define PIN_UART4_RX PIN_UART4_RX_1 #define PIN_UART4_TX PIN_UART4_TX_1 +/* LPUART + * + * J1 Pin Name K66 Name + * -------- ------------ ------ --------- + * 7 I2S_RX_BCLK PTE9 LPUART0_RX + * 11 I2S_RX_FS PTE8 LPUART0_TX + * -------- ----- ------ --------- + */ + +#define PIN_LPUART0_RX PIN_LPUART0_RX_1 +#define PIN_LPUART0_TX PIN_LPUART0_TX_1 + /* I2C INERTIAL SENSOR (Gyroscope) * * Pin Name K66 Name