1 //*****************************************************************************
2 //
3 //! @file am_hal_ios.c
4 //!
5 //! @brief Functions for Interfacing with the IO Slave module
6 //!
7 //! @addtogroup ios3p IOS - IO Slave (SPI/I2C)
8 //! @ingroup apollo3p_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_1_1-10cda4b5e0 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51
52 #define AM_HAL_IOS_MAX_SW_FIFO_SIZE 1023
53 #define AM_HAL_MAGIC_IOS 0x123456
54 #define AM_HAL_IOS_CHK_HANDLE(h) ((h) && ((am_hal_handle_prefix_t *)(h))->s.bInit && (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_IOS))
55
56 //*****************************************************************************
57 //
58 //! SRAM Buffer structure
59 //
60 //*****************************************************************************
61 am_hal_ios_buffer_t g_sSRAMBuffer;
62
63 //*****************************************************************************
64 //
65 //! Private Types.
66 //
67 //*****************************************************************************
68 typedef struct
69 {
70 bool bValid;
71 uint32_t regFIFOCFG;
72 uint32_t regFIFOTHR;
73 uint32_t regCFG;
74 uint32_t regINTEN;
75 uint32_t regACCINTEN;
76 } am_hal_ios_register_state_t;
77
78 typedef struct
79 {
80 am_hal_handle_prefix_t prefix;
81 //
82 //! Physical module number.
83 //
84 uint32_t ui32Module;
85
86 am_hal_ios_register_state_t registerState;
87
88 uint8_t *pui8FIFOBase;
89 uint8_t *pui8FIFOEnd;
90 uint8_t *pui8FIFOPtr;
91 uint8_t ui32HwFifoSize;
92 uint32_t ui32FifoBaseOffset;
93 } am_hal_ios_state_t;
94
95 //*****************************************************************************
96 //
97 // Forward declarations of static funcitons.
98 //
99 //*****************************************************************************
100 static void am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer,
101 void *pvArray, uint32_t ui32Bytes);
102 static void fifo_write(void *pHandle, uint8_t *pui8Data, uint32_t ui32NumBytes);
103 static uint32_t am_hal_ios_fifo_ptr_set(void *pHandle, uint32_t ui32Offset);
104 //*****************************************************************************
105 //
106 // Function-like macros.
107 //
108 //*****************************************************************************
109 #define am_hal_ios_buffer_empty(psBuffer) \
110 ((psBuffer)->ui32Length == 0)
111
112 #define am_hal_ios_buffer_full(psBuffer) \
113 ((psBuffer)->ui32Length == (psBuffer)->ui32Capacity)
114
115 #define am_hal_ios_buffer_data_left(psBuffer) \
116 ((psBuffer)->ui32Length)
117
118 //*****************************************************************************
119 //
120 // Global Variables
121 //
122 //*****************************************************************************
123 volatile uint8_t * const am_hal_ios_pui8LRAM = (uint8_t *)REG_IOSLAVE_BASEADDR;
124
125 am_hal_ios_state_t g_IOShandles[AM_REG_IOSLAVE_NUM_MODULES];
126
127 //*****************************************************************************
128 //
129 // IOS power control function
130 //
131 //*****************************************************************************
am_hal_ios_power_ctrl(void * pHandle,am_hal_sysctrl_power_state_e ePowerState,bool bRetainState)132 uint32_t am_hal_ios_power_ctrl(void *pHandle,
133 am_hal_sysctrl_power_state_e ePowerState,
134 bool bRetainState)
135 {
136 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
137
138 #ifndef AM_HAL_DISABLE_API_VALIDATION
139 if ( !AM_HAL_IOS_CHK_HANDLE(pHandle) )
140 {
141 return AM_HAL_STATUS_INVALID_HANDLE;
142 }
143 #endif // AM_HAL_DISABLE_API_VALIDATION
144
145 //
146 // Decode the requested power state and update IOS operation accordingly.
147 //
148 switch (ePowerState)
149 {
150 case AM_HAL_SYSCTRL_WAKE:
151 if (bRetainState && !pIOSState->registerState.bValid)
152 {
153 return AM_HAL_STATUS_INVALID_OPERATION;
154 }
155
156 //
157 // Enable power control.
158 //
159 am_hal_pwrctrl_periph_enable((am_hal_pwrctrl_periph_e)(AM_HAL_PWRCTRL_PERIPH_IOS + pIOSState->ui32Module));
160
161 if (bRetainState)
162 {
163 //
164 // Restore IOS registers
165 IOSLAVEn(pIOSState->ui32Module)->FIFOCFG = pIOSState->registerState.regFIFOCFG;
166 IOSLAVEn(pIOSState->ui32Module)->FIFOTHR = pIOSState->registerState.regFIFOTHR;
167 IOSLAVEn(pIOSState->ui32Module)->CFG = pIOSState->registerState.regCFG;
168 IOSLAVEn(pIOSState->ui32Module)->INTEN = pIOSState->registerState.regINTEN;
169 IOSLAVEn(pIOSState->ui32Module)->REGACCINTEN = pIOSState->registerState.regACCINTEN;
170
171 pIOSState->registerState.bValid = false;
172 }
173 break;
174
175 case AM_HAL_SYSCTRL_NORMALSLEEP:
176 case AM_HAL_SYSCTRL_DEEPSLEEP:
177 if (bRetainState)
178 {
179 // Save IOS Registers
180 pIOSState->registerState.regFIFOCFG = IOSLAVEn(pIOSState->ui32Module)->FIFOCFG;
181 pIOSState->registerState.regFIFOTHR = IOSLAVEn(pIOSState->ui32Module)->FIFOTHR;
182 pIOSState->registerState.regCFG = IOSLAVEn(pIOSState->ui32Module)->CFG;
183 pIOSState->registerState.regINTEN = IOSLAVEn(pIOSState->ui32Module)->INTEN;
184 pIOSState->registerState.regACCINTEN = IOSLAVEn(pIOSState->ui32Module)->REGACCINTEN;
185 pIOSState->registerState.bValid = true;
186 }
187
188 //
189 // Disable power control.
190 //
191 am_hal_pwrctrl_periph_disable((am_hal_pwrctrl_periph_e)(AM_HAL_PWRCTRL_PERIPH_IOS + pIOSState->ui32Module));
192 break;
193
194 default:
195 return AM_HAL_STATUS_INVALID_ARG;
196 }
197
198 //
199 // Return the status.
200 //
201 return AM_HAL_STATUS_SUCCESS;
202 } // am_hal_ios_power_ctrl()
203
204 //*****************************************************************************
205 //
206 // IOS uninitialize function
207 //
208 //*****************************************************************************
am_hal_ios_uninitialize(void * pHandle)209 uint32_t am_hal_ios_uninitialize(void *pHandle)
210 {
211 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
212
213 #ifndef AM_HAL_DISABLE_API_VALIDATION
214 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
215 {
216 return AM_HAL_STATUS_INVALID_HANDLE;
217 }
218 #endif // AM_HAL_DISABLE_API_VALIDATION
219
220 if (pIOSState->prefix.s.bEnable)
221 {
222 am_hal_ios_disable(pHandle);
223 }
224
225 pIOSState->prefix.s.bInit = false;
226
227 return AM_HAL_STATUS_SUCCESS;
228 } // am_hal_ios_uninitialize()
229
230
231 //*****************************************************************************
232 //
233 // IOS initialization function
234 //
235 //*****************************************************************************
am_hal_ios_initialize(uint32_t ui32Module,void ** ppHandle)236 uint32_t am_hal_ios_initialize(uint32_t ui32Module, void **ppHandle)
237 {
238 #ifndef AM_HAL_DISABLE_API_VALIDATION
239 //
240 // Validate the module number
241 //
242 if ( ui32Module >= AM_REG_IOSLAVE_NUM_MODULES )
243 {
244 return AM_HAL_STATUS_OUT_OF_RANGE;
245 }
246
247 if (ppHandle == NULL)
248 {
249 return AM_HAL_STATUS_INVALID_ARG;
250 }
251
252 if (g_IOShandles[ui32Module].prefix.s.bInit)
253 {
254 return AM_HAL_STATUS_INVALID_OPERATION;
255 }
256 #endif // AM_HAL_DISABLE_API_VALIDATION
257
258 g_IOShandles[ui32Module].prefix.s.bInit = true;
259 g_IOShandles[ui32Module].prefix.s.bEnable = false;
260 g_IOShandles[ui32Module].prefix.s.magic = AM_HAL_MAGIC_IOS;
261
262 //
263 // Initialize the handle.
264 //
265 g_IOShandles[ui32Module].ui32Module = ui32Module;
266
267 //
268 // Return the handle.
269 //
270 *ppHandle = (void *)&g_IOShandles[ui32Module];
271
272 return AM_HAL_STATUS_SUCCESS;
273 } // am_hal_ios_initialize()
274
275 //*****************************************************************************
276 //
277 // IOS enable function
278 //
279 //*****************************************************************************
am_hal_ios_enable(void * pHandle)280 uint32_t am_hal_ios_enable(void *pHandle)
281 {
282 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
283 #ifndef AM_HAL_DISABLE_API_VALIDATION
284 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
285 {
286 return AM_HAL_STATUS_INVALID_HANDLE;
287 }
288
289 if (pIOSState->prefix.s.bEnable)
290 {
291 return AM_HAL_STATUS_SUCCESS;
292 }
293 #endif // AM_HAL_DISABLE_API_VALIDATION
294
295 IOSLAVEn(pIOSState->ui32Module)->CFG |= _VAL2FLD(IOSLAVE_CFG_IFCEN, 1);
296
297 pIOSState->prefix.s.bEnable = true;
298
299 return AM_HAL_STATUS_SUCCESS;
300 } // am_hal_ios_enable()
301
302 //*****************************************************************************
303 //
304 // IOS disable function
305 //
306 //*****************************************************************************
am_hal_ios_disable(void * pHandle)307 uint32_t am_hal_ios_disable(void *pHandle)
308 {
309 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
310
311 #ifndef AM_HAL_DISABLE_API_VALIDATION
312 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
313 {
314 return AM_HAL_STATUS_INVALID_HANDLE;
315 }
316 #endif // AM_HAL_DISABLE_API_VALIDATION
317
318 if (!pIOSState->prefix.s.bEnable)
319 {
320 return AM_HAL_STATUS_SUCCESS;
321 }
322
323 IOSLAVEn(pIOSState->ui32Module)->CFG &= ~(_VAL2FLD(IOSLAVE_CFG_IFCEN, 1));
324
325 pIOSState->prefix.s.bEnable = false;
326
327 return AM_HAL_STATUS_SUCCESS;
328
329 } // am_hal_ios_disable()
330
331 //*****************************************************************************
332 //
333 // IOS configuration function.
334 //
335 //*****************************************************************************
am_hal_ios_configure(void * pHandle,am_hal_ios_config_t * psConfig)336 uint32_t am_hal_ios_configure(void *pHandle, am_hal_ios_config_t *psConfig)
337 {
338 uint32_t ui32LRAMConfig = 0;
339 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
340 uint32_t ui32Module;
341
342 #ifndef AM_HAL_DISABLE_API_VALIDATION
343 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
344 {
345 return AM_HAL_STATUS_INVALID_HANDLE;
346 }
347
348 //
349 // Validate the parameters
350 //
351 if ( (psConfig == NULL) ||
352 (pIOSState->ui32Module >= AM_REG_IOSLAVE_NUM_MODULES) )
353 {
354 return AM_HAL_STATUS_INVALID_ARG;
355 }
356 // Configure not allowed in Enabled state
357 if (pIOSState->prefix.s.bEnable)
358 {
359 return AM_HAL_STATUS_INVALID_OPERATION;
360 }
361 #endif // AM_HAL_DISABLE_API_VALIDATION
362
363 ui32Module = pIOSState->ui32Module;
364
365 //
366 // Record the FIFO parameters for later use.
367 //
368 pIOSState->pui8FIFOBase = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32FIFOBase);
369 pIOSState->pui8FIFOEnd = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32RAMBase);
370 pIOSState->ui32HwFifoSize = pIOSState->pui8FIFOEnd - pIOSState->pui8FIFOBase;
371 pIOSState->ui32FifoBaseOffset = psConfig->ui32FIFOBase;
372
373 //
374 // Initialize the global SRAM buffer
375 // Total size, which is SRAM Buffer plus the hardware FIFO needs to be
376 // limited to 1023
377 //
378 if ( psConfig->ui32SRAMBufferCap > (AM_HAL_IOS_MAX_SW_FIFO_SIZE - pIOSState->ui32HwFifoSize + 1) )
379 {
380 psConfig->ui32SRAMBufferCap = (AM_HAL_IOS_MAX_SW_FIFO_SIZE - pIOSState->ui32HwFifoSize + 1);
381 }
382 am_hal_ios_buffer_init(&g_sSRAMBuffer, psConfig->pui8SRAMBuffer, psConfig->ui32SRAMBufferCap);
383
384 //
385 // Calculate the value for the IO Slave FIFO configuration register.
386 //
387 ui32LRAMConfig = _VAL2FLD(IOSLAVE_FIFOCFG_ROBASE, psConfig->ui32ROBase >> 3);
388 ui32LRAMConfig |= _VAL2FLD(IOSLAVE_FIFOCFG_FIFOBASE, psConfig->ui32FIFOBase >> 3);
389 ui32LRAMConfig |= _VAL2FLD(IOSLAVE_FIFOCFG_FIFOMAX, psConfig->ui32RAMBase >> 3);
390
391 //
392 // Just in case, disable the IOS
393 //
394 am_hal_ios_disable(pHandle);
395
396 //
397 // Write the configuration register with the user's selected interface
398 // characteristics.
399 //
400 IOSLAVEn(ui32Module)->CFG = psConfig->ui32InterfaceSelect;
401
402 //
403 // Write the FIFO configuration register to set the memory map for the LRAM.
404 //
405 IOSLAVEn(ui32Module)->FIFOCFG = ui32LRAMConfig;
406
407 //
408 // Clear the FIFO State
409 //
410 IOSLAVEn(pIOSState->ui32Module)->FIFOCTR_b.FIFOCTR = 0x0;
411 IOSLAVEn(pIOSState->ui32Module)->FIFOPTR_b.FIFOSIZ = 0x0;
412 am_hal_ios_fifo_ptr_set(pHandle, pIOSState->ui32FifoBaseOffset);
413
414 //
415 // Enable the IOS. The following configuration options can't be set while
416 // the IOS is disabled.
417 //
418 am_hal_ios_enable(pHandle);
419
420 //
421 // Initialize the FIFO pointer to the beginning of the FIFO section.
422 //
423 am_hal_ios_fifo_ptr_set(pHandle, psConfig->ui32FIFOBase);
424
425 //
426 // Write the FIFO threshold register.
427 //
428 IOSLAVEn(ui32Module)->FIFOTHR = psConfig->ui32FIFOThreshold;
429
430 return AM_HAL_STATUS_SUCCESS;
431 } // am_hal_ios_config()
432
433 //*****************************************************************************
434 //
435 // IOS enable interrupts function
436 //
437 //*****************************************************************************
am_hal_ios_interrupt_enable(void * pHandle,uint32_t ui32IntMask)438 uint32_t am_hal_ios_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
439 {
440 uint32_t ui32Module;
441
442 #ifndef AM_HAL_DISABLE_API_VALIDATION
443 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
444 {
445 return AM_HAL_STATUS_INVALID_HANDLE;
446 }
447 #endif // AM_HAL_DISABLE_API_VALIDATION
448
449 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
450
451 //
452 // OR the desired interrupt into the enable register.
453 //
454 IOSLAVEn(ui32Module)->INTEN |= ui32IntMask;
455
456 return AM_HAL_STATUS_SUCCESS;
457 } // am_hal_ios_int_enable()
458
459 //*****************************************************************************
460 //
461 // IOS disable interrupts function
462 //
463 //*****************************************************************************
am_hal_ios_interrupt_disable(void * pHandle,uint32_t ui32IntMask)464 uint32_t am_hal_ios_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
465 {
466 uint32_t ui32Module;
467
468 #ifndef AM_HAL_DISABLE_API_VALIDATION
469 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
470 {
471 return AM_HAL_STATUS_INVALID_HANDLE;
472 }
473 #endif // AM_HAL_DISABLE_API_VALIDATION
474
475 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
476
477 //
478 // Clear the desired bit from the interrupt enable register.
479 //
480 IOSLAVEn(ui32Module)->INTEN &= ~(ui32IntMask);
481
482 return AM_HAL_STATUS_SUCCESS;
483 } // am_hal_ios_int_disable()
484
485 //*****************************************************************************
486 //
487 // IOS interrupt clear
488 //
489 //*****************************************************************************
am_hal_ios_interrupt_clear(void * pHandle,uint32_t ui32IntMask)490 uint32_t am_hal_ios_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
491 {
492 uint32_t ui32Module;
493
494 #ifndef AM_HAL_DISABLE_API_VALIDATION
495 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
496 {
497 return AM_HAL_STATUS_INVALID_HANDLE;
498 }
499 #endif // AM_HAL_DISABLE_API_VALIDATION
500
501 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
502
503 //
504 // Use the interrupt clear register to deactivate the chosen interrupt.
505 //
506 IOSLAVEn(ui32Module)->INTCLR = ui32IntMask;
507
508 return AM_HAL_STATUS_SUCCESS;
509 } // am_hal_ios_int_clear()
510
511 //*****************************************************************************
512 //
513 // IOS get interrupt status
514 //
515 //*****************************************************************************
am_hal_ios_interrupt_status_get(void * pHandle,bool bEnabledOnly,uint32_t * pui32IntStatus)516 uint32_t am_hal_ios_interrupt_status_get(void *pHandle, bool bEnabledOnly,
517 uint32_t *pui32IntStatus)
518 {
519 uint32_t ui32IntStatus = 0;
520 uint32_t ui32Module;
521
522 #ifndef AM_HAL_DISABLE_API_VALIDATION
523 if ( !AM_HAL_IOS_CHK_HANDLE(pHandle) )
524 {
525 return AM_HAL_STATUS_INVALID_HANDLE;
526 }
527
528 if ( !pui32IntStatus )
529 {
530 return AM_HAL_STATUS_INVALID_ARG;
531 }
532 #endif // AM_HAL_DISABLE_API_VALIDATION
533
534 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
535
536 ui32IntStatus = IOSLAVEn(ui32Module)->INTSTAT;
537
538 if ( bEnabledOnly )
539 {
540 ui32IntStatus &= IOSLAVEn(ui32Module)->INTEN;
541 }
542
543 *pui32IntStatus = ui32IntStatus;
544
545 return AM_HAL_STATUS_SUCCESS;
546 } // am_hal_ios_int_status_get()
547
548 //*****************************************************************************
549 //
550 // @brief Check the amount of space used in the FIFO
551 //
552 // @param pHandle - IOS handle
553 // @param pui32UsedSpace is bytes used in the Overall FIFO.
554 //
555 // This function returns the available data in the overall FIFO yet to be
556 // read by the host. This takes into account the SRAM buffer and hardware FIFO
557 //
558 // @return success or error code
559 //
560 //*****************************************************************************
am_hal_ios_fifo_space_used(void * pHandle,uint32_t * pui32UsedSpace)561 uint32_t am_hal_ios_fifo_space_used(void *pHandle, uint32_t *pui32UsedSpace)
562 {
563 uint32_t ui32Module;
564 uint32_t ui32Val = 0;
565
566 #ifndef AM_HAL_DISABLE_API_VALIDATION
567 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
568 {
569 return AM_HAL_STATUS_INVALID_HANDLE;
570 }
571 if ( !pui32UsedSpace )
572 {
573 return AM_HAL_STATUS_INVALID_ARG;
574 }
575 #endif // AM_HAL_DISABLE_API_VALIDATION
576
577 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
578
579 //
580 // Start a critical section for thread safety.
581 //
582 AM_CRITICAL_BEGIN
583
584 ui32Val = g_sSRAMBuffer.ui32Length;
585 ui32Val += IOSLAVEn(ui32Module)->FIFOPTR_b.FIFOSIZ;
586
587 //
588 // End the critical section
589 //
590 AM_CRITICAL_END
591
592 *pui32UsedSpace = ui32Val;
593
594 return AM_HAL_STATUS_SUCCESS;
595 } // am_hal_ios_fifo_space_used()
596
597 //*****************************************************************************
598 //
599 // @brief Check the amount of space left in the FIFO
600 //
601 // @param pHandle - IOS handle
602 // @param pui32LeftSpace is bytes left in the Overall FIFO.
603 //
604 // This function returns the available space in the overall FIFO to accept
605 // new data. This takes into account the SRAM buffer and hardware FIFO
606 //
607 // @return success or error code
608 //
609 //*****************************************************************************
am_hal_ios_fifo_space_left(void * pHandle,uint32_t * pui32LeftSpace)610 uint32_t am_hal_ios_fifo_space_left(void *pHandle, uint32_t *pui32LeftSpace)
611 {
612 uint32_t ui32Module;
613 uint32_t ui32Val = 0;
614
615 #ifndef AM_HAL_DISABLE_API_VALIDATION
616 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
617 {
618 return AM_HAL_STATUS_INVALID_HANDLE;
619 }
620 if ( !pui32LeftSpace )
621 {
622 return AM_HAL_STATUS_INVALID_ARG;
623 }
624 #endif // AM_HAL_DISABLE_API_VALIDATION
625
626 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
627
628 //
629 // Start a critical section for thread safety.
630 //
631 AM_CRITICAL_BEGIN
632
633 //
634 // We waste one byte in HW FIFO
635 //
636 ui32Val = g_sSRAMBuffer.ui32Capacity + ((am_hal_ios_state_t*)pHandle)->ui32HwFifoSize - 1;
637 ui32Val -= g_sSRAMBuffer.ui32Length;
638 ui32Val -= IOSLAVEn(ui32Module)->FIFOPTR_b.FIFOSIZ;
639
640 //
641 // End the critical section
642 //
643 AM_CRITICAL_END
644
645 *pui32LeftSpace = ui32Val;
646
647 return AM_HAL_STATUS_SUCCESS;
648 } // am_hal_ios_fifo_space_left()
649
650 //*****************************************************************************
651 //
652 // @brief Check the amount of space left in the hardware FIFO
653 //
654 // @param pHandle - IOS handle
655 // @param pui32LeftSpace is bytes left in the IOS FIFO.
656 //
657 // This function reads the IOSLAVE FIFOPTR register and determines the amount
658 // of space left in the IOS LRAM FIFO.
659 //
660 // @return success or error code
661 //
662 //*****************************************************************************
fifo_space_left(void * pHandle,uint32_t * pui32LeftSpace)663 static uint32_t fifo_space_left(void *pHandle, uint32_t *pui32LeftSpace)
664 {
665 uint32_t ui32Module;
666
667 #ifndef AM_HAL_DISABLE_API_VALIDATION
668 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
669 {
670 return AM_HAL_STATUS_INVALID_HANDLE;
671 }
672 if ( !pui32LeftSpace )
673 {
674 return AM_HAL_STATUS_INVALID_ARG;
675 }
676 #endif // AM_HAL_DISABLE_API_VALIDATION
677
678 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
679
680 //
681 // We waste one byte in HW FIFO
682 //
683 *pui32LeftSpace = ((uint32_t)((am_hal_ios_state_t*)pHandle)->ui32HwFifoSize - IOSLAVEn(ui32Module)->FIFOPTR_b.FIFOSIZ - 1);
684
685 return AM_HAL_STATUS_SUCCESS;
686 } // fifo_space_left()
687
688 //*****************************************************************************
689 // @brief Helper function for managing IOS FIFO writes.
690 //
691 // @param pHandle
692 // @param pui8Data
693 // @param ui32NumBytes
694 //*****************************************************************************
fifo_write(void * pHandle,uint8_t * pui8Data,uint32_t ui32NumBytes)695 static void fifo_write(void *pHandle, uint8_t *pui8Data, uint32_t ui32NumBytes)
696 {
697 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
698 uint8_t *pFifoPtr = pIOSState->pui8FIFOPtr;
699 uint8_t *pFifoBase = pIOSState->pui8FIFOBase;
700 uint8_t *pFifoEnd = pIOSState->pui8FIFOEnd;
701
702 while ( ui32NumBytes )
703 {
704 //
705 // Write the data to the FIFO
706 //
707 *pFifoPtr++ = *pui8Data++;
708 ui32NumBytes--;
709
710 //
711 // Make sure to wrap the FIFO pointer if necessary.
712 //
713 if ( pFifoPtr == pFifoEnd )
714 {
715 pFifoPtr = pFifoBase;
716 }
717 }
718 pIOSState->pui8FIFOPtr = pFifoPtr;
719 } // fifo_write()
720
721 //*****************************************************************************
722 //
723 // IOS interrupt service routine
724 //
725 //*****************************************************************************
am_hal_ios_interrupt_service(void * pHandle,uint32_t ui32IntMask)726 uint32_t am_hal_ios_interrupt_service(void *pHandle, uint32_t ui32IntMask)
727 {
728 uint32_t thresh;
729 uint32_t freeSpace, usedSpace, chunk1, chunk2, ui32WriteIndex;
730 uint32_t ui32Module;
731
732 #ifndef AM_HAL_DISABLE_API_VALIDATION
733 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
734 {
735 return AM_HAL_STATUS_INVALID_HANDLE;
736 }
737 #endif // AM_HAL_DISABLE_API_VALIDATION
738
739 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
740
741 //
742 // Check for FIFO size interrupts.
743 //
744 if ( ui32IntMask & AM_HAL_IOS_INT_FSIZE )
745 {
746 thresh = IOSLAVEn(ui32Module)->FIFOTHR_b.FIFOTHR;
747
748 //
749 // While the FIFO is at or below threshold Add more data
750 // If Fifo level is above threshold, we're guaranteed an FSIZ interrupt
751 //
752 while ( g_sSRAMBuffer.ui32Length &&
753 ((usedSpace = IOSLAVEn(ui32Module)->FIFOPTR_b.FIFOSIZ) <= thresh) )
754 {
755 //
756 // So, we do have some data in SRAM which needs to be moved to FIFO.
757 // A chunk of data is a continguous set of bytes in SRAM that can be
758 // written to FIFO. Determine the chunks of data from SRAM that can
759 // be written. Up to two chunks possible
760 //
761 ui32WriteIndex = g_sSRAMBuffer.ui32WriteIndex;
762 chunk1 = ((ui32WriteIndex > (uint32_t)g_sSRAMBuffer.ui32ReadIndex) ? \
763 (ui32WriteIndex - (uint32_t)g_sSRAMBuffer.ui32ReadIndex) : \
764 (g_sSRAMBuffer.ui32Capacity - (uint32_t)g_sSRAMBuffer.ui32ReadIndex));
765 chunk2 = g_sSRAMBuffer.ui32Length - chunk1;
766 // We waste one byte in HW FIFO
767 freeSpace = ((am_hal_ios_state_t*)pHandle)->ui32HwFifoSize - usedSpace - 1;
768 // Write data in chunks
769 // Determine the chunks of data from SRAM that can be written
770 if ( chunk1 > freeSpace )
771 {
772 fifo_write(pHandle, (uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
773 //
774 // Advance the read index, wrapping if needed.
775 //
776 g_sSRAMBuffer.ui32ReadIndex += freeSpace;
777 // No need to check for wrap as we wrote less than chunk1
778 //
779 // Adjust the length value to reflect the change.
780 //
781 g_sSRAMBuffer.ui32Length -= freeSpace;
782 }
783 else
784 {
785 fifo_write(pHandle, (uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk1);
786
787 //
788 // Update the read index - wrapping as needed
789 //
790 g_sSRAMBuffer.ui32ReadIndex += chunk1;
791 g_sSRAMBuffer.ui32ReadIndex %= g_sSRAMBuffer.ui32Capacity;
792 //
793 // Adjust the length value to reflect the change.
794 //
795 g_sSRAMBuffer.ui32Length -= chunk1;
796 freeSpace -= chunk1;
797
798 if ( freeSpace && chunk2 )
799 {
800 if ( chunk2 > freeSpace )
801 {
802 fifo_write(pHandle, (uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
803
804 //
805 // Advance the read index, wrapping if needed.
806 //
807 g_sSRAMBuffer.ui32ReadIndex += freeSpace;
808
809 // No need to check for wrap in chunk2
810 //
811 // Adjust the length value to reflect the change.
812 //
813 g_sSRAMBuffer.ui32Length -= freeSpace;
814 }
815 else
816 {
817 fifo_write(pHandle, (uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk2);
818 //
819 // Advance the read index, wrapping if needed.
820 //
821 g_sSRAMBuffer.ui32ReadIndex += chunk2;
822
823 // No need to check for wrap in chunk2
824 //
825 // Adjust the length value to reflect the change.
826 //
827 g_sSRAMBuffer.ui32Length -= chunk2;
828 }
829 }
830 }
831
832 //
833 // Need to retake the FIFO space, after Threshold interrupt has been reenabled
834 // Clear any spurious FSIZE interrupt that might have got raised
835 //
836 IOSLAVEn(ui32Module)->INTCLR_b.FSIZE = 1;
837 }
838 }
839
840 return AM_HAL_STATUS_SUCCESS;
841 } // am_hal_ios_fifo_service()
842
843 //*****************************************************************************
844 //
845 // @brief Writes the specified number of bytes to the IOS fifo.
846 //
847 // @param pHandle - IOS handle
848 // @param pui8Data - pointer to the data to be written to the fifo.
849 // @param ui32NumBytes - the number of bytes to send.
850 // @param pui32WrittenBytes -number of bytes written (could be less than ui32NumBytes, if not enough space)
851 //
852 // This function will write data from the caller-provided array to the IOS
853 // LRAM FIFO. If there is no space in the LRAM FIFO, the data will be copied
854 // to a temporary SRAM buffer instead.
855 //
856 // The maximum message size for the IO Slave is 1023 bytes.
857 //
858 // @note In order for SRAM copy operations in the function to work correctly,
859 // the \e am_hal_ios_buffer_service() function must be called in the ISR for
860 // the ioslave module.
861 //
862 // @return success or error code
863 //
864 //*****************************************************************************
am_hal_ios_fifo_write(void * pHandle,uint8_t * pui8Data,uint32_t ui32NumBytes,uint32_t * pui32WrittenBytes)865 uint32_t am_hal_ios_fifo_write(void *pHandle, uint8_t *pui8Data, uint32_t ui32NumBytes, uint32_t *pui32WrittenBytes)
866 {
867 uint32_t ui32FIFOSpace = 0;
868 uint32_t ui32SRAMSpace;
869 uint32_t ui32SRAMLength;
870 uint32_t totalBytes = ui32NumBytes;
871 uint32_t ui32Module;
872
873 #ifndef AM_HAL_DISABLE_API_VALIDATION
874 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
875 {
876 return AM_HAL_STATUS_INVALID_HANDLE;
877 }
878 if ( !pui8Data || !pui32WrittenBytes)
879 {
880 return AM_HAL_STATUS_INVALID_ARG;
881 }
882 #endif // AM_HAL_DISABLE_API_VALIDATION
883
884 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
885
886 //
887 // This operation will only work properly if an SRAM buffer has been
888 // allocated. Make sure that am_hal_ios_fifo_buffer_init() has been called,
889 // and the buffer pointer looks valid.
890 //
891 am_hal_debug_assert(g_sSRAMBuffer.pui8Data != 0);
892
893 if ( ui32NumBytes == 0 )
894 {
895 *pui32WrittenBytes = 0;
896 }
897 else
898 {
899 //
900 // Start a critical section for thread safety.
901 //
902 AM_CRITICAL_BEGIN
903
904 ui32SRAMLength = g_sSRAMBuffer.ui32Length;
905
906 //
907 // End the critical section
908 //
909 AM_CRITICAL_END
910
911 //
912 // If the SRAM buffer is empty, we should just write directly to the FIFO.
913 //
914 if ( ui32SRAMLength == 0 )
915 {
916 fifo_space_left(pHandle, &ui32FIFOSpace);
917
918 //
919 // If the whole message fits, send it now.
920 //
921 if ( ui32NumBytes <= ui32FIFOSpace )
922 {
923 fifo_write(pHandle, pui8Data, ui32NumBytes);
924 ui32NumBytes = 0;
925 }
926 else
927 {
928 fifo_write(pHandle, pui8Data, ui32FIFOSpace);
929 ui32NumBytes -= ui32FIFOSpace;
930 pui8Data += ui32FIFOSpace;
931 }
932 }
933
934 //
935 // If there's still data, write it to the SRAM buffer.
936 //
937 if ( ui32NumBytes )
938 {
939 uint32_t idx, writeIdx, capacity, fifoSize;
940 ui32SRAMSpace = g_sSRAMBuffer.ui32Capacity - ui32SRAMLength;
941
942 writeIdx = g_sSRAMBuffer.ui32WriteIndex;
943 capacity = g_sSRAMBuffer.ui32Capacity;
944
945 //
946 // Make sure that the data will fit inside the SRAM buffer.
947 //
948 if ( ui32SRAMSpace > ui32NumBytes )
949 {
950 ui32SRAMSpace = ui32NumBytes;
951 }
952
953 //
954 // If the data will fit, write it to the SRAM buffer.
955 //
956 for ( idx = 0; idx < ui32SRAMSpace; idx++ )
957 {
958 g_sSRAMBuffer.pui8Data[(idx + writeIdx) % capacity] = pui8Data[idx];
959 }
960
961 ui32NumBytes -= idx;
962
963 //
964 // Start a critical section for thread safety before updating length & wrIdx.
965 //
966 AM_CRITICAL_BEGIN
967
968 //
969 // Advance the write index, making sure to wrap if necessary.
970 //
971 g_sSRAMBuffer.ui32WriteIndex = (idx + writeIdx) % capacity;
972
973 //
974 // Update the length value appropriately.
975 //
976 g_sSRAMBuffer.ui32Length += idx;
977
978 //
979 // End the critical section
980 //
981 AM_CRITICAL_END
982
983 // It is possible that there is a race condition that the FIFO level has
984 // gone below the threshold by the time we set the wrIdx above, and hence
985 // we may never get the threshold interrupt to serve the SRAM data we
986 // just wrote
987
988 // If that is the case, explicitly generate the FSIZE interrupt from here
989 fifoSize = IOSLAVEn(ui32Module)->FIFOPTR_b.FIFOSIZ;
990
991 if ( fifoSize <= IOSLAVEn(ui32Module)->FIFOTHR_b.FIFOTHR )
992 {
993 IOSLAVEn(ui32Module)->INTSET_b.FSIZE = 1;
994 }
995 }
996
997 *pui32WrittenBytes = totalBytes - ui32NumBytes;
998 }
999
1000 return AM_HAL_STATUS_SUCCESS;
1001 } // am_hal_ios_fifo_write()
1002
1003 //*****************************************************************************
1004 //
1005 // @brief Sets the IOS FIFO pointer to the specified LRAM offset.
1006 //
1007 // @param pHandle - IOS handle
1008 // @param ui32Offset - LRAM offset to set the FIFO pointer to.
1009 //
1010 // @return success or error code
1011 //
1012 //*****************************************************************************
am_hal_ios_fifo_ptr_set(void * pHandle,uint32_t ui32Offset)1013 static uint32_t am_hal_ios_fifo_ptr_set(void *pHandle, uint32_t ui32Offset)
1014 {
1015 uint32_t ui32Module;
1016
1017 #ifndef AM_HAL_DISABLE_API_VALIDATION
1018 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
1019 {
1020 return AM_HAL_STATUS_INVALID_HANDLE;
1021 }
1022 #endif // AM_HAL_DISABLE_API_VALIDATION
1023
1024 ui32Module = ((am_hal_ios_state_t*)pHandle)->ui32Module;
1025
1026 //
1027 // Start a critical section for thread safety.
1028 //
1029 AM_CRITICAL_BEGIN
1030
1031 //
1032 // Set the FIFO Update bit.
1033 //
1034 IOSLAVEn(ui32Module)->FUPD = 0x1;
1035
1036 //
1037 // Change the FIFO offset.
1038 //
1039 IOSLAVEn(ui32Module)->FIFOPTR = ui32Offset;
1040
1041 //
1042 // Clear the FIFO update bit.
1043 //
1044 IOSLAVEn(ui32Module)->FUPD = 0x0;
1045
1046 //
1047 // Set the global FIFO-pointer tracking variable.
1048 //
1049 ((am_hal_ios_state_t*)pHandle)->pui8FIFOPtr = (uint8_t *) (REG_IOSLAVE_BASEADDR + ui32Offset);
1050
1051 //
1052 // End the critical section.
1053 //
1054 AM_CRITICAL_END
1055
1056 return AM_HAL_STATUS_SUCCESS;
1057 } // am_hal_ios_fifo_ptr_set()
1058
1059 //*****************************************************************************
1060 //
1061 // @brief Initialize an SRAM buffer for use with the IO Slave.
1062 //
1063 // @param psBuffer
1064 // @param pvArray
1065 // @param ui32Bytes
1066 //
1067 //*****************************************************************************
am_hal_ios_buffer_init(am_hal_ios_buffer_t * psBuffer,void * pvArray,uint32_t ui32Bytes)1068 static void am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer, void *pvArray,
1069 uint32_t ui32Bytes)
1070 {
1071 psBuffer->ui32WriteIndex = 0;
1072 psBuffer->ui32ReadIndex = 0;
1073 psBuffer->ui32Length = 0;
1074 psBuffer->ui32Capacity = ui32Bytes;
1075 psBuffer->pui8Data = (uint8_t *)pvArray;
1076 } // am_hal_ios_buffer_init()
1077
1078 //*****************************************************************************
1079 //
1080 // @brief IOS control function
1081 //
1082 // @param pHandle - handle for the IOS.
1083 // @param eReq - device specific special request code.
1084 // @param pArgs - pointer to the request specific arguments.
1085 //
1086 // This function allows advanced settings
1087 //
1088 // @return success or error code
1089 //
1090 //*****************************************************************************
am_hal_ios_control(void * pHandle,am_hal_ios_request_e eReq,void * pArgs)1091 uint32_t am_hal_ios_control(void *pHandle, am_hal_ios_request_e eReq, void *pArgs)
1092 {
1093 am_hal_ios_state_t *pIOSState = (am_hal_ios_state_t*)pHandle;
1094 uint32_t ui32Val = 0;
1095
1096 #ifndef AM_HAL_DISABLE_API_VALIDATION
1097 if (!AM_HAL_IOS_CHK_HANDLE(pHandle))
1098 {
1099 return AM_HAL_STATUS_INVALID_HANDLE;
1100 }
1101
1102 //
1103 // Validate the parameters
1104 //
1105 if ((eReq < AM_HAL_IOS_REQ_ARG_MAX) && (NULL == pArgs))
1106 {
1107 return AM_HAL_STATUS_INVALID_ARG;
1108 }
1109 #endif // AM_HAL_DISABLE_API_VALIDATION
1110
1111 switch (eReq)
1112 {
1113 case AM_HAL_IOS_REQ_HOST_INTSET:
1114 IOSLAVEn(pIOSState->ui32Module)->IOINTCTL = _VAL2FLD(IOSLAVE_IOINTCTL_IOINTSET, *((uint32_t *)pArgs));
1115 break;
1116 case AM_HAL_IOS_REQ_HOST_INTCLR:
1117 IOSLAVEn(pIOSState->ui32Module)->IOINTCTL = _VAL2FLD(IOSLAVE_IOINTCTL_IOINTCLR, *((uint32_t *)pArgs));
1118 break;
1119 case AM_HAL_IOS_REQ_HOST_INTGET:
1120 *((uint32_t*)pArgs) = IOSLAVEn(pIOSState->ui32Module)->IOINTCTL_b.IOINT;
1121 break;
1122 case AM_HAL_IOS_REQ_HOST_INTEN_GET:
1123 *((uint32_t*)pArgs) = IOSLAVEn(pIOSState->ui32Module)->IOINTCTL_b.IOINTEN;
1124 break;
1125 case AM_HAL_IOS_REQ_READ_GADATA:
1126 *((uint32_t*)pArgs) = IOSLAVEn(pIOSState->ui32Module)->GENADD_b.GADATA;
1127 break;
1128 case AM_HAL_IOS_REQ_READ_POLL:
1129 while ( IOSLAVEn(pIOSState->ui32Module)->FUPD & IOSLAVE_FUPD_IOREAD_Msk );
1130 break;
1131 case AM_HAL_IOS_REQ_FIFO_UPDATE_CTR:
1132 am_hal_ios_fifo_space_used(pHandle, &ui32Val);
1133 IOSLAVEn(pIOSState->ui32Module)->FIFOCTR_b.FIFOCTR = ui32Val;
1134 break;
1135 case AM_HAL_IOS_REQ_FIFO_BUF_CLR:
1136 am_hal_ios_buffer_init(&g_sSRAMBuffer, NULL, 0);
1137 //
1138 // Clear the FIFO State
1139 //
1140 IOSLAVEn(pIOSState->ui32Module)->FIFOCTR_b.FIFOCTR = 0x0;
1141 IOSLAVEn(pIOSState->ui32Module)->FIFOPTR_b.FIFOSIZ = 0x0;
1142 break;
1143 case AM_HAL_IOS_REQ_MAX:
1144 return AM_HAL_STATUS_INVALID_ARG;
1145 }
1146
1147 return AM_HAL_STATUS_SUCCESS;
1148 }
1149
1150 //*****************************************************************************
1151 //
1152 // End the doxygen group
1153 //! @}
1154 //
1155 //*****************************************************************************
1156