diff --git a/bsp/imxrt1052-evk/drivers/drv_uart.c b/bsp/imxrt1052-evk/drivers/drv_uart.c new file mode 100644 index 0000000000..b3f9db685c --- /dev/null +++ b/bsp/imxrt1052-evk/drivers/drv_uart.c @@ -0,0 +1,569 @@ +/* + * File : drv_uart.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006-2013, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2017-10-10 Tanek the first version + * 2018-03-17 laiyiketang Add other uart. + */ +#include +#include "drv_usart.h" + +#include "fsl_common.h" +#include "fsl_lpuart.h" +#include "fsl_iomuxc.h" + +#ifdef RT_USING_SERIAL + +/* GPIO外设时钟会在LPUART_Init中自动配置, 如果定义了以下宏则不会自动配置 */ +#if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL +#error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!" +#endif + +#if !defined(RT_USING_UART1) && !defined(RT_USING_UART2) && \ + !defined(RT_USING_UART3) && !defined(RT_USING_UART4) && \ + !defined(RT_USING_UART5) && !defined(RT_USING_UART6) && \ + !defined(RT_USING_UART7) && !defined(RT_USING_UART8) +#error "Please define at least one UARTx" + +#endif + + + +#include + +/* imxrt uart driver */ +struct imxrt_uart +{ + LPUART_Type * uart_base; + IRQn_Type irqn; + + struct rt_serial_device * serial; + char *device_name; +}; + +static void uart_isr(struct rt_serial_device *serial); + +#if defined(RT_USING_UART1) +struct rt_serial_device serial1; + +void LPUART1_IRQHandler(void) +{ + uart_isr(&serial1); +} + +#endif /* RT_USING_UART1 */ + +#if defined(RT_USING_UART2) +struct rt_serial_device serial2; + +void USART2_IRQHandler(void) +{ + uart_isr(&serial2); +} + +#endif /* RT_USING_UART2 */ + +#if defined(RT_USING_UART3) +struct rt_serial_device serial3; + +void UART3_IRQHandler(void) +{ + uart_isr(&serial3); +} + +#endif /* RT_USING_UART3 */ + +#if defined(RT_USING_UART4) +struct rt_serial_device serial4; + +void UART4_IRQHandler(void) +{ + uart_isr(&serial4); +} +#endif /* RT_USING_UART4 */ + +#if defined(RT_USING_UART5) +struct rt_serial_device serial5; + +void USART5_IRQHandler(void) +{ + uart_isr(&serial5); +} + +#endif /* RT_USING_UART5 */ + +#if defined(RT_USING_UART6) +struct rt_serial_device serial6; + +void UART6_IRQHandler(void) +{ + uart_isr(&serial6); +} + +#endif /* RT_USING_UART6 */ + +#if defined(RT_USING_UART7) +struct rt_serial_device serial7; + +void UART7_IRQHandler(void) +{ + uart_isr(&serial7); +} + +#endif /* RT_USING_UART7 */ + +#if defined(RT_USING_UART8) +struct rt_serial_device serial8; + +void UART8_IRQHandler(void) +{ + uart_isr(&serial8); +} + +#endif /* RT_USING_UART8 */ + +static const struct imxrt_uart uarts[] = { +#ifdef RT_USING_UART1 + { + LPUART1, + LPUART1_IRQn, + &serial1, + "uart1", + }, +#endif +#ifdef RT_USING_UART2 + { + LPUART2, + LPUART2_IRQn, + &serial2, + "uart2", + }, +#endif +#ifdef RT_USING_UART3 + { + LPUART3, + LPUART3_IRQn, + &serial3, + "uart3", + }, +#endif +#ifdef RT_USING_UART4 + { + LPUART4, + LPUART4_IRQn, + &serial4, + "uart4", + }, +#endif +#ifdef RT_USING_UART5 + { + LPUART5, + LPUART5_IRQn, + &serial5, + "uart5", + }, +#endif +#ifdef RT_USING_UART6 + { + LPUART6, + LPUART6_IRQn, + &serial6, + "uart6", + }, +#endif +#ifdef RT_USING_UART7 + { + LPUART7, + LPUART7_IRQn, + &serial7, + "uart7", + }, +#endif +#ifdef RT_USING_UART8 + { + LPUART8, + LPUART8_IRQn, + &serial8, + "uart8", + }, +#endif + +}; + +/* Get debug console frequency. */ +uint32_t BOARD_DebugConsoleSrcFreq(void) +{ + uint32_t freq; + + /* To make it simple, we assume default PLL and divider settings, and the only variable + from application is use PLL3 source or OSC source */ + if (CLOCK_GetMux(kCLOCK_UartMux) == 0) /* PLL3 div6 80M */ + { + freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); + } + else + { + freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); + } + + return freq; +} + + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example: +* - Peripheral's clock enable +* - Peripheral's GPIO Configuration +* - NVIC configuration for UART interrupt request enable +* @param huart: UART handle pointer +* @retval None +*/ +void imxrt_uart_gpio_init(struct imxrt_uart *uart) +{ + if (uart->uart_base != RT_NULL) + { +#ifdef RT_USING_UART1 + CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ +#endif +#ifdef RT_USING_UART2 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_02_LPUART2_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_03_LPUART2_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_02_LPUART2_TX, + 0x10B0u); + + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_03_LPUART2_RX, + 0x10B0u); + +#endif +#ifdef RT_USING_UART3 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_06_LPUART3_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_07_LPUART3_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_06_LPUART3_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_07_LPUART3_RX, + 0x10B0u); +#endif +#ifdef RT_USING_UART4 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_00_LPUART4_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_01_LPUART4_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_00_LPUART4_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_01_LPUART4_RX, + 0x10B0u); +#endif +#ifdef RT_USING_UART5 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_12_LPUART5_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_13_LPUART5_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_12_LPUART5_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_13_LPUART5_RX, + 0x10B0u); +#endif +#ifdef RT_USING_UART6 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_02_LPUART6_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_03_LPUART6_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_02_LPUART6_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_03_LPUART6_RX, + 0x10B0u); +#endif +#ifdef RT_USING_UART7 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_EMC_31_LPUART7_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_EMC_32_LPUART7_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_EMC_31_LPUART7_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_EMC_32_LPUART7_RX, + 0x10B0u); +#endif +#ifdef RT_USING_UART8 + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_10_LPUART8_TX, + 0U); + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B1_11_LPUART8_RX, + 0U); + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_10_LPUART8_TX, + 0x10B0u); + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B1_11_LPUART8_RX, + 0x10B0u); +#endif + } + else + { + RT_ASSERT(RT_NULL); + } +} + +static rt_err_t imxrt_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct imxrt_uart *uart; + lpuart_config_t config; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart = (struct imxrt_uart *)serial->parent.user_data; + + imxrt_uart_gpio_init(uart); + + LPUART_GetDefaultConfig(&config); + config.baudRate_Bps = cfg->baud_rate; + + switch (cfg->data_bits) + { + case DATA_BITS_7: + config.dataBitsCount = kLPUART_SevenDataBits; + break; + + default: + config.dataBitsCount = kLPUART_EightDataBits; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_2: + config.stopBitCount = kLPUART_TwoStopBit; + break; + default: + config.stopBitCount = kLPUART_OneStopBit; + break; + } + + switch (cfg->parity) + { + case PARITY_ODD: + config.parityMode = kLPUART_ParityOdd; + break; + case PARITY_EVEN: + config.parityMode = kLPUART_ParityEven; + break; + default: + config.parityMode = kLPUART_ParityDisabled; + break; + } + + config.enableTx = true; + config.enableRx = true; + + LPUART_Init(uart->uart_base, &config, BOARD_DebugConsoleSrcFreq()); + + + return RT_EOK; +} + +static rt_err_t imxrt_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct imxrt_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct imxrt_uart *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable interrupt */ + LPUART_DisableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable); + /* disable rx irq */ + DisableIRQ(uart->irqn); + + break; + case RT_DEVICE_CTRL_SET_INT: + /* enable interrupt */ + LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable); + /* enable rx irq */ + EnableIRQ(uart->irqn); + break; + } + + return RT_EOK; +} + +static int imxrt_putc(struct rt_serial_device *serial, char ch) +{ + struct imxrt_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct imxrt_uart *)serial->parent.user_data; + + LPUART_WriteByte(uart->uart_base, ch); + while(!(LPUART_GetStatusFlags(uart->uart_base) & kLPUART_TxDataRegEmptyFlag)); + + return 1; +} + +static int imxrt_getc(struct rt_serial_device *serial) +{ + int ch; + struct imxrt_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct imxrt_uart *)serial->parent.user_data; + + ch = -1; + if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag) + ch = LPUART_ReadByte(uart->uart_base); + return ch; +} + +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +static void uart_isr(struct rt_serial_device *serial) +{ + struct imxrt_uart *uart; + LPUART_Type *base; + + RT_ASSERT(serial != RT_NULL); + + uart = (struct imxrt_uart *) serial->parent.user_data; + RT_ASSERT(uart != RT_NULL); + + base = uart->uart_base; + RT_ASSERT(base != RT_NULL); + + /* enter interrupt */ + rt_interrupt_enter(); + + /* UART in mode Receiver -------------------------------------------------*/ + if (LPUART_GetStatusFlags(base) & kLPUART_RxDataRegFullFlag) + { + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + + /* If RX overrun. */ + if (LPUART_STAT_OR_MASK & base->STAT) + { + /* Clear overrun flag, otherwise the RX does not work. */ + base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK); + } + + /* leave interrupt */ + rt_interrupt_leave(); +} + +static const struct rt_uart_ops imxrt_uart_ops = +{ + imxrt_configure, + imxrt_control, + imxrt_putc, + imxrt_getc, +}; + +int imxrt_hw_usart_init(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + int i; + for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) + { + uarts[i].serial->ops = &imxrt_uart_ops; + uarts[i].serial->config = config; + + /* register UART1 device */ + rt_hw_serial_register(uarts[i].serial, + uarts[i].device_name, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + (void *)&uarts[i]); + } + + return 0; +} +INIT_BOARD_EXPORT(imxrt_hw_usart_init); + +#endif /*RT_USING_SERIAL */ diff --git a/bsp/imxrt1052-evk/drivers/drv_uart.h b/bsp/imxrt1052-evk/drivers/drv_uart.h new file mode 100644 index 0000000000..6f14c7adbd --- /dev/null +++ b/bsp/imxrt1052-evk/drivers/drv_uart.h @@ -0,0 +1,23 @@ +/* + * File : drv_uart.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2017-10-10 Tanek the first version + */ + +#ifndef __USART_H__ +#define __USART_H__ + +#include +#include + +int rt_hw_usart_init(void); + +#endif