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 |
50 | static LPUART_Type *fmstr_serialBaseAddr = FMSTR_SERIAL_BASE; |
51 | #else |
52 | static LPUART_Type *fmstr_serialBaseAddr = NULL; |
53 | #endif |
54 | |
55 | /*********************************** |
56 | * local function prototypes |
57 | ***********************************/ |
58 | |
59 | /* Interface function - Initialization of serial UART driver adapter */ |
60 | static FMSTR_BOOL _FMSTR_SerialLpuartInit(void); |
61 | static void _FMSTR_SerialLpuartEnableTransmit(FMSTR_BOOL enable); |
62 | static void _FMSTR_SerialLpuartEnableReceive(FMSTR_BOOL enable); |
63 | static void _FMSTR_SerialLpuartEnableTransmitInterrupt(FMSTR_BOOL enable); |
64 | static void _FMSTR_SerialLpuartEnableTransmitCompleteInterrupt(FMSTR_BOOL enable); |
65 | static void _FMSTR_SerialLpuartEnableReceiveInterrupt(FMSTR_BOOL enable); |
66 | static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitRegEmpty(void); |
67 | static FMSTR_BOOL _FMSTR_SerialLpuartIsReceiveRegFull(void); |
68 | static FMSTR_BOOL _FMSTR_SerialLpuartIsTransmitterActive(void); |
69 | static void _FMSTR_SerialLpuartPutChar(FMSTR_BCHR ch); |
70 | static FMSTR_BCHR _FMSTR_SerialLpuartGetChar(void); |
71 | static void _FMSTR_SerialLpuartFlush(void); |
72 | |
73 | /*********************************** |
74 | * global variables |
75 | ***********************************/ |
76 | /* Interface of this serial UART driver */ |
77 | const 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 | ******************************************************************************/ |
98 | static 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 | |
122 | static 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 | |
147 | static 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 | |
165 | static 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 | |
183 | static 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 | |
201 | static 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 | |
219 | static 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 | |
232 | static 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 | |
245 | static 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 | |
258 | static 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 | ******************************************************************************/ |
268 | static 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 | ******************************************************************************/ |
278 | static void _FMSTR_SerialLpuartFlush(void) |
279 | { |
280 | } |
281 | |
282 | /****************************************************************************** |
283 | * |
284 | * @brief Assigning FreeMASTER communication module base address |
285 | * |
286 | ******************************************************************************/ |
287 | void 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 | |
305 | void 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 | |
315 | void FMSTR_SerialSetBaseAddress(LPUART_Type *base) |
316 | { |
317 | FMSTR_UNUSED(base); |
318 | } |
319 | |
320 | void FMSTR_SerialIsr(void) |
321 | { |
322 | } |
323 | |
324 | #endif /* (!(FMSTR_DISABLE)) */ |
325 | #endif /* (FMSTR_MK_IDSTR(FMSTR_SERIAL_DRV) == FMSTR_SERIAL_MCUX_LPUART_ID) */ |
326 | |