1 /*
2 * Copyright 2020-2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #ifndef FSL_IMU_H_
8 #define FSL_IMU_H_
9
10 #include "fsl_common.h"
11
12 /*!
13 * @addtogroup imu
14 * @{
15 */
16
17 /******************************************************************************
18 * Definitions
19 *****************************************************************************/
20
21 /*! @name Driver version */
22 /*! @{ */
23 /*! @brief IMU driver version. */
24 #define FSL_IMU_DRIVER_VERSION (MAKE_VERSION(2, 1, 1))
25 /*! @} */
26
27 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK (1UL)
28 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK (1UL << 1U)
29 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK (1UL << 2U)
30 #define IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK (1UL << 3U)
31 #define IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK (0x1FUL << 4U)
32 #define IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT (4U)
33 #define IMU_MSG_FIFO_STATUS_WR_PTR_MASK (0xFUL << 16U)
34 #define IMU_MSG_FIFO_STATUS_WR_PTR_SHIFT (16U)
35 #define IMU_MSG_FIFO_STATUS_RD_PTR_MASK (0xFUL << 20U)
36 #define IMU_MSG_FIFO_STATUS_RD_PTR_SHIFT (20U)
37
38 #define IMU_MSG_FIFO_CNTL_MSG_RDY_INT_CLR_MASK (1UL << 0U)
39 #define IMU_MSG_FIFO_CNTL_SP_AV_INT_CLR_MASK (1UL << 1U)
40 #define IMU_MSG_FIFO_CNTL_FIFO_FLUSH_MASK (1UL << 16U)
41 #define IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK (1UL << 17U)
42 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_MASK (0x0FUL << 20U)
43 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_SHIFT (20U)
44 #define IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK(x) (((uint32_t)(x)) << 20U)
45
46 /* Write message directly. */
47 #define IMU_WR_MSG(link, msg) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->WR_MSG = (msg))
48
49 /* Read message directly. */
50 #define IMU_RD_MSG(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->RD_MSG)
51
52 /* Check whether RX FIFO is locked. */
53 #define IMU_RX_FIFO_LOCKED(link) \
54 (0UL != \
55 (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
56
57 /* Check whether TX FIFO is locked. */
58 #define IMU_TX_FIFO_LOCKED(link) \
59 (0UL != \
60 (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
61
62 /* Check whether TX FIFO is almost full. */
63 #define IMU_TX_FIFO_ALMOST_FULL(link) \
64 (0UL != (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & \
65 IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK))
66
67 /*! @brief Get Rx FIFO empty status. */
68 #define IMU_RX_FIFO_EMPTY(link) \
69 (0UL != \
70 (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK))
71
72 /* Lock the TX FIFO. */
73 #define IMU_LOCK_TX_FIFO(link) \
74 (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK)
75
76 /* Unlock the TX FIFO. */
77 #define IMU_UNLOCK_TX_FIFO(link) \
78 (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL &= ~IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK)
79
80 /* Get message count in RX FIFO. */
81 #define IMU_RX_FIFO_MSG_COUNT(link) \
82 ((((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> \
83 IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
84
85 /* Get message count in TX FIFO. */
86 #define IMU_TX_FIFO_MSG_COUNT(link) \
87 ((((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS & IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> \
88 IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
89
90 /* Get message count from RX FIFO status register value. */
91 #define IMU_RX_FIFO_MSG_COUNT_FROM_STATUS(rxFifoStatus) \
92 (((rxFifoStatus)&IMU_MSG_FIFO_STATUS_MSG_COUNT_MASK) >> IMU_MSG_FIFO_STATUS_MSG_COUNT_SHIFT)
93
94 /* Get RX FIFO lock status from RX FIFO status register value. */
95 #define IMU_RX_FIFO_LOCKED_FROM_STATUS(rxFifoStatus) (0UL != ((rxFifoStatus)&IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK))
96
97 /* TX FIFO status register. */
98 #define IMU_TX_FIFO_STATUS(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_STATUS)
99
100 /* RX FIFO status register. */
101 #define IMU_RX_FIFO_STATUS(link) (((IMU_Type *)(uintptr_t)IMU_PEER_CPU_BASE(link))->MSG_FIFO_STATUS)
102
103 /* RX FIFO control register. */
104 #define IMU_TX_FIFO_CNTL(link) (((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL)
105
106 /*! @brief IMU driver returned error value. */
107 #define IMU_ERR_TX_FIFO_LOCKED (-1L)
108
109 /*! @brief Maximum message numbers in FIFO. */
110 #define IMU_MSG_FIFO_MAX_COUNT 16U
111
112 /*! @brief Maximum message FIFO warter mark. */
113 #define IMU_MAX_MSG_FIFO_WATER_MARK (IMU_MSG_FIFO_MAX_COUNT - 1U)
114
115 /* IMP: ICC_MAX_MSG_CNT should be power of 2 */
116 #define IMU_FIFO_SW_WRAPAROUND(ptr) ((ptr) & (IMU_MSG_FIFO_MAX_COUNT - 1U))
117
118 #define IMU_WR_PTR(link) \
119 IMU_FIFO_SW_WRAPAROUND((IMU_TX_FIFO_STATUS(link) & IMU_MSG_FIFO_STATUS_WR_PTR_MASK) >> \
120 IMU_MSG_FIFO_STATUS_WR_PTR_SHIFT)
121
122 #define IMU_RD_PTR(link) \
123 IMU_FIFO_SW_WRAPAROUND((IMU_RX_FIFO_STATUS(link) & IMU_MSG_FIFO_STATUS_RD_PTR_MASK) >> \
124 IMU_MSG_FIFO_STATUS_RD_PTR_SHIFT)
125
126 /*!
127 * @brief IMU status flags.
128 * @anchor _imu_status_flags
129 */
130 enum _imu_status_flags
131 {
132 kIMU_TxFifoEmpty = IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK,
133 kIMU_TxFifoFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK,
134 kIMU_TxFifoAlmostFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK,
135 kIMU_TxFifoLocked = IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK,
136 kIMU_RxFifoEmpty = IMU_MSG_FIFO_STATUS_MSG_FIFO_EMPTY_MASK << 8U,
137 kIMU_RxFifoFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_FULL_MASK << 8U,
138 kIMU_RxFifoAlmostFull = IMU_MSG_FIFO_STATUS_MSG_FIFO_ALMOST_FULL_MASK << 8U,
139 kIMU_RxFifoLocked = IMU_MSG_FIFO_STATUS_MSG_FIFO_LOCKED_MASK << 8U,
140 };
141
142 /*!
143 * @brief IMU interrupt.
144 * @anchor _imu_interrupts
145 */
146 enum _imu_interrupts
147 {
148 kIMU_RxMsgReadyInterrupt = IMU_MSG_FIFO_CNTL_MSG_RDY_INT_CLR_MASK,
149 kIMU_TxFifoSpaceAvailableInterrupt = IMU_MSG_FIFO_CNTL_SP_AV_INT_CLR_MASK,
150 };
151
152 /*! @brief IMU register structure. */
153 typedef struct
154 {
155 volatile uint32_t WR_MSG;
156 const volatile uint32_t RD_MSG;
157 const volatile uint32_t MSG_FIFO_STATUS;
158 volatile uint32_t MSG_FIFO_CNTL;
159 const volatile uint32_t RD_MSG_DBG;
160 } IMU_Type;
161
162 /*******************************************************************************
163 * API
164 ******************************************************************************/
165
166 #if defined(__cplusplus)
167 extern "C" {
168 #endif
169
170 /*!
171 * @name IMU initialization.
172 * @{
173 */
174
175 /*!
176 * @brief Initializes the IMU module.
177 *
178 * This function sets IMU to initialized state, including:
179 *
180 * - Flush the send FIFO.
181 * - Unlock the send FIFO.
182 * - Set the water mark to (IMU_MAX_MSG_FIFO_WATER_MARK)
183 * - Flush the read FIFO.
184 *
185 * @param link IMU link.
186 * @retval kStatus_InvalidArgument The link is invalid.
187 * @retval kStatus_Success Initialized successfully.
188 */
189 status_t IMU_Init(imu_link_t link);
190
191 /*!
192 * @brief De-initializes the IMU module.
193 *
194 * @param link IMU link.
195 */
196 void IMU_Deinit(imu_link_t link);
197
198 /*! @} */
199
200 /*!
201 * @name IMU Message
202 * @{
203 */
204
205 /*!
206 * @brief Write one message to TX FIFO.
207 *
208 * This function writes message to the TX FIFO, user need to make sure
209 * there is empty space in the TX FIFO, and TX FIFO not locked before
210 * calling this function.
211 *
212 * @param link IMU link.
213 * @param msg The message to send.
214 */
IMU_WriteMsg(imu_link_t link,uint32_t msg)215 static inline void IMU_WriteMsg(imu_link_t link, uint32_t msg)
216 {
217 IMU_WR_MSG(link, msg);
218 }
219
220 /*!
221 * @brief Read one message from RX FIFO.
222 *
223 * User need to make sure there is available message in the RX FIFO.
224 *
225 * @param link IMU link.
226 * @return The message.
227 */
IMU_ReadMsg(imu_link_t link)228 static inline uint32_t IMU_ReadMsg(imu_link_t link)
229 {
230 return IMU_RD_MSG(link);
231 }
232
233 /*!
234 * @brief Blocking to send messages.
235 *
236 * This function blocks until all messages have been filled to TX FIFO.
237 *
238 * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
239 * - If TX FIFO not locked, this function waits the available empty slot in TX FIFO,
240 * and fills the message to TX FIFO.
241 * - To lock TX FIFO after filling all messages, set @p lockSendFifo to true.
242 *
243 * @param link IMU link.
244 * @param msgs The messages to send.
245 * @param msgCount Message count, one message is a 32-bit word.
246 * @param lockSendFifo If set to true, the TX FIFO is locked after all messages filled to TX FIFO.
247 * @return If TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED,
248 * otherwise, this function returns the actual message count sent out, it equals @p msgCount
249 * because this function is blocking function, it returns until all messages have been
250 * filled into TX FIFO.
251 */
252 int32_t IMU_SendMsgsBlocking(imu_link_t link, const uint32_t *msgs, int32_t msgCount, bool lockSendFifo);
253
254 /*!
255 * @brief Try to send messages.
256 *
257 * This function is similar with @ref IMU_SendMsgsBlocking, the difference is,
258 * this function tries to send as many as possible, if there is not enough
259 * empty slot in TX FIFO, this function fills messages to available empty slots
260 * and returns how many messages have been filled.
261 *
262 * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
263 * - If TX FIFO not locked, this function fills messages to TX FIFO empty slot,
264 * and returns how many messages have been filled.
265 * - If @p lockSendFifo is set to true, TX FIFO is locked after all messages have
266 * been filled to TX FIFO. In other word, TX FIFO is locked if the function
267 * return value equals @p msgCount, when @p lockSendFifo set to true.
268 *
269 * @param link IMU link.
270 * @param msgs The messages to send.
271 * @param msgCount Message count, one message is a 32-bit word.
272 * @param lockSendFifo If set to true, the TX FIFO is locked after all messages filled to TX FIFO.
273 * @return If TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED,
274 * otherwise, this function returns the actual message count sent out.
275 */
276 int32_t IMU_TrySendMsgs(imu_link_t link, const uint32_t *msgs, int32_t msgCount, bool lockSendFifo);
277
278 /*!
279 * @brief Try to receive messages.
280 *
281 * This function tries to read messages from RX FIFO. It reads the messages already
282 * exists in RX FIFO and returns the actual read count.
283 *
284 * - If the RX FIFO has enough messages, this function reads the messages and returns.
285 * - If the RX FIFO does not have enough messages, this function the messages in RX FIFO
286 * and returns the actual read count.
287 * - During message reading, if RX FIFO is empty and locked, in this case peer CPU will not
288 * send message until current CPU send lock ack message. Then this function
289 * returns the message count actually received, and sets @p needAckLock to true
290 * to inform upper layer.
291 *
292 * @param link IMU link.
293 * @param msgs The buffer to read messages.
294 * @param desiredMsgCount Desired read count, one message is a 32-bit word.
295 * @param needAckLock Upper layer should always check this value. When this is
296 * set to true by this function, upper layer should send lock ack message to peer CPU.
297 * @return Count of messages actually received.
298 */
299 int32_t IMU_TryReceiveMsgs(imu_link_t link, uint32_t *msgs, int32_t desiredMsgCount, bool *needAckLock);
300
301 /*!
302 * @brief Blocking to receive messages.
303 *
304 * This function blocks until all desired messages have been received or the RX FIFO
305 * is locked.
306 *
307 * - If the RX FIFO has enough messages, this function reads the messages and returns.
308 * - If the RX FIFO does not have enough messages, this function waits for the new
309 * messages.
310 * - During message reading, if RX FIFO is empty and locked, in this case peer CPU will not
311 * send message until current CPU send lock ack message. Then this function
312 * returns the message count actually received, and sets @p needAckLock to true
313 * to inform upper layer.
314 *
315 * @param link IMU link.
316 * @param msgs The buffer to read messages.
317 * @param desiredMsgCount Desired read count, one message is a 32-bit word.
318 * @param needAckLock Upper layer should always check this value. When this is
319 * set to true by this function, upper layer should send lock ack message to peer CPU.
320 * @return Count of messages actually received.
321 */
322 int32_t IMU_ReceiveMsgsBlocking(imu_link_t link, uint32_t *msgs, int32_t desiredMsgCount, bool *needAckLock);
323
324 /*!
325 * @brief Blocking to send messages pointer.
326 *
327 * Compared with @ref IMU_SendMsgsBlocking, this function fills message pointer
328 * to TX FIFO, but not the message content.
329 *
330 * This function blocks until the message pointer is filled to TX FIFO.
331 *
332 * - If the TX FIFO is locked, this function returns IMU_ERR_TX_FIFO_LOCKED.
333 * - If TX FIFO not locked, this function waits the available empty slot in TX FIFO,
334 * and fills the message pointer to TX FIFO.
335 * - To lock TX FIFO after filling the message pointer, set @p lockSendFifo to true.
336 *
337 * @param link IMU link.
338 * @param msgPtr The buffer pointer to message to send.
339 * @param needAckLock Upper layer should always check this value. When this is
340 * set to true by this function, upper layer should send lock ack message to peer CPU.
341 * @retval 0 The message pointer set successfully.
342 * @retval IMU_ERR_TX_FIFO_LOCKED The TX FIFO is locked, send failed.
343 */
344 int32_t IMU_SendMsgPtrBlocking(imu_link_t link, uint32_t msgPtr, bool lockSendFifo);
345
346 /*!
347 * @brief Lock or unlock the TX FIFO.
348 *
349 * @param link IMU link.
350 * @param lock Use true to lock the FIFO, use false to unlock.
351 */
IMU_LockSendFifo(imu_link_t link,bool lock)352 static inline void IMU_LockSendFifo(imu_link_t link, bool lock)
353 {
354 if (lock)
355 {
356 ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK;
357 }
358 else
359 {
360 ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL &= ~IMU_MSG_FIFO_CNTL_WAIT_FOR_ACK_MASK;
361 }
362 }
363
364 /*!
365 * @brief Flush the send FIFO.
366 *
367 * Flush all messages in send FIFO.
368 *
369 * @param link IMU link.
370 */
371 void IMU_FlushSendFifo(imu_link_t link);
372
373 /*!
374 * @brief Set send FIFO warter mark.
375 *
376 * The warter mark must be less than IMU_MAX_MSG_FIFO_WATER_MARK,
377 * i.e. 0 < waterMark <= IMU_MAX_MSG_FIFO_WATER_MARK.
378 *
379 * @param link IMU link.
380 * @param waterMark Send FIFO warter mark.
381 */
IMU_SetSendFifoWaterMark(imu_link_t link,uint8_t waterMark)382 static inline void IMU_SetSendFifoWaterMark(imu_link_t link, uint8_t waterMark)
383 {
384 uint32_t reg = ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL;
385
386 reg &= ~IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK_MASK;
387 reg |= IMU_MSG_FIFO_CNTL_FIFO_FULL_WATERMARK(waterMark);
388
389 ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL = reg;
390 }
391
392 /*!
393 * @brief Get the message count in receive FIFO.
394 *
395 * @param link IMU link.
396 * @return The message count in receive FIFO.
397 */
IMU_GetReceivedMsgCount(imu_link_t link)398 static inline uint32_t IMU_GetReceivedMsgCount(imu_link_t link)
399 {
400 return IMU_RX_FIFO_MSG_COUNT(link);
401 }
402
403 /*!
404 * @brief Get the empty slot in send FIFO.
405 *
406 * @param link IMU link.
407 * @return The empty slot count in send FIFO.
408 */
IMU_GetSendFifoEmptySpace(imu_link_t link)409 static inline uint32_t IMU_GetSendFifoEmptySpace(imu_link_t link)
410 {
411 return IMU_MSG_FIFO_MAX_COUNT - IMU_TX_FIFO_MSG_COUNT(link) - 1U;
412 }
413
414 /*! @} */
415
416 /*!
417 * @name Status and Interrupt.
418 * @{
419 */
420
421 /*!
422 * @brief Gets the IMU status flags.
423 *
424 * @param link IMU link.
425 * @return Bit mask of the IMU status flags, see @ref _imu_status_flags.
426 */
427 uint32_t IMU_GetStatusFlags(imu_link_t link);
428
429 /*!
430 * @brief Clear the IMU IRQ
431 *
432 * @param link IMU link.
433 * @param mask Bit mask of the interrupts to clear, see @ref _imu_interrupts.
434 */
IMU_ClearPendingInterrupts(imu_link_t link,uint32_t mask)435 static inline void IMU_ClearPendingInterrupts(imu_link_t link, uint32_t mask)
436 {
437 ((IMU_Type *)(uintptr_t)IMU_CUR_CPU_BASE(link))->MSG_FIFO_CNTL |= mask;
438 }
439
440 /*! @} */
441
442 #if defined(__cplusplus)
443 }
444 #endif /*_cplusplus*/
445 /*! @} */
446
447 #endif /* FSL_IMU_H_*/
448