summaryrefslogtreecommitdiff
path: root/platform/drivers/inc/mu_imx.h
blob: 40bacc73f5009ea0e6f212805fa99e7906d0c682 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __MU_IMX_H__
#define __MU_IMX_H__

#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "device_imx.h"

/*!
 * @addtogroup mu_driver
 * @{
 */

/******************************************************************************
 * Definitions
 *****************************************************************************/

/*!@brief Bit mask for general purpose interrupt 0 pending. */
#define MU_SR_GIP0_MASK (1U<<31U)
/*!@brief Bit mask for RX full interrupt 0 pending. */
#define MU_SR_RF0_MASK (1U<<27U)
/*!@brief Bit mask for TX empty interrupt 0 pending. */
#define MU_SR_TE0_MASK (1U<<23U)
/*!@brief Bit mask for general purpose interrupt 0 enable. */
#define MU_CR_GIE0_MASK (1U<<31U)
/*!@brief Bit mask for RX full interrupt 0 enable. */
#define MU_CR_RIE0_MASK (1U<<27U)
/*!@brief Bit mask for TX empty interrupt 0 enable. */
#define MU_CR_TIE0_MASK (1U<<23U)
/*!@brief Bit mask to trigger general purpose interrupt 0. */
#define MU_CR_GIR0_MASK (1U<<19U)

/*!@brief Number of general purpose interrupt. */
#define MU_GPn_COUNT (4U)

/* Mask for MU_CR_GIRN. When read-modify-write to MU_CR, should
   pay attention to these bits in case of trigger interrupts by mistake.*/

/*!
 * @brief MU status return codes.
 */
typedef enum _mu_status
{
    kStatus_MU_Success       = 0U, /*!< Success.                              */
    kStatus_MU_TxNotEmpty    = 1U, /*!< TX register is not empty.             */
    kStatus_MU_RxNotFull     = 2U, /*!< RX register is not full.              */
    kStatus_MU_FlagPending   = 3U, /*!< Previous flags update pending.        */
    kStatus_MU_EventPending  = 4U, /*!< MU event is pending.                  */
    kStatus_MU_Initialized   = 5U, /*!< MU driver has initialized previously. */
    kStatus_MU_IntPending    = 6U, /*!< Previous general interrupt still pending. */
    kStatus_MU_Failed        = 7U  /*!< Execution failed.                     */
} mu_status_t;

/*!
 * @brief MU message status.
 */
typedef enum _mu_msg_status
{
    kMuTxEmpty0 = MU_SR_TE0_MASK,        /*!< TX0 empty status.                          */
    kMuTxEmpty1 = MU_SR_TE0_MASK >> 1U,  /*!< TX1 empty status.                          */
    kMuTxEmpty2 = MU_SR_TE0_MASK >> 2U,  /*!< TX2 empty status.                          */
    kMuTxEmpty3 = MU_SR_TE0_MASK >> 3U,  /*!< TX3 empty status.                          */
    kMuTxEmpty  = kMuTxEmpty0  |
                  kMuTxEmpty1  |
                  kMuTxEmpty2  |
                  kMuTxEmpty3,           /*!< TX empty status.                            */

    kMuRxFull0  = MU_SR_RF0_MASK,        /*!< RX0 full status.                            */
    kMuRxFull1  = MU_SR_RF0_MASK >> 1U,  /*!< RX1 full status.                            */
    kMuRxFull2  = MU_SR_RF0_MASK >> 2U,  /*!< RX2 full status.                            */
    kMuRxFull3  = MU_SR_RF0_MASK >> 3U,  /*!< RX3 full status.                            */
    kMuRxFull   = kMuRxFull0   |
                  kMuRxFull1   |
                  kMuRxFull2   |
                  kMuRxFull3,            /*!< RX empty status.                            */

    kMuGenInt0  = MU_SR_GIP0_MASK,       /*!< General purpose interrupt 0 pending status. */
    kMuGenInt1  = MU_SR_GIP0_MASK >> 1U, /*!< General purpose interrupt 2 pending status. */
    kMuGenInt2  = MU_SR_GIP0_MASK >> 2U, /*!< General purpose interrupt 2 pending status. */
    kMuGenInt3  = MU_SR_GIP0_MASK >> 3U, /*!< General purpose interrupt 3 pending status. */
    kMuGenInt   = kMuGenInt0    |
                  kMuGenInt1    |
                  kMuGenInt2    |
                  kMuGenInt3,      /*!< General purpose interrupt pending status.   */

    kMuStatusAll = kMuTxEmpty |
                   kMuRxFull  |
                   kMuGenInt,      /*!< All MU status.                              */

} mu_msg_status_t;

/*!
 * @brief Power mode definition.
 */
typedef enum _mu_power_mode
{
    kMuPowerModeRun       = 0x00U,   /*!< Run mode.    */
    kMuPowerModeWait      = 0x01U,   /*!< WAIT mode.   */
    kMuPowerModeStop      = 0x02U,   /*!< STOP mode.   */
    kMuPowerModeDsm       = 0x03U,   /*!< DSM mode.    */
} mu_power_mode_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @name Initialization.
 * @{
 */
/*!
 * @brief Initializes the MU module to reset state.
 *
 * This function sets the MU module control register to its default reset value.
 *
 * @param base Register base address for the module.
 */
static inline void MU_Init(MU_Type * base)
{
    // Clear GIEn, RIEn, TIEn, GIRn and ABFn.
    base->CR &= ~(MU_CR_GIEn_MASK | MU_CR_RIEn_MASK | MU_CR_TIEn_MASK | MU_CR_GIRn_MASK | MU_CR_Fn_MASK);
}

/* @} */

/*!
 * @name Send Messages.
 * @{
 */

/*!
 * @brief Try to send a message.
 *
 * This function tries to send a message, if the TX register is not empty,
 * this function returns kStatus_MU_TxNotEmpty.
 *
 * @param base Register base address for the module.
 * @param regIdex  Tx register index.
 * @param msg      Message to send.
 * @retval kStatus_MU_Success     Message send successfully.
 * @retval kStatus_MU_TxNotEmpty  Message not send because TX is not empty.
 */
mu_status_t MU_TrySendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);

/*!
 * @brief Block to send a message.
 *
 * This function waits until TX register is empty and send the message.
 *
 * @param base Register base address for the module.
 * @param regIdex  Tx register index.
 * @param msg      Message to send.
 */
void MU_SendMsg(MU_Type * base, uint32_t regIndex, uint32_t msg);

/*!
 * @brief Check TX empty status.
 *
 * This function checks the specific tramsmit register empty status.
 *
 * @param base Register base address for the module.
 * @param index    TX register index to check.
 * @retval true    TX register is empty.
 * @retval false   TX register is not empty.
 */
static inline bool MU_IsTxEmpty(MU_Type * base, uint32_t index)
{
    return (bool)(base->SR & (MU_SR_TE0_MASK >> index));
}

/*!
 * @brief Enable TX empty interrupt.
 *
 * This function enables specific TX empty interrupt.
 *
 * @param base   Register base address for the module.
 * @param index  TX interrupt index to enable.
 *
 * Example:
   @code
   // To enable TX0 empty interrupts.
   MU_EnableTxEmptyInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_EnableTxEmptyInt(MU_Type * base, uint32_t index)
{
    base->CR = (base->CR & ~ MU_CR_GIRn_MASK)   // Clear GIRn
                         | (MU_CR_TIE0_MASK>>index); // Set TIEn
}

/*!
 * @brief Disable TX empty interrupt.
 *
 * This function disables specific TX empty interrupt.
 *
 * @param base   Register base address for the module.
 * @param disableMask Bitmap of the interrupts to disable.
 *
 * Example:
   @code
   // To disable TX0 empty interrupts.
   MU_DisableTxEmptyInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_DisableTxEmptyInt(MU_Type * base, uint32_t index)
{
    base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_TIE0_MASK>>index)); // Clear GIRn , clear TIEn
}

/* @} */

/*!
 * @name Receive Messages.
 * @{
 */

/*!
 * @brief Try to receive a message.
 *
 * This function tries to receive a message, if the RX register is not full,
 * this function returns kStatus_MU_RxNotFull.
 *
 * @param base Register base address for the module.
 * @param regIdex  Rx register index.
 * @param msg      Message to receive.
 * @retval kStatus_MU_Success    Message receive successfully.
 * @retval kStatus_MU_RxNotFull  Message not received because RX is not full.
 */
mu_status_t MU_TryReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);

/*!
 * @brief Block to receive a message.
 *
 * This function waits until RX register is full and receive the message.
 *
 * @param base Register base address for the module.
 * @param regIdex  Rx register index.
 * @param msg      Message to receive.
 */
void MU_ReceiveMsg(MU_Type * base, uint32_t regIndex, uint32_t *msg);

/*!
 * @brief Check RX full status.
 *
 * This function checks the specific receive register full status.
 *
 * @param base Register base address for the module.
 * @param index    RX register index to check.
 * @retval true    RX register is full.
 * @retval false   RX register is not full.
 */
static inline bool MU_IsRxFull(MU_Type * base, uint32_t index)
{
    return (bool)(base->SR & (MU_SR_RF0_MASK >> index));
}

/*!
 * @brief Enable RX full interrupt.
 *
 * This function enables specific RX full interrupt.
 *
 * @param base   Register base address for the module.
 * @param index      RX interrupt index to enable.
 *
 * Example:
   @code
   // To enable RX0 full interrupts.
   MU_EnableRxFullInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_EnableRxFullInt(MU_Type * base, uint32_t index)
{
    base->CR = (base->CR & ~MU_CR_GIRn_MASK)  // Clear GIRn
                         | (MU_CR_RIE0_MASK>>index); // Set RIEn
}

/*!
 * @brief Disable RX full interrupt.
 *
 * This function disables specific RX full interrupt.
 *
 * @param base   Register base address for the module.
 * @param disableMask Bitmap of the interrupts to disable.
 *
 * Example:
   @code
   // To disable RX0 full interrupts.
   MU_DisableRxFullInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_DisableRxFullInt(MU_Type * base, uint32_t index)
{
    base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_RIE0_MASK>>index)); // Clear GIRn, clear RIEn
}

/* @} */

/*!
 * @name General Purpose Interrupt.
 * @{
 */

/*!
 * @brief Enable general purpose interrupt.
 *
 * This function enables specific general purpose interrupt.
 *
 * @param base   Register base address for the module.
 * @param index      General purpose interrupt index to enable.
 *
 * Example:
   @code
   // To enable general purpose interrupts 0.
   MU_EnableGeneralInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_EnableGeneralInt(MU_Type * base, uint32_t index)
{
    base->CR = (base->CR & ~MU_CR_GIRn_MASK)  // Clear GIRn
                         | (MU_CR_GIE0_MASK>>index); // Set GIEn
}

/*!
 * @brief Disable general purpose interrupt.
 *
 * This function disables specific general purpose interrupt.
 *
 * @param base   Register base address for the module.
 * @param index      General purpose interrupt index to disable.
 *
 * Example:
   @code
   // To disable general purpose interrupts 0.
   MU_DisableGeneralInt(MU0_BASE, 0U);
   @endcode
 */
static inline void MU_DisableGeneralInt(MU_Type * base, uint32_t index)
{
    base->CR &= ~(MU_CR_GIRn_MASK | (MU_CR_GIE0_MASK>>index));  // Clear GIRn, clear GIEn
}

/*!
 * @brief Check specific general purpose interrupt pending flag.
 *
 * This function checks the specific general purpose interrupt pending status.
 *
 * @param base Register base address for the module.
 * @param index    Index of the general purpose interrupt flag to check.
 * @retval true    General purpose interrupt is pending.
 * @retval false   General purpose interrupt is not pending.
 */
static inline bool MU_IsGeneralIntPending(MU_Type * base, uint32_t index)
{
    return (bool)(base->SR & (MU_SR_GIP0_MASK >> index));
}

/*!
 * @brief Clear specific general purpose interrupt pending flag.
 *
 * This function clears the specific general purpose interrupt pending status.
 *
 * @param base Register base address for the module.
 * @param index    Index of the general purpose interrupt flag to clear.
 */
static inline void MU_ClearGeneralIntPending(MU_Type * base, uint32_t index)
{
    base->SR = (MU_SR_GIP0_MASK >> index);
}

/*!
 * @brief Trigger specific general purpose interrupt.
 *
 * This function triggers specific general purpose interrupt to other core.
 *
 * To ensure proper operations, please make sure the correspond general purpose
 * interrupt triggerd previously has been accepted by the other core. The
 * function MU_IsGeneralIntAccepted could be used for this check. If the
 * previous general interrupt has not been accepted by the other core, this
 * function does not trigger interrupt acctually and returns error.
 *
 * @param base Register base address for the module.
 * @param index    Index of general purpose interrupt to trigger.
 * @retval kStatus_MU_Success    Interrupt has been triggered successfully.
 * @retval kStatus_MU_IntPending Previous interrupt has not been accepted.
 */
mu_status_t MU_TriggerGeneralInt(MU_Type * base, uint32_t index);

/*!
 * @brief Check specific general purpose interrupt is accepted or not.
 *
 * This function checks whether the specific general purpose interrupt has
 * been accepted by the other core or not.
 *
 * @param base Register base address for the module.
 * @param index    Index of the general purpose interrupt to check.
 * @retval true    General purpose interrupt is accepted.
 * @retval false   General purpose interrupt is not accepted.
 */
static inline bool MU_IsGeneralIntAccepted(MU_Type * base, uint32_t index)
{
    return !(bool)(base->CR & (MU_CR_GIR0_MASK >> index));
}

/* @} */

/*!
 * @name Flags
 * @{
 */

/*!
 * @brief Try to set some bits of the 3-bit flag reflect on the other MU side.
 *
 * This functions tries to set some bits of the 3-bit flag. If previous flags
 * update is still pending, this function returns kStatus_MU_FlagPending.
 *
 * @param base Register base address for the module.
 * @retval kStatus_MU_Success     Flag set successfully.
 * @retval kStatus_MU_FlagPending Previous flag update is pending.
 */
mu_status_t MU_TrySetFlags(MU_Type * base, uint32_t flags);

/*!
 * @brief Set some bits of the 3-bit flag reflect on the other MU side.
 *
 * This functions set some bits of the 3-bit flag. If previous flags update is
 * still pending, this function will block and poll to set the flag.
 *
 * @param base Register base address for the module.
 */
void MU_SetFlags(MU_Type * base, uint32_t flags);

/*!
 * @brief Checks whether the previous flag update is pending.
 *
 * After setting flags, the flags update request is pending untill internally
 * acknowledged. During the pending period, it is not allowed to set flags again.
 * This function is used to check the pending status, it could be used together
 * with function MU_TrySetFlags.
 *
 * @param base Register base address for the module.
 * @return True if pending, faulse if not.
 */
static inline bool MU_IsFlagPending(MU_Type * base)
{
    return (bool)(base->SR & MU_SR_FUP_MASK);
}

/*!
 * @brief Get the current value of the 3-bit flag set by other side.
 *
 * This functions gets the current value of the 3-bit flag.
 *
 * @param base Register base address for the module.
 * @return flags   Current value of the 3-bit flag.
 */
static inline uint32_t MU_GetFlags(MU_Type * base)
{
    return base->SR & MU_SR_Fn_MASK;
}

/* @} */

/*!
 * @name Misc.
 * @{
 */

/*!
 * @brief Get the power mode of the other core.
 *
 * This functions gets the power mode of the other core.
 *
 * @param base Register base address for the module.
 * @return powermode Power mode of the other core.
 */
static inline mu_power_mode_t MU_GetOtherCorePowerMode(MU_Type * base)
{
    return (mu_power_mode_t)((base->SR & MU_SR_PM_MASK) >> MU_SR_PM_SHIFT);
}

/*!
 * @brief Get the event pending status.
 *
 * This functions gets the event pending status. To ensure events have been
 * posted to the other side before entering STOP mode, please verify the
 * event pending status using this function.
 *
 * @param base Register base address for the module.
 * @retval true    Event is pending.
 * @retval false   Event is not pending.
 */
static inline bool MU_IsEventPending(MU_Type * base)
{
    return (bool)(base->SR & MU_SR_EP_MASK);
}

/*!
 * @brief Get the the MU message status.
 *
 * This functions gets TX/RX and general purpose interrupt pending status. The
 * parameter is passed in as bitmask of the status to check.
 *
 * @param base Register base address for the module.
 * @param statusToCheck The status to check, see mu_msg_status_t.
 * @return Status checked.
 *
 * Example:
   @code
   // To check TX0 empty status.
   MU_GetMsgStatus(MU0_BASE, kMuTxEmpty0);

   // To check all RX full status.
   MU_GetMsgStatus(MU0_BASE, kMuRxFull);

   // To check general purpose interrupt 0 and 3 pending status.
   MU_GetMsgStatus(MU0_BASE, kMuGenInt0 | kMuGenInt3);

   // To check all status.
   MU_GetMsgStatus(MU0_BASE, kMuStatusAll);

   @endcode
 */
static inline uint32_t MU_GetMsgStatus(MU_Type * base, uint32_t statusToCheck)
{
    return base->SR & statusToCheck;
}

/* @} */

#if defined(__cplusplus)
}
#endif

/*!
 * @}
 */

#endif /* __MU_IMX_H__ */
/******************************************************************************
 * EOF
 *****************************************************************************/