1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
10 *
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef __MU_IMX_H__
32 #define __MU_IMX_H__
33
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <assert.h>
37 #include "device_imx.h"
38
39 /*!
40 * @addtogroup mu_driver
41 * @{
42 */
43
44 /******************************************************************************
45 * Definitions
46 *****************************************************************************/
47
48 /*!@brief Bit mask for general purpose interrupt 0 pending. */
49 #define MU_SR_GIP0_MASK (1U<<31U)
50 /*!@brief Bit mask for RX full interrupt 0 pending. */
51 #define MU_SR_RF0_MASK (1U<<27U)
52 /*!@brief Bit mask for TX empty interrupt 0 pending. */
53 #define MU_SR_TE0_MASK (1U<<23U)
54 /*!@brief Bit mask for general purpose interrupt 0 enable. */
55 #define MU_CR_GIE0_MASK (1U<<31U)
56 /*!@brief Bit mask for RX full interrupt 0 enable. */
57 #define MU_CR_RIE0_MASK (1U<<27U)
58 /*!@brief Bit mask for TX empty interrupt 0 enable. */
59 #define MU_CR_TIE0_MASK (1U<<23U)
60 /*!@brief Bit mask to trigger general purpose interrupt 0. */
61 #define MU_CR_GIR0_MASK (1U<<19U)
62
63 /*!@brief Number of general purpose interrupt. */
64 #define MU_GPn_COUNT (4U)
65
66 /* Mask for MU_CR_GIRN. When read-modify-write to MU_CR, should
67 pay attention to these bits in case of trigger interrupts by mistake.*/
68
69 /*! @brief MU status return codes. */
70 typedef enum _mu_status
71 {
72 kStatus_MU_Success = 0U, /*!< Success. */
73 kStatus_MU_TxNotEmpty = 1U, /*!< TX register is not empty. */
74 kStatus_MU_RxNotFull = 2U, /*!< RX register is not full. */
75 kStatus_MU_FlagPending = 3U, /*!< Previous flags update pending. */
76 kStatus_MU_EventPending = 4U, /*!< MU event is pending. */
77 kStatus_MU_Initialized = 5U, /*!< MU driver has initialized previously. */
78 kStatus_MU_IntPending = 6U, /*!< Previous general interrupt still pending. */
79 kStatus_MU_Failed = 7U /*!< Execution failed. */
80 } mu_status_t;
81
82 /*! @brief MU message status. */
83 typedef enum _mu_msg_status
84 {
85 kMuTxEmpty0 = MU_SR_TE0_MASK, /*!< TX0 empty status. */
86 kMuTxEmpty1 = MU_SR_TE0_MASK >> 1U, /*!< TX1 empty status. */
87 kMuTxEmpty2 = MU_SR_TE0_MASK >> 2U, /*!< TX2 empty status. */
88 kMuTxEmpty3 = MU_SR_TE0_MASK >> 3U, /*!< TX3 empty status. */
89 kMuTxEmpty = kMuTxEmpty0 |
90 kMuTxEmpty1 |
91 kMuTxEmpty2 |
92 kMuTxEmpty3, /*!< TX empty status. */
93
94 kMuRxFull0 = MU_SR_RF0_MASK, /*!< RX0 full status. */
95 kMuRxFull1 = MU_SR_RF0_MASK >> 1U, /*!< RX1 full status. */
96 kMuRxFull2 = MU_SR_RF0_MASK >> 2U, /*!< RX2 full status. */
97 kMuRxFull3 = MU_SR_RF0_MASK >> 3U, /*!< RX3 full status. */
98 kMuRxFull = kMuRxFull0 |
99 kMuRxFull1 |
100 kMuRxFull2 |
101 kMuRxFull3, /*!< RX empty status. */
102
103 kMuGenInt0 = MU_SR_GIP0_MASK, /*!< General purpose interrupt 0 pending status. */
104 kMuGenInt1 = MU_SR_GIP0_MASK >> 1U, /*!< General purpose interrupt 2 pending status. */
105 kMuGenInt2 = MU_SR_GIP0_MASK >> 2U, /*!< General purpose interrupt 2 pending status. */
106 kMuGenInt3 = MU_SR_GIP0_MASK >> 3U, /*!< General purpose interrupt 3 pending status. */
107 kMuGenInt = kMuGenInt0 |
108 kMuGenInt1 |
109 kMuGenInt2 |
110 kMuGenInt3, /*!< General purpose interrupt pending status. */
111
112 kMuStatusAll = kMuTxEmpty |
113 kMuRxFull |
114 kMuGenInt, /*!< All MU status. */
115
116 } mu_msg_status_t;
117
118 /*! @brief Power mode definition. */
119 typedef enum _mu_power_mode
120 {
121 kMuPowerModeRun = 0x00U, /*!< Run mode. */
122 kMuPowerModeWait = 0x01U, /*!< WAIT mode. */
123 kMuPowerModeStop = 0x02U, /*!< STOP mode. */
124 kMuPowerModeDsm = 0x03U, /*!< DSM mode. */
125 } mu_power_mode_t;
126
127 /*******************************************************************************
128 * API
129 ******************************************************************************/
130
131 #if defined(__cplusplus)
132 extern "C" {
133 #endif
134
135 /*!
136 * @name Initialization.
137 * @{
138 */
139 /*!
140 * @brief Initializes the MU module to reset state.
141 * This function sets the MU module control register to its default reset value.
142 *
143 * @param base Register base address for the module.
144 */
MU_Init(MU_Type * base)145 static inline void MU_Init(MU_Type * base)
146 {
147 // Clear GIEn, RIEn, TIEn, GIRn and ABFn.
148 base->CR &= ~(MU_CR_GIEn_MASK | MU_CR_RIEn_MASK | MU_CR_TIEn_MASK | MU_CR_GIRn_MASK | MU_CR_Fn_MASK);
149 }
150
151 /* @} */
152
153 /*!
154 * @name Send Messages.
155 * @{
156 */
157
158 /*!
159 * @brief Try to send a message.
160 *
161 * This function tries to send a message, if the TX register is not empty,
162 * this function returns kStatus_MU_TxNotEmpty.
163 *
164 * @param base Register base address for the module.
165 * @param regIdex Tx register index.
166 * @param msg Message to send.
167 * @retval kStatus_MU_Success Message send successfully.
168 * @retval kStatus_MU_TxNotEmpty Message not send because TX is not empty.
169 */
170 mu_status_t MU_TrySendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);
171
172 /*!
173 * @brief Block to send a message.
174 *
175 * This function waits until TX register is empty and send the message.
176 *
177 * @param base Register base address for the module.
178 * @param regIdex Tx register index.
179 * @param msg Message to send.
180 */
181 void MU_SendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);
182
183 /*!
184 * @brief Check TX empty status.
185 *
186 * This function checks the specific transmit register empty status.
187 *
188 * @param base Register base address for the module.
189 * @param index TX register index to check.
190 * @retval true TX register is empty.
191 * @retval false TX register is not empty.
192 */
MU_IsTxEmpty(MU_Type * base,uint32_t index)193 static inline bool MU_IsTxEmpty(MU_Type * base, uint32_t index)
194 {
195 return (bool)(base->SR & (MU_SR_TE0_MASK >> index));
196 }
197
198 /*!
199 * @brief Enable TX empty interrupt.
200 *
201 * This function enables specific TX empty interrupt.
202 *
203 * @param base Register base address for the module.
204 * @param index TX interrupt index to enable.
205 *
206 * Example:
207 @code
208 // To enable TX0 empty interrupts.
209 MU_EnableTxEmptyInt(MU0_BASE, 0U);
210 @endcode
211 */
MU_EnableTxEmptyInt(MU_Type * base,uint32_t index)212 static inline void MU_EnableTxEmptyInt(MU_Type * base, uint32_t index)
213 {
214 base->CR = (base->CR & ~ MU_CR_GIRn_MASK) // Clear GIRn
215 | (MU_CR_TIE0_MASK>>index); // Set TIEn
216 }
217
218 /*!
219 * @brief Disable TX empty interrupt.
220 *
221 * This function disables specific TX empty interrupt.
222 *
223 * @param base Register base address for the module.
224 * @param disableMask Bitmap of the interrupts to disable.
225 *
226 * Example:
227 @code
228 // To disable TX0 empty interrupts.
229 MU_DisableTxEmptyInt(MU0_BASE, 0U);
230 @endcode
231 */
MU_DisableTxEmptyInt(MU_Type * base,uint32_t index)232 static inline void MU_DisableTxEmptyInt(MU_Type * base, uint32_t index)
233 {
234 base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_TIE0_MASK>>index)); // Clear GIRn , clear TIEn
235 }
236
237 /* @} */
238
239 /*!
240 * @name Receive Messages.
241 * @{
242 */
243
244 /*!
245 * @brief Try to receive a message.
246 *
247 * This function tries to receive a message, if the RX register is not full,
248 * this function returns kStatus_MU_RxNotFull.
249 *
250 * @param base Register base address for the module.
251 * @param regIdex Rx register index.
252 * @param msg Message to receive.
253 * @retval kStatus_MU_Success Message receive successfully.
254 * @retval kStatus_MU_RxNotFull Message not received because RX is not full.
255 */
256 mu_status_t MU_TryReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);
257
258 /*!
259 * @brief Block to receive a message.
260 *
261 * This function waits until RX register is full and receive the message.
262 *
263 * @param base Register base address for the module.
264 * @param regIdex Rx register index.
265 * @param msg Message to receive.
266 */
267 void MU_ReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);
268
269 /*!
270 * @brief Check RX full status.
271 *
272 * This function checks the specific receive register full status.
273 *
274 * @param base Register base address for the module.
275 * @param index RX register index to check.
276 * @retval true RX register is full.
277 * @retval false RX register is not full.
278 */
MU_IsRxFull(MU_Type * base,uint32_t index)279 static inline bool MU_IsRxFull(MU_Type * base, uint32_t index)
280 {
281 return (bool)(base->SR & (MU_SR_RF0_MASK >> index));
282 }
283
284 /*!
285 * @brief Enable RX full interrupt.
286 *
287 * This function enables specific RX full interrupt.
288 *
289 * @param base Register base address for the module.
290 * @param index RX interrupt index to enable.
291 *
292 * Example:
293 @code
294 // To enable RX0 full interrupts.
295 MU_EnableRxFullInt(MU0_BASE, 0U);
296 @endcode
297 */
MU_EnableRxFullInt(MU_Type * base,uint32_t index)298 static inline void MU_EnableRxFullInt(MU_Type * base, uint32_t index)
299 {
300 base->CR = (base->CR & ~MU_CR_GIRn_MASK) // Clear GIRn
301 | (MU_CR_RIE0_MASK>>index); // Set RIEn
302 }
303
304 /*!
305 * @brief Disable RX full interrupt.
306 *
307 * This function disables specific RX full interrupt.
308 *
309 * @param base Register base address for the module.
310 * @param disableMask Bitmap of the interrupts to disable.
311 *
312 * Example:
313 @code
314 // To disable RX0 full interrupts.
315 MU_DisableRxFullInt(MU0_BASE, 0U);
316 @endcode
317 */
MU_DisableRxFullInt(MU_Type * base,uint32_t index)318 static inline void MU_DisableRxFullInt(MU_Type * base, uint32_t index)
319 {
320 base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_RIE0_MASK>>index)); // Clear GIRn, clear RIEn
321 }
322
323 /* @} */
324
325 /*!
326 * @name General Purpose Interrupt.
327 * @{
328 */
329
330 /*!
331 * @brief Enable general purpose interrupt.
332 *
333 * This function enables specific general purpose interrupt.
334 *
335 * @param base Register base address for the module.
336 * @param index General purpose interrupt index to enable.
337 *
338 * Example:
339 @code
340 // To enable general purpose interrupts 0.
341 MU_EnableGeneralInt(MU0_BASE, 0U);
342 @endcode
343 */
MU_EnableGeneralInt(MU_Type * base,uint32_t index)344 static inline void MU_EnableGeneralInt(MU_Type * base, uint32_t index)
345 {
346 base->CR = (base->CR & ~MU_CR_GIRn_MASK) // Clear GIRn
347 | (MU_CR_GIE0_MASK>>index); // Set GIEn
348 }
349
350 /*!
351 * @brief Disable general purpose interrupt.
352 *
353 * This function disables specific general purpose interrupt.
354 *
355 * @param base Register base address for the module.
356 * @param index General purpose interrupt index to disable.
357 *
358 * Example:
359 @code
360 // To disable general purpose interrupts 0.
361 MU_DisableGeneralInt(MU0_BASE, 0U);
362 @endcode
363 */
MU_DisableGeneralInt(MU_Type * base,uint32_t index)364 static inline void MU_DisableGeneralInt(MU_Type * base, uint32_t index)
365 {
366 base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_GIE0_MASK>>index)); // Clear GIRn, clear GIEn
367 }
368
369 /*!
370 * @brief Check specific general purpose interrupt pending flag.
371 *
372 * This function checks the specific general purpose interrupt pending status.
373 *
374 * @param base Register base address for the module.
375 * @param index Index of the general purpose interrupt flag to check.
376 * @retval true General purpose interrupt is pending.
377 * @retval false General purpose interrupt is not pending.
378 */
MU_IsGeneralIntPending(MU_Type * base,uint32_t index)379 static inline bool MU_IsGeneralIntPending(MU_Type * base, uint32_t index)
380 {
381 return (bool)(base->SR & (MU_SR_GIP0_MASK >> index));
382 }
383
384 /*!
385 * @brief Clear specific general purpose interrupt pending flag.
386 *
387 * This function clears the specific general purpose interrupt pending status.
388 *
389 * @param base Register base address for the module.
390 * @param index Index of the general purpose interrupt flag to clear.
391 */
MU_ClearGeneralIntPending(MU_Type * base,uint32_t index)392 static inline void MU_ClearGeneralIntPending(MU_Type * base, uint32_t index)
393 {
394 base->SR = (MU_SR_GIP0_MASK >> index);
395 }
396
397 /*!
398 * @brief Trigger specific general purpose interrupt.
399 *
400 * This function triggers specific general purpose interrupt to other core.
401 *
402 * To ensure proper operations, make sure the correspond general purpose
403 * interrupt triggered previously has been accepted by the other core. The
404 * function MU_IsGeneralIntAccepted can be used for this check. If the
405 * previous general interrupt has not been accepted by the other core, this
406 * function does not trigger interrupt actually and returns an error.
407 *
408 * @param base Register base address for the module.
409 * @param index Index of general purpose interrupt to trigger.
410 * @retval kStatus_MU_Success Interrupt has been triggered successfully.
411 * @retval kStatus_MU_IntPending Previous interrupt has not been accepted.
412 */
413 mu_status_t MU_TriggerGeneralInt(MU_Type * base, uint32_t index);
414
415 /*!
416 * @brief Check specific general purpose interrupt is accepted or not.
417 *
418 * This function checks whether the specific general purpose interrupt has
419 * been accepted by the other core or not.
420 *
421 * @param base Register base address for the module.
422 * @param index Index of the general purpose interrupt to check.
423 * @retval true General purpose interrupt is accepted.
424 * @retval false General purpose interrupt is not accepted.
425 */
MU_IsGeneralIntAccepted(MU_Type * base,uint32_t index)426 static inline bool MU_IsGeneralIntAccepted(MU_Type * base, uint32_t index)
427 {
428 return !(bool)(base->CR & (MU_CR_GIR0_MASK >> index));
429 }
430
431 /* @} */
432
433 /*!
434 * @name Flags
435 * @{
436 */
437
438 /*!
439 * @brief Try to set some bits of the 3-bit flag reflect on the other MU side.
440 *
441 * This functions tries to set some bits of the 3-bit flag. If previous flags
442 * update is still pending, this function returns kStatus_MU_FlagPending.
443 *
444 * @param base Register base address for the module.
445 * @retval kStatus_MU_Success Flag set successfully.
446 * @retval kStatus_MU_FlagPending Previous flag update is pending.
447 */
448 mu_status_t MU_TrySetFlags(MU_Type * base, uint32_t flags);
449
450 /*!
451 * @brief Set some bits of the 3-bit flag reflect on the other MU side.
452 *
453 * This functions set some bits of the 3-bit flag. If previous flags update is
454 * still pending, this function blocks and polls to set the flag.
455 *
456 * @param base Register base address for the module.
457 */
458 void MU_SetFlags(MU_Type * base, uint32_t flags);
459
460 /*!
461 * @brief Checks whether the previous flag update is pending.
462 *
463 * After setting flags, the flags update request is pending until internally
464 * acknowledged. During the pending period, it is not allowed to set flags again.
465 * This function is used to check the pending status, it can be used together
466 * with function MU_TrySetFlags.
467 *
468 * @param base Register base address for the module.
469 * @return True if pending, false if not.
470 */
MU_IsFlagPending(MU_Type * base)471 static inline bool MU_IsFlagPending(MU_Type * base)
472 {
473 return (bool)(base->SR & MU_SR_FUP_MASK);
474 }
475
476 /*!
477 * @brief Get the current value of the 3-bit flag set by other side.
478 *
479 * This functions gets the current value of the 3-bit flag.
480 *
481 * @param base Register base address for the module.
482 * @return flags Current value of the 3-bit flag.
483 */
MU_GetFlags(MU_Type * base)484 static inline uint32_t MU_GetFlags(MU_Type * base)
485 {
486 return base->SR & MU_SR_Fn_MASK;
487 }
488
489 /* @} */
490
491 /*!
492 * @name Misc.
493 * @{
494 */
495
496 /*!
497 * @brief Get the power mode of the other core.
498 *
499 * This functions gets the power mode of the other core.
500 *
501 * @param base Register base address for the module.
502 * @return powermode Power mode of the other core.
503 */
MU_GetOtherCorePowerMode(MU_Type * base)504 static inline mu_power_mode_t MU_GetOtherCorePowerMode(MU_Type * base)
505 {
506 return (mu_power_mode_t)((base->SR & MU_SR_PM_MASK) >> MU_SR_PM_SHIFT);
507 }
508
509 /*!
510 * @brief Get the event pending status.
511 *
512 * This functions gets the event pending status. To ensure events have been
513 * posted to the other side before entering STOP mode, verify the
514 * event pending status using this function.
515 *
516 * @param base Register base address for the module.
517 * @retval true Event is pending.
518 * @retval false Event is not pending.
519 */
MU_IsEventPending(MU_Type * base)520 static inline bool MU_IsEventPending(MU_Type * base)
521 {
522 return (bool)(base->SR & MU_SR_EP_MASK);
523 }
524
525 /*!
526 * @brief Get the the MU message status.
527 *
528 * This functions gets TX/RX and general purpose interrupt pending status. The
529 * parameter is passed in as bitmask of the status to check.
530 *
531 * @param base Register base address for the module.
532 * @param statusToCheck The status to check, see mu_msg_status_t.
533 * @return Status checked.
534 *
535 * Example:
536 @code
537 // To check TX0 empty status.
538 MU_GetMsgStatus(MU0_BASE, kMuTxEmpty0);
539
540 // To check all RX full status.
541 MU_GetMsgStatus(MU0_BASE, kMuRxFull);
542
543 // To check general purpose interrupt 0 and 3 pending status.
544 MU_GetMsgStatus(MU0_BASE, kMuGenInt0 | kMuGenInt3);
545
546 // To check all status.
547 MU_GetMsgStatus(MU0_BASE, kMuStatusAll);
548
549 @endcode
550 */
MU_GetMsgStatus(MU_Type * base,uint32_t statusToCheck)551 static inline uint32_t MU_GetMsgStatus(MU_Type * base, uint32_t statusToCheck)
552 {
553 return base->SR & statusToCheck;
554 }
555
556 /* @} */
557
558 #if defined(__cplusplus)
559 }
560 #endif
561
562 /*!
563 * @}
564 */
565
566 #endif /* __MU_IMX_H__ */
567 /******************************************************************************
568 * EOF
569 *****************************************************************************/
570