nuttx/arch/arm/src/kinetis/kinetis_lowputc.c
Alin Jerpelea 37f91b023c arch: Author David Sidrane: update licenses to Apache
David Sidrane has submitted the ICL and we can migrate the licenses
 to Apache.

Gregory Nutt has submitted the SGA and we can migrate the licenses
 to Apache.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
2021-03-22 19:28:38 -07:00

968 lines
28 KiB
C

/****************************************************************************
* arch/arm/src/kinetis/kinetis_lowputc.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <arch/irq.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include "arm_arch.h"
#include "kinetis_config.h"
#include "kinetis.h"
#include "hardware/kinetis_uart.h"
#include "hardware/kinetis_lpuart.h"
#include "hardware/kinetis_sim.h"
#include "hardware/kinetis_pinmux.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Default hardware flow control */
#if !defined(CONFIG_UART0_IFLOWCONTROL)
# define CONFIG_UART0_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART0_OFLOWCONTROL)
# define CONFIG_UART0_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART1_IFLOWCONTROL)
# define CONFIG_UART1_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART1_OFLOWCONTROL)
# define CONFIG_UART1_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART2_IFLOWCONTROL)
# define CONFIG_UART2_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART2_OFLOWCONTROL)
# define CONFIG_UART2_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART3_IFLOWCONTROL)
# define CONFIG_UART3_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART3_OFLOWCONTROL)
# define CONFIG_UART3_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART4_IFLOWCONTROL)
# define CONFIG_UART4_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART4_OFLOWCONTROL)
# define CONFIG_UART4_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART5_IFLOWCONTROL)
# define CONFIG_UART5_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_UART5_OFLOWCONTROL)
# define CONFIG_UART5_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART0_IFLOWCONTROL)
# define CONFIG_LPUART0_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART0_OFLOWCONTROL)
# define CONFIG_LPUART0_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART1_IFLOWCONTROL)
# define CONFIG_LPUART1_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART1_OFLOWCONTROL)
# define CONFIG_LPUART1_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART2_IFLOWCONTROL)
# define CONFIG_LPUART2_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART2_OFLOWCONTROL)
# define CONFIG_LPUART2_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART3_IFLOWCONTROL)
# define CONFIG_LPUART3_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART3_OFLOWCONTROL)
# define CONFIG_LPUART3_OFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART4_IFLOWCONTROL)
# define CONFIG_LPUART4_IFLOWCONTROL 0
#endif
#if !defined(CONFIG_LPUART4_OFLOWCONTROL)
# define CONFIG_LPUART4_OFLOWCONTROL 0
#endif
/* Select UART parameters for the selected console */
#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
# define CONSOLE_IFLOW CONFIG_UART0_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART0_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_UART1_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART1_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_UART2_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART2_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_UART3_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART3_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_UART4_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART4_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_UART5_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_UART5_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_LPUART0_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_LPUART0_OFLOWCONTROL
# 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
# define CONSOLE_IFLOW CONFIG_LPUART1_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_LPUART1_OFLOWCONTROL
# elif defined(CONFIG_LPUART2_SERIAL_CONSOLE)
# define CONSOLE_BASE KINETIS_LPUART2_BASE
# define CONSOLE_FREQ BOARD_LPUART2_FREQ
# define CONSOLE_BAUD CONFIG_LPUART2_BAUD
# define CONSOLE_PARITY CONFIG_LPUART2_PARITY
# define CONSOLE_BITS CONFIG_LPUART2_BITS
# define CONSOLE_2STOP CONFIG_LPUART2_2STOP
# define CONSOLE_IFLOW CONFIG_LPUART2_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_LPUART2_OFLOWCONTROL
# elif defined(CONFIG_LPUART3_SERIAL_CONSOLE)
# define CONSOLE_BASE KINETIS_LPUART3_BASE
# define CONSOLE_FREQ BOARD_LPUART3_FREQ
# define CONSOLE_BAUD CONFIG_LPUART3_BAUD
# define CONSOLE_PARITY CONFIG_LPUART3_PARITY
# define CONSOLE_BITS CONFIG_LPUART3_BITS
# define CONSOLE_2STOP CONFIG_LPUART3_2STOP
# define CONSOLE_IFLOW CONFIG_LPUART3_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_LPUART3_OFLOWCONTROL
# elif defined(CONFIG_LPUART4_SERIAL_CONSOLE)
# define CONSOLE_BASE KINETIS_LPUART4_BASE
# define CONSOLE_FREQ BOARD_LPUART4_FREQ
# define CONSOLE_BAUD CONFIG_LPUART4_BAUD
# define CONSOLE_PARITY CONFIG_LPUART4_PARITY
# define CONSOLE_BITS CONFIG_LPUART4_BITS
# define CONSOLE_2STOP CONFIG_LPUART4_2STOP
# define CONSOLE_IFLOW CONFIG_LPUART4_IFLOWCONTROL
# define CONSOLE_OFLOW CONFIG_LPUART4_OFLOWCONTROL
# 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
#endif
#ifdef HAVE_LPUART_DEVICE
# 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 Data
****************************************************************************/
/* This array maps an encoded FIFO depth (index) to the actual size of the
* FIFO (indexed value). NOTE: That there is no 8th value.
*/
#ifdef CONFIG_KINETIS_UARTFIFOS
static uint8_t g_sizemap[8] =
{
1, 4, 8, 16, 32, 64, 128, 0
};
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arm_lowputc
*
* Description:
* Output one byte on the serial console
*
****************************************************************************/
void arm_lowputc(char ch)
{
#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
/* 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
* 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
* full (other than reading the FIFO length and comparing the FIFO count).
* Hence, the FIFOs are not used in this implementation and, as a result
* TDRE indeed mean that the single output buffer is available.
*
* Performance on UART0 could be improved by enabling the FIFO and by
* redesigning all of the FIFO status logic.
*/
while (
(getreg8(CONSOLE_BASE + KINETIS_UART_S1_OFFSET) & UART_S1_TDRE) == 0);
# 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
}
/****************************************************************************
* Name: kinetis_lowsetup
*
* Description:
* This performs basic initialization of the UART used for the serial
* console. Its purpose is to get the console output available as soon
* as possible.
*
****************************************************************************/
void kinetis_lowsetup(void)
{
#if defined(HAVE_UART_DEVICE) || defined(HAVE_LPUART_DEVICE)
uint32_t regval;
#endif
#ifdef HAVE_UART_DEVICE
/* Enable peripheral clocking for all enabled UARTs. Clocking for UARTs
* 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)
regval = getreg32(KINETIS_SIM_SCGC4);
# ifdef CONFIG_KINETIS_UART0
regval |= SIM_SCGC4_UART0;
# endif
# ifdef CONFIG_KINETIS_UART1
regval |= SIM_SCGC4_UART1;
# endif
# ifdef CONFIG_KINETIS_UART2
regval |= SIM_SCGC4_UART2;
# endif
# ifdef CONFIG_KINETIS_UART3
regval |= SIM_SCGC4_UART3;
# endif
putreg32(regval, KINETIS_SIM_SCGC4);
# endif
/* Clocking for UARTs 4-5 is enabled in the SCGC1 register. */
# if defined(CONFIG_KINETIS_UART4) || defined(CONFIG_KINETIS_UART5)
regval = getreg32(KINETIS_SIM_SCGC1);
# ifdef CONFIG_KINETIS_UART4
regval |= SIM_SCGC1_UART4;
# endif
# ifdef CONFIG_KINETIS_UART5
regval |= SIM_SCGC1_UART5;
# endif
putreg32(regval, KINETIS_SIM_SCGC1);
# endif
/* Configure UART pins for the all enabled UARTs */
# ifdef CONFIG_KINETIS_UART0
kinetis_pinconfig(PIN_UART0_TX);
kinetis_pinconfig(PIN_UART0_RX);
# if CONFIG_UART0_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART0_RTS);
# endif
# if CONFIG_UART0_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART0_CTS);
# endif
# endif
# ifdef CONFIG_KINETIS_UART1
kinetis_pinconfig(PIN_UART1_TX);
kinetis_pinconfig(PIN_UART1_RX);
# if CONFIG_UART1_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART1_RTS);
# endif
# if CONFIG_UART1_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART1_CTS);
# endif
# endif
# ifdef CONFIG_KINETIS_UART2
kinetis_pinconfig(PIN_UART2_TX);
kinetis_pinconfig(PIN_UART2_RX);
# if CONFIG_UART2_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART2_RTS);
# endif
# if CONFIG_UART2_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART2_CTS);
# endif
# endif
# ifdef CONFIG_KINETIS_UART3
kinetis_pinconfig(PIN_UART3_TX);
kinetis_pinconfig(PIN_UART3_RX);
# if CONFIG_UART3_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART3_RTS);
# endif
# if CONFIG_UART3_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART3_CTS);
# endif
# endif
# ifdef CONFIG_KINETIS_UART4
kinetis_pinconfig(PIN_UART4_TX);
kinetis_pinconfig(PIN_UART4_RX);
# if CONFIG_UART4_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART4_RTS);
# endif
# if CONFIG_UART4_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART4_CTS);
# endif
# endif
# ifdef CONFIG_KINETIS_UART5
kinetis_pinconfig(PIN_UART5_TX);
kinetis_pinconfig(PIN_UART5_RX);
# if CONFIG_UART5_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART5_RTS);
# endif
# if CONFIG_UART5_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_UART5_CTS);
# endif
# endif
/* Configure the console (only) now. Other UARTs will be configured
* when the serial driver is opened.
*/
# if defined(HAVE_UART_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG)
kinetis_uartconfigure(CONSOLE_BASE, CONSOLE_BAUD, CONSOLE_FREQ, \
CONSOLE_PARITY, CONSOLE_BITS, CONSOLE_2STOP, \
CONSOLE_IFLOW, CONSOLE_OFLOW);
# endif
#endif /* HAVE_UART_DEVICE */
#ifdef HAVE_LPUART_DEVICE
/* Clocking Source for LPUART0 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
#if defined(CONFIG_KINETIS_LPUART1)
# warning REVISIT
#endif
#if defined(CONFIG_KINETIS_LPUART2)
# warning REVISIT
#endif
#if defined(CONFIG_KINETIS_LPUART3)
# warning REVISIT
#endif
#if defined(CONFIG_KINETIS_LPUART4)
# warning REVISIT
#endif
/* Configure UART pins for the all enabled UARTs */
#ifdef CONFIG_KINETIS_LPUART0
kinetis_pinconfig(PIN_LPUART0_TX);
kinetis_pinconfig(PIN_LPUART0_RX);
#if CONFIG_LPUART0_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_LPUART0_RTS);
#endif
#if CONFIG_LPUART0_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_LOUART0_CTS);
#endif
#endif
#ifdef CONFIG_KINETIS_LPUART1
kinetis_pinconfig(PIN_LPUART1_TX);
kinetis_pinconfig(PIN_LPUART1_RX);
#if CONFIG_LPUART1_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_LPUART1_RTS);
#endif
#if CONFIG_LPUART1_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_LOUART1_CTS);
#endif
#endif
#ifdef CONFIG_KINETIS_LPUART2
kinetis_pinconfig(PIN_LPUART2_TX);
kinetis_pinconfig(PIN_LPUART2_RX);
#if CONFIG_LPUART2_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_LPUART2_RTS);
#endif
#if CONFIG_LPUART2_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_LOUART2_CTS);
#endif
#endif
#ifdef CONFIG_KINETIS_LPUART3
kinetis_pinconfig(PIN_LPUART3_TX);
kinetis_pinconfig(PIN_LPUART3_RX);
#if CONFIG_LPUART3_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_LPUART3_RTS);
#endif
#if CONFIG_LPUART3_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_LOUART3_CTS);
#endif
#endif
#ifdef CONFIG_KINETIS_LPUART4
kinetis_pinconfig(PIN_LPUART4_TX);
kinetis_pinconfig(PIN_LPUART4_RX);
#if CONFIG_LPUART4_IFLOWCONTROL == 1
kinetis_pinconfig(PIN_LPUART4_RTS);
#endif
#if CONFIG_LPUART4_OFLOWCONTROL == 1
kinetis_pinconfig(PIN_LOUART4_CTS);
#endif
#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, \
CONSOLE_IFLOW, CONSOLE_OFLOW);
#endif
#endif /* HAVE_LPUART_DEVICE */
}
/****************************************************************************
* Name: kinetis_uartreset
*
* Description:
* Reset a UART.
*
****************************************************************************/
#ifdef HAVE_UART_DEVICE
void kinetis_uartreset(uintptr_t uart_base)
{
uint8_t regval;
/* Just disable the transmitter and receiver */
regval = getreg8(uart_base + KINETIS_UART_C2_OFFSET);
regval &= ~(UART_C2_RE | UART_C2_TE);
putreg8(regval, uart_base + KINETIS_UART_C2_OFFSET);
}
#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
*
* Description:
* Configure a UART as a RS-232 UART.
*
****************************************************************************/
#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 stop2,
bool iflow, bool oflow)
{
uint32_t sbr;
uint32_t brfa;
uint32_t tmp;
uint8_t regval;
#ifdef CONFIG_KINETIS_UARTFIFOS
unsigned int depth;
#endif
/* Disable the transmitter and receiver throughout the reconfiguration */
regval = getreg8(uart_base + KINETIS_UART_C2_OFFSET);
regval &= ~(UART_C2_RE | UART_C2_TE);
putreg8(regval, uart_base + KINETIS_UART_C2_OFFSET);
/* Configure number of bits, stop bits and parity */
regval = 0;
/* Check for odd parity */
if (parity == 1)
{
regval |= (UART_C1_PE | UART_C1_PT); /* Enable + odd parity type */
}
/* Check for even parity */
else if (parity == 2)
{
regval |= UART_C1_PE; /* Enable (even parity default) */
}
/* The only other option is no parity */
else
{
DEBUGASSERT(parity == 0);
}
/* Check for 9-bit operation or enter 9 bit mode for 8 bit with parity
* see K66 Sub-Family Reference Manual, Rev. 2, May 2015
* 59.5.4 Data format
*/
if (nbits == 9 || (nbits == 8 && parity != 0))
{
regval |= UART_C1_M;
}
/* The only other option is 8-bit operation */
else
{
DEBUGASSERT(nbits == 8);
}
putreg8(regval, uart_base + KINETIS_UART_C1_OFFSET);
/* Calculate baud settings (truncating) */
sbr = clock / (baud << 4);
DEBUGASSERT(sbr < 0x2000);
/* Save the new baud divisor and stop bits, retaining other bits in the
* UARTx_BDH register.
*/
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);
regval = sbr & 0xff;
putreg8(regval, uart_base + KINETIS_UART_BDL_OFFSET);
/* Calculate a fractional divider to get closer to the requested 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))
*
* The BRFA the remainder. This will be a non-negative value since the SBR
* was calculated by truncation.
*/
tmp = clock - (sbr * (baud << 4));
brfa = (tmp << 5) / (baud << 4);
/* Set the BRFA field (retaining other bits in the UARTx_C4 register) */
regval = getreg8(uart_base + KINETIS_UART_C4_OFFSET) & ~UART_C4_BRFA_MASK;
regval |= ((uint8_t)brfa << UART_C4_BRFA_SHIFT) & UART_C4_BRFA_MASK;
putreg8(regval, uart_base + KINETIS_UART_C4_OFFSET);
/* Set the FIFO watermarks.
*
* 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
* full (other than reading the FIFO length and comparing the FIFO count).
* Hence, the FIFOs are not used in this implementation and, as a result
* TDRE indeed mean that the single output buffer is available.
*
* Performance on UART0 could be improved by enabling the FIFO and by
* redesigning all of the FIFO status logic.
*/
#ifdef CONFIG_KINETIS_UARTFIFOS
depth = g_sizemap[(regval & UART_PFIFO_RXFIFOSIZE_MASK) >>
UART_PFIFO_RXFIFOSIZE_SHIFT];
if (depth > 1)
{
depth = (3 * depth) >> 2;
}
putreg8(depth , uart_base + KINETIS_UART_RWFIFO_OFFSET);
depth = g_sizemap[(regval & UART_PFIFO_TXFIFOSIZE_MASK) >>
UART_PFIFO_TXFIFOSIZE_SHIFT];
if (depth > 3)
{
depth = (depth >> 2);
}
putreg8(depth, uart_base + KINETIS_UART_TWFIFO_OFFSET);
/* Enable RX and TX FIFOs */
putreg8(UART_PFIFO_RXFE | UART_PFIFO_TXFE,
uart_base + KINETIS_UART_PFIFO_OFFSET);
#else
/* Otherwise, disable the FIFOs. Then the FIFOs are disable, the effective
* FIFO depth is 1. So set the watermarks as follows:
*
* TWFIFO[TXWATER] = 0: TDRE will be set when the number of queued bytes
* (1 in this case) is less than or equal to 0.
* RWFIFO[RXWATER] = 1: RDRF will be set when the number of queued bytes
* (1 in this case) is greater than or equal to 1.
*
* Set the watermarks to one/zero and disable the FIFOs
*/
putreg8(1, uart_base + KINETIS_UART_RWFIFO_OFFSET);
putreg8(0, uart_base + KINETIS_UART_TWFIFO_OFFSET);
putreg8(0, uart_base + KINETIS_UART_PFIFO_OFFSET);
#endif
/* Hardware flow control */
regval = getreg8(uart_base + KINETIS_UART_MODEM_OFFSET);
regval &= ~(UART_MODEM_TXCTSE | UART_MODEM_RXRTSE);
#ifdef CONFIG_SERIAL_IFLOWCONTROL
if (iflow)
{
regval |= UART_MODEM_RXRTSE;
}
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
if (oflow)
{
regval |= UART_MODEM_TXCTSE;
}
#endif
putreg8(regval, uart_base + KINETIS_UART_MODEM_OFFSET);
/* Now we can (re-)enable the transmitter and receiver */
regval = getreg8(uart_base + KINETIS_UART_C2_OFFSET);
regval |= (UART_C2_RE | UART_C2_TE);
putreg8(regval, uart_base + KINETIS_UART_C2_OFFSET);
}
#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,
bool iflow, bool oflow)
{
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 || (nbits == 8 && parity != 0))
{
regval |= LPUART_CTRL_M;
}
/* The only other option is 8-bit operation */
else
{
DEBUGASSERT(nbits == 8);
}
/* Hardware flow control */
regval = getreg32(uart_base + KINETIS_LPUART_MODIR_OFFSET);
regval &= ~(UART_MODEM_TXCTSE | UART_MODEM_RXRTSE);
#ifdef CONFIG_SERIAL_IFLOWCONTROL
if (iflow)
{
regval |= LPUART_MODIR_RXRTSE;
}
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
if (oflow)
{
regval |= LPUART_MODIR_TXCTSE;
}
#endif
putreg32(regval, uart_base + KINETIS_LPUART_MODIR_OFFSET);
/* 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