1/*
2 * Copyright (c) 2007-2015 Freescale Semiconductor, Inc.
3 * Copyright 2018-2020 NXP
4 *
5 * License: NXP LA_OPT_NXP_Software_License
6 *
7 * NXP Confidential. This software is owned or controlled by NXP and may
8 * only be used strictly in accordance with the applicable license terms.
9 * By expressly accepting such terms or by downloading, installing,
10 * activating and/or otherwise using the software, you are agreeing that
11 * you have read, and that you agree to comply with and are bound by,
12 * such license terms. If you do not agree to be bound by the applicable
13 * license terms, then you may not retain, install, activate or otherwise
14 * use the software. This code may only be used in a microprocessor,
15 * microcontroller, sensor or digital signal processor ("NXP Product")
16 * supplied directly or indirectly from NXP. See the full NXP Software
17 * License Agreement in license/LA_OPT_NXP_Software_License.pdf
18 *
19 * FreeMASTER Communication Driver - LPUART low-level driver
20 */
21
22#include "freemaster.h"
23#include "freemaster_private.h"
24
25/* Numeric identifier to help pre-processor to identify whether our driver is used or not. */
26#define FMSTR_SERIAL_MCUX_LPUART_ID 1
27
28#if (FMSTR_MK_IDSTR(FMSTR_SERIAL_DRV) == FMSTR_SERIAL_MCUX_LPUART_ID)
29
30#include "freemaster_serial_lpuart.h"
31
32#if FMSTR_DISABLE == 0
33
34#include "fsl_common.h"
35#include "fsl_lpuart.h"
36
37#include "freemaster_protocol.h"
38#include "freemaster_serial.h"
39
40/******************************************************************************
41 * Adapter configuration
42 ******************************************************************************/
43
44/***********************************
45 * local variables
46 ***********************************/
47
48/* Serial base address */
49#ifdef FMSTR_SERIAL_BASE
50static LPUART_Type *fmstr_serialBaseAddr = FMSTR_SERIAL_BASE;
51#else
52static LPUART_Type *fmstr_serialBaseAddr = NULL;
53#endif
54
55/***********************************
56 * local function prototypes
57 ***********************************/
58
59/* Interface function - Initialization of serial UART driver adapter */
60static FMSTR_BOOL _FMSTR_SerialLpuartInit(void);
61static void _FMSTR_SerialLpuartEnableTransmit(FMSTR_BOOL enable);
62static void _FMSTR_SerialLpuartEnableReceive(FMSTR_BOOL enable);
63static void _FMSTR_SerialLpuartEnableTransmitInterrupt(FMSTR_BOOL enable);
64static void _FMSTR_SerialLpuartEnableTransmitCompleteInterrupt(FMSTR_BOOL enable);
65static void _FMSTR_SerialLpuartEnableReceiveInterrupt(FMSTR_BOOL enable);
66static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitRegEmpty(void);
67static FMSTR_BOOL _FMSTR_SerialLpuartIsReceiveRegFull(void);
68static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitterActive(void);
69static void _FMSTR_SerialLpuartPutChar(FMSTR_BCHR ch);
70static FMSTR_BCHR _FMSTR_SerialLpuartGetChar(void);
71static void _FMSTR_SerialLpuartFlush(void);
72
73/***********************************
74 * global variables
75 ***********************************/
76/* Interface of this serial UART driver */
77const FMSTR_SERIAL_DRV_INTF FMSTR_SERIAL_MCUX_LPUART = {
78 .Init = _FMSTR_SerialLpuartInit,
79 .EnableTransmit = _FMSTR_SerialLpuartEnableTransmit,
80 .EnableReceive = _FMSTR_SerialLpuartEnableReceive,
81 .EnableTransmitInterrupt = _FMSTR_SerialLpuartEnableTransmitInterrupt,
82 .EnableTransmitCompleteInterrupt = _FMSTR_SerialLpuartEnableTransmitCompleteInterrupt,
83 .EnableReceiveInterrupt = _FMSTR_SerialLpuartEnableReceiveInterrupt,
84 .IsTransmitRegEmpty = _FMSTR_SerialLpuartIsTransmitRegEmpty,
85 .IsReceiveRegFull = _FMSTR_SerialLpuartIsReceiveRegFull,
86 .IsTransmitterActive = _FMSTR_SerialLpuartIsTransmitterActive,
87 .PutChar = _FMSTR_SerialLpuartPutChar,
88 .GetChar = _FMSTR_SerialLpuartGetChar,
89 .Flush = _FMSTR_SerialLpuartFlush,
90
91};
92
93/******************************************************************************
94 *
95 * @brief Serial communication initialization
96 *
97 ******************************************************************************/
98static FMSTR_BOOL _FMSTR_SerialLpuartInit(void)
99{
100 /* Valid runtime module address must be assigned */
101 if (fmstr_serialBaseAddr == NULL)
102 {
103 return FMSTR_FALSE;
104 }
105
106#if FMSTR_SERIAL_SINGLEWIRE > 0
107 /* Enable single wire mode and force TX and RX to be enabled all the time. */
108 fmstr_serialBaseAddr->CTRL |= LPUART_CTRL_LOOPS_MASK | LPUART_CTRL_RSRC_MASK;
109 LPUART_EnableTx(fmstr_serialBaseAddr, 1);
110 LPUART_EnableRx(fmstr_serialBaseAddr, 1);
111#endif
112
113 return FMSTR_TRUE;
114}
115
116/******************************************************************************
117 *
118 * @brief Enable/Disable Serial transmitter
119 *
120 ******************************************************************************/
121
122static void _FMSTR_SerialLpuartEnableTransmit(FMSTR_BOOL enable)
123{
124#if FMSTR_SERIAL_SINGLEWIRE > 0
125 /* In single-wire mode, the Transmitter is never physically disabled since it was
126 enabled in the Init() call. The TX pin direction is being changed only. */
127 if (enable != 0U)
128 {
129 fmstr_serialBaseAddr->CTRL |= LPUART_CTRL_TXDIR_MASK;
130 }
131 else
132 {
133 fmstr_serialBaseAddr->CTRL &= ~LPUART_CTRL_TXDIR_MASK;
134 }
135#else
136 /* In normal mode (or "external" single-wire mode) the Transmitter is controlled. */
137 LPUART_EnableTx(fmstr_serialBaseAddr, enable != FMSTR_FALSE);
138#endif
139}
140
141/******************************************************************************
142 *
143 * @brief Enable/Disable Serial receiver
144 *
145 ******************************************************************************/
146
147static void _FMSTR_SerialLpuartEnableReceive(FMSTR_BOOL enable)
148{
149#if FMSTR_SERIAL_SINGLEWIRE > 0
150 /* In single-wire mode, the Receiver is never physically disabled since it was
151 enabled in the Init() call. The TX pin direction is being changed only. */
152 FMSTR_UNUSED(enable);
153#else
154 /* In normal mode (or "external" single-wire mode) the Receiver is controlled. */
155 LPUART_EnableRx(fmstr_serialBaseAddr, enable != FMSTR_FALSE);
156#endif
157}
158
159/******************************************************************************
160 *
161 * @brief Enable/Disable interrupt from transmit register empty event
162 *
163 ******************************************************************************/
164
165static void _FMSTR_SerialLpuartEnableTransmitInterrupt(FMSTR_BOOL enable)
166{
167 if (enable != FMSTR_FALSE)
168 {
169 LPUART_EnableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_TxDataRegEmptyInterruptEnable);
170 }
171 else
172 {
173 LPUART_DisableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_TxDataRegEmptyInterruptEnable);
174 }
175}
176
177/******************************************************************************
178 *
179 * @brief Enable/Disable interrupt from transmit complete event
180 *
181 ******************************************************************************/
182
183static void _FMSTR_SerialLpuartEnableTransmitCompleteInterrupt(FMSTR_BOOL enable)
184{
185 if (enable != FMSTR_FALSE)
186 {
187 LPUART_EnableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
188 }
189 else
190 {
191 LPUART_DisableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
192 }
193}
194
195/******************************************************************************
196 *
197 * @brief Enable/Disable interrupt from receive register full event
198 *
199 ******************************************************************************/
200
201static void _FMSTR_SerialLpuartEnableReceiveInterrupt(FMSTR_BOOL enable)
202{
203 if (enable != FMSTR_FALSE)
204 {
205 LPUART_EnableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_RxDataRegFullInterruptEnable);
206 }
207 else
208 {
209 LPUART_DisableInterrupts(fmstr_serialBaseAddr, (uint32_t)kLPUART_RxDataRegFullInterruptEnable);
210 }
211}
212
213/******************************************************************************
214 *
215 * @brief Returns TRUE if the transmit register is empty, and it's possible to put next char
216 *
217 ******************************************************************************/
218
219static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitRegEmpty(void)
220{
221 uint32_t sr = LPUART_GetStatusFlags(fmstr_serialBaseAddr);
222
223 return (FMSTR_BOOL)((sr & (uint32_t)kLPUART_TxDataRegEmptyFlag) != 0U);
224}
225
226/******************************************************************************
227 *
228 * @brief Returns TRUE if the receive register is full, and it's possible to get received char
229 *
230 ******************************************************************************/
231
232static FMSTR_BOOL _FMSTR_SerialLpuartIsReceiveRegFull(void)
233{
234 uint32_t sr = LPUART_GetStatusFlags(fmstr_serialBaseAddr);
235
236 return (FMSTR_BOOL)((sr & (uint32_t)kLPUART_RxDataRegFullFlag) != 0U);
237}
238
239/******************************************************************************
240 *
241 * @brief Returns TRUE if the transmitter is still active
242 *
243 ******************************************************************************/
244
245static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitterActive(void)
246{
247 uint32_t sr = LPUART_GetStatusFlags(fmstr_serialBaseAddr);
248
249 return (FMSTR_BOOL)((sr & (uint32_t)kLPUART_TransmissionCompleteFlag) == 0U);
250}
251
252/******************************************************************************
253 *
254 * @brief The function puts the char for transmit
255 *
256 ******************************************************************************/
257
258static void _FMSTR_SerialLpuartPutChar(FMSTR_BCHR ch)
259{
260 LPUART_WriteByte(fmstr_serialBaseAddr, ch);
261}
262
263/******************************************************************************
264 *
265 * @brief The function gets the received char
266 *
267 ******************************************************************************/
268static FMSTR_BCHR _FMSTR_SerialLpuartGetChar(void)
269{
270 return LPUART_ReadByte(fmstr_serialBaseAddr);
271}
272
273/******************************************************************************
274 *
275 * @brief The function sends buffered data
276 *
277 ******************************************************************************/
278static void _FMSTR_SerialLpuartFlush(void)
279{
280}
281
282/******************************************************************************
283 *
284 * @brief Assigning FreeMASTER communication module base address
285 *
286 ******************************************************************************/
287void FMSTR_SerialSetBaseAddress(LPUART_Type *base)
288{
289 fmstr_serialBaseAddr = base;
290}
291
292/******************************************************************************
293 *
294 * @brief API: Interrupt handler call
295 *
296 * This Interrupt Service Routine handles the UART interrupts for the FreeMASTER
297 * driver. In case you want to handle the interrupt in the application yourselves,
298 * call the FMSTR_ProcessSerial function which
299 * does the same job but is not compiled as an Interrupt Service Routine.
300 *
301 * In poll-driven mode (FMSTR_POLL_DRIVEN) this function does nothing.
302 *
303 ******************************************************************************/
304
305void FMSTR_SerialIsr(void)
306{
307#if FMSTR_LONG_INTR > 0 || FMSTR_SHORT_INTR > 0
308 /* Process received or just-transmitted byte. */
309 FMSTR_ProcessSerial();
310#endif
311}
312
313#else /* (!(FMSTR_DISABLE)) */
314
315void FMSTR_SerialSetBaseAddress(LPUART_Type *base)
316{
317 FMSTR_UNUSED(base);
318}
319
320void FMSTR_SerialIsr(void)
321{
322}
323
324#endif /* (!(FMSTR_DISABLE)) */
325#endif /* (FMSTR_MK_IDSTR(FMSTR_SERIAL_DRV) == FMSTR_SERIAL_MCUX_LPUART_ID) */
326