1 //*****************************************************************************
2 //
3 //  am_hal_ios.c
4 //! @file
5 //!
6 //! @brief Functions for interfacing with the IO Slave module
7 //!
8 //! @addtogroup ios2 IO Slave (SPI/I2C)
9 //! @ingroup apollo2hal
10 //! @{
11 //
12 //*****************************************************************************
13 
14 //*****************************************************************************
15 //
16 // Copyright (c) 2017, Ambiq Micro
17 // All rights reserved.
18 //
19 // Redistribution and use in source and binary forms, with or without
20 // modification, are permitted provided that the following conditions are met:
21 //
22 // 1. Redistributions of source code must retain the above copyright notice,
23 // this list of conditions and the following disclaimer.
24 //
25 // 2. Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // 3. Neither the name of the copyright holder nor the names of its
30 // contributors may be used to endorse or promote products derived from this
31 // software without specific prior written permission.
32 //
33 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
37 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 // POSSIBILITY OF SUCH DAMAGE.
44 //
45 // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
46 //
47 //*****************************************************************************
48 
49 #include <stdint.h>
50 #include <stdbool.h>
51 #include "am_mcu_apollo.h"
52 
53 //*****************************************************************************
54 //
55 // SRAM Buffer structure
56 //
57 //*****************************************************************************
58 typedef struct
59 {
60     uint8_t           *pui8Data;
61     volatile uint32_t ui32WriteIndex;
62     volatile uint32_t ui32ReadIndex;
63     volatile uint32_t ui32Length;
64     uint32_t          ui32FifoInc;
65     uint32_t          ui32Capacity;
66 }
67 am_hal_ios_buffer_t;
68 
69 am_hal_ios_buffer_t g_sSRAMBuffer;
70 
71 //*****************************************************************************
72 //
73 // Forward declarations of static funcitons.
74 //
75 //*****************************************************************************
76 static void am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer,
77                                    void *pvArray, uint32_t ui32Bytes);
78 
79 static void fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes);
80 
81 //*****************************************************************************
82 //
83 // Function-like macros.
84 //
85 //*****************************************************************************
86 #define am_hal_ios_buffer_empty(psBuffer)                                   \
87     ((psBuffer)->ui32Length == 0)
88 
89 #define am_hal_ios_buffer_full(psBuffer)                                    \
90     ((psBuffer)->ui32Length == (psBuffer)->ui32Capacity)
91 
92 #define am_hal_ios_buffer_data_left(psBuffer)                               \
93     ((psBuffer)->ui32Length)
94 
95 //*****************************************************************************
96 //
97 // Global Variables
98 //
99 //*****************************************************************************
100 volatile uint8_t * const am_hal_ios_pui8LRAM = (uint8_t *)REG_IOSLAVE_BASEADDR;
101 uint8_t *g_pui8FIFOBase = (uint8_t *) REG_IOSLAVE_BASEADDR;
102 uint8_t *g_pui8FIFOEnd = (uint8_t *) REG_IOSLAVE_BASEADDR;
103 uint8_t *g_pui8FIFOPtr = (uint8_t *) REG_IOSLAVE_BASEADDR;
104 uint8_t g_ui32HwFifoSize = 0;
105 uint32_t g_ui32FifoBaseOffset = 0;
106 
107 //*****************************************************************************
108 //
109 // Checks to see if this processor is a Rev B2 device.
110 //
111 // This is needed to disable SHELBY-1654 workaround.
112 //
113 //*****************************************************************************
114 bool
isRevB2(void)115 isRevB2(void)
116 {
117     //
118     // Check to make sure the major rev is B and the minor rev is 2.
119     //
120     return ( (AM_REG(MCUCTRL, CHIPREV) & 0xFF) ==   \
121         (AM_REG_MCUCTRL_CHIPREV_REVMAJ_B | (AM_REG_MCUCTRL_CHIPREV_REVMIN_REV0 + 2)) );
122 }
123 
124 //*****************************************************************************
125 //
126 //! @brief Enable the IOS in the power control block.
127 //!
128 //! This function enables the IOS module in the power control block.
129 //!
130 //! @return None.
131 //
132 //*****************************************************************************
133 void
am_hal_ios_pwrctrl_enable(void)134 am_hal_ios_pwrctrl_enable(void)
135 {
136     am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
137 }
138 
139 //*****************************************************************************
140 //
141 //! @brief Disable the IOS in the power control block.
142 //!
143 //! This function disables the IOS module in the power control block.
144 //!
145 //! @return None.
146 //
147 //*****************************************************************************
148 void
am_hal_ios_pwrctrl_disable(void)149 am_hal_ios_pwrctrl_disable(void)
150 {
151     am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_IOS);
152 }
153 
154 //*****************************************************************************
155 //
156 //! @brief Enables the IOS module
157 //!
158 //! This function enables the IOSLAVE module using the IFCEN bitfield in the
159 //! IOSLAVE_CFG register.
160 //!
161 //! @return None.
162 //
163 //*****************************************************************************
164 void
am_hal_ios_enable(uint32_t ui32Module)165 am_hal_ios_enable(uint32_t ui32Module)
166 {
167     AM_REGn(IOSLAVE, ui32Module, CFG) |= AM_REG_IOSLAVE_CFG_IFCEN(1);
168 }
169 
170 //*****************************************************************************
171 //
172 //! @brief Disables the IOSLAVE module.
173 //!
174 //! This function disables the IOSLAVE module using the IFCEN bitfield in the
175 //! IOSLAVE_CFG register.
176 //!
177 //! @return None.
178 //
179 //*****************************************************************************
180 void
am_hal_ios_disable(uint32_t ui32Module)181 am_hal_ios_disable(uint32_t ui32Module)
182 {
183     AM_REGn(IOSLAVE, ui32Module, CFG) &= ~(AM_REG_IOSLAVE_CFG_IFCEN(1));
184 }
185 
186 //*****************************************************************************
187 //
188 //! @brief Configure the IOS module.
189 //!
190 //! This function reads the an \e am_hal_ios_config_t structure and uses it to
191 //! set up the IO Slave module. Please see the information on the configuration
192 //! structure for more information on the parameters that may be set by this
193 //! function.
194 //!
195 //! @return None.
196 //
197 //*****************************************************************************
198 void
am_hal_ios_config(am_hal_ios_config_t * psConfig)199 am_hal_ios_config(am_hal_ios_config_t *psConfig)
200 {
201     uint32_t ui32LRAMConfig;
202 
203     am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
204 
205     //
206     // Record the FIFO parameters for later use.
207     //
208     g_pui8FIFOBase = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32FIFOBase);
209     g_pui8FIFOEnd = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32RAMBase);
210     g_ui32HwFifoSize = g_pui8FIFOEnd - g_pui8FIFOBase;
211     g_ui32FifoBaseOffset = psConfig->ui32FIFOBase;
212 
213     //
214     // Caluclate the value for the IO Slave FIFO configuration register.
215     //
216     ui32LRAMConfig = AM_REG_IOSLAVE_FIFOCFG_ROBASE(psConfig->ui32ROBase >> 3);
217     ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOBASE(psConfig->ui32FIFOBase >> 3);
218     ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOMAX(psConfig->ui32RAMBase >> 3);
219 
220     //
221     // Just in case, disable the IOS
222     //
223     am_hal_ios_disable(0);
224 
225     //
226     // Write the configuration register with the user's selected interface
227     // characteristics.
228     //
229     AM_REG(IOSLAVE, CFG) = psConfig->ui32InterfaceSelect;
230 
231     //
232     // Write the FIFO configuration register to set the memory map for the LRAM.
233     //
234     AM_REG(IOSLAVE, FIFOCFG) = ui32LRAMConfig;
235 
236     //
237     // Enable the IOS. The following configuration options can't be set while
238     // the IOS is disabled.
239     //
240     am_hal_ios_enable(0);
241 
242     //
243     // Initialize the FIFO pointer to the beginning of the FIFO section.
244     //
245     am_hal_ios_fifo_ptr_set(psConfig->ui32FIFOBase);
246 
247     //
248     // Write the FIFO threshold register.
249     //
250     AM_REG(IOSLAVE, FIFOTHR) = psConfig->ui32FIFOThreshold;
251 }
252 
253 //*****************************************************************************
254 //
255 //! @brief Set bits in the HOST side IOINTCTL register.
256 //!
257 //! This function may be used to set an interrupt bit to the host.
258 //!
259 //! @return None.
260 //
261 //*****************************************************************************
262 void
am_hal_ios_host_int_set(uint32_t ui32Interrupt)263 am_hal_ios_host_int_set(uint32_t ui32Interrupt)
264 {
265     //
266     // Set a bit that will cause an interrupt to the host.
267     //
268     AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTSET(ui32Interrupt);
269 }
270 
271 //*****************************************************************************
272 //
273 //! @brief Clear bits in the HOST side IOINTCTL register.
274 //!
275 //! This function may be used to clear an interrupt bit to the host.
276 //!
277 //! @return None.
278 //
279 //*****************************************************************************
280 void
am_hal_ios_host_int_clear(uint32_t ui32Interrupt)281 am_hal_ios_host_int_clear(uint32_t ui32Interrupt)
282 {
283     //
284     // Clear bits that will cause an interrupt to the host.
285     //
286     AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTCLR(ui32Interrupt);
287 }
288 
289 //*****************************************************************************
290 //
291 //! @brief Get the bits in the HOST side IOINTCTL register.
292 //!
293 //! This function may be used to read the host side interrupt bits.
294 //!
295 //! @return None.
296 //
297 //*****************************************************************************
298 uint32_t
am_hal_ios_host_int_get(void)299 am_hal_ios_host_int_get(void)
300 {
301     //
302     // return the value of the bits that will cause an interrupt to the host.
303     //
304     return AM_BFR(IOSLAVE, IOINTCTL, IOINT);
305 }
306 
307 //*****************************************************************************
308 //
309 //! @brief Get the enable bits in the HOST side IOINTCTL register.
310 //!
311 //! This function may be used to read the host side interrupt bits.
312 //!
313 //! @return None.
314 //
315 //*****************************************************************************
316 uint32_t
am_hal_ios_host_int_enable_get(void)317 am_hal_ios_host_int_enable_get(void)
318 {
319     //
320     // return the value of the bits that will cause an interrupt to the host.
321     //
322     return AM_BFR(IOSLAVE, IOINTCTL, IOINTEN);
323 }
324 
325 //*****************************************************************************
326 //
327 //! @brief Enable an IOS Access Interrupt.
328 //!
329 //! This function may be used to enable an interrupt to the NVIC.
330 //!
331 //! @return None.
332 //
333 //*****************************************************************************
334 void
am_hal_ios_access_int_enable(uint32_t ui32Interrupt)335 am_hal_ios_access_int_enable(uint32_t ui32Interrupt)
336 {
337     //
338     // OR the desired interrupt into the enable register.
339     //
340     AM_REG(IOSLAVE, REGACCINTEN) |= ui32Interrupt;
341 }
342 
343 //*****************************************************************************
344 //
345 //! @brief Return all enabled IOS Access Interrupts.
346 //!
347 //! This function may be used to return all enabled IOS Access interrupts.
348 //!
349 //! @return the enabled interrrupts.
350 //
351 //*****************************************************************************
352 uint32_t
am_hal_ios_access_int_enable_get(void)353 am_hal_ios_access_int_enable_get(void)
354 {
355     //
356     // Return the enabled interrupts.
357     //
358     return AM_REG(IOSLAVE, REGACCINTEN);
359 }
360 
361 //*****************************************************************************
362 //
363 //! @brief Disable an IOS Access Interrupt.
364 //!
365 //! This function may be used to disable an interrupt to the NVIC.
366 //!
367 //! @return None.
368 //
369 //*****************************************************************************
370 void
am_hal_ios_access_int_disable(uint32_t ui32Interrupt)371 am_hal_ios_access_int_disable(uint32_t ui32Interrupt)
372 {
373     //
374     // Clear the desired bit from the interrupt enable register.
375     //
376     AM_REG(IOSLAVE, REGACCINTEN) &= ~(ui32Interrupt);
377 }
378 
379 //*****************************************************************************
380 //
381 //! @brief Clear an IOS Access Interrupt.
382 //!
383 //! This function may be used to clear an interrupt to the NVIC.
384 //!
385 //! @return None.
386 //
387 //*****************************************************************************
388 void
am_hal_ios_access_int_clear(uint32_t ui32Interrupt)389 am_hal_ios_access_int_clear(uint32_t ui32Interrupt)
390 {
391     //
392     // Use the interrupt clear register to deactivate the chosen interrupt.
393     //
394     AM_REG(IOSLAVE, REGACCINTCLR) = ui32Interrupt;
395 }
396 
397 //*****************************************************************************
398 //
399 //! @brief Set an IOS Access Interrupt.
400 //!
401 //! This function may be used to set an interrupt to the NVIC.
402 //!
403 //! @return None.
404 //
405 //*****************************************************************************
406 void
am_hal_ios_access_int_set(uint32_t ui32Interrupt)407 am_hal_ios_access_int_set(uint32_t ui32Interrupt)
408 {
409     //
410     // Use the interrupt set register to activate the chosen interrupt.
411     //
412     AM_REG(IOSLAVE, REGACCINTSET) = ui32Interrupt;
413 }
414 
415 //*****************************************************************************
416 //
417 //! @brief Check the status of an IOS Access Interrupt.
418 //!
419 //! @param bEnabledOnly - return only the enabled interrupt status.
420 //!
421 //! This function may be used to return the enabled interrupt status.
422 //!
423 //! @return the enabled interrupt status.
424 //
425 //*****************************************************************************
426 uint32_t
am_hal_ios_access_int_status_get(bool bEnabledOnly)427 am_hal_ios_access_int_status_get(bool bEnabledOnly)
428 {
429     if ( bEnabledOnly )
430     {
431         uint32_t u32RetVal = AM_REG(IOSLAVE, REGACCINTSTAT);
432         return u32RetVal & AM_REG(IOSLAVE, REGACCINTEN);
433 
434     }
435     else
436     {
437         return AM_REG(IOSLAVE, REGACCINTSTAT);
438     }
439 }
440 
441 //*****************************************************************************
442 //
443 //! @brief Enable an IOS Interrupt.
444 //!
445 //! @param ui32Interrupt - desired interrupts.
446 //!
447 //! This function may be used to enable an interrupt to the NVIC.
448 //!
449 //! @return None.
450 //
451 //*****************************************************************************
452 void
am_hal_ios_int_enable(uint32_t ui32Interrupt)453 am_hal_ios_int_enable(uint32_t ui32Interrupt)
454 {
455     //
456     // OR the desired interrupt into the enable register.
457     //
458     AM_REG(IOSLAVE, INTEN) |= ui32Interrupt;
459 }
460 
461 //*****************************************************************************
462 //
463 //! @brief Return all enabled IOS Interrupts.
464 //!
465 //! This function may be used to return all enabled IOS interrupts.
466 //!
467 //! @return the enabled interrrupts.
468 //
469 //*****************************************************************************
470 uint32_t
am_hal_ios_int_enable_get(void)471 am_hal_ios_int_enable_get(void)
472 {
473     //
474     // Return the enabled interrupts.
475     //
476     return AM_REG(IOSLAVE, INTEN);
477 }
478 
479 //*****************************************************************************
480 //
481 //! @brief Disable an IOS Interrupt.
482 //!
483 //! @param ui32Interrupt - desired interrupts.
484 //!
485 //! This function may be used to disable an interrupt to the NVIC.
486 //!
487 //! @return None.
488 //
489 //*****************************************************************************
490 void
am_hal_ios_int_disable(uint32_t ui32Interrupt)491 am_hal_ios_int_disable(uint32_t ui32Interrupt)
492 {
493     //
494     // Clear the desired bit from the interrupt enable register.
495     //
496     AM_REG(IOSLAVE, INTEN) &= ~(ui32Interrupt);
497 }
498 
499 //*****************************************************************************
500 //
501 //! @brief Clear an IOS Interrupt.
502 //!
503 //! @param ui32Interrupt - desired interrupts.
504 //!
505 //! This function may be used to clear an interrupt to the NVIC.
506 //!
507 //! @return None.
508 //
509 //*****************************************************************************
510 void
am_hal_ios_int_clear(uint32_t ui32Interrupt)511 am_hal_ios_int_clear(uint32_t ui32Interrupt)
512 {
513     //
514     // Use the interrupt clear register to deactivate the chosen interrupt.
515     //
516     AM_REG(IOSLAVE, INTCLR) = ui32Interrupt;
517 }
518 
519 //*****************************************************************************
520 //
521 //! @brief Set an IOS Interrupt.
522 //!
523 //! @param ui32Interrupt - desired interrupts.
524 //!
525 //! This function may be used to set an interrupt to the NVIC.
526 //!
527 //! @return None.
528 //
529 //*****************************************************************************
530 void
am_hal_ios_int_set(uint32_t ui32Interrupt)531 am_hal_ios_int_set(uint32_t ui32Interrupt)
532 {
533     //
534     // Use the interrupt clear register to deactivate the chosen interrupt.
535     //
536     AM_REG(IOSLAVE, INTSET) = ui32Interrupt;
537 }
538 
539 //*****************************************************************************
540 //
541 //! @brief Write to the LRAM.
542 //!
543 //! @param ui32Offset - offset into the LRAM to write.
544 //! @param ui8Value - value to be written.
545 //!
546 //! This function writes ui8Value to offset ui32Offset inside the LRAM.
547 //!
548 //! @return None.
549 //
550 //*****************************************************************************
551 void
am_hal_ios_lram_write(uint32_t ui32Offset,uint8_t ui8Value)552 am_hal_ios_lram_write(uint32_t ui32Offset, uint8_t ui8Value)
553 {
554     //
555     // Write the LRAM.
556     //
557     am_hal_ios_pui8LRAM[ui32Offset] = ui8Value;
558 }
559 
560 //*****************************************************************************
561 //
562 //! @brief Read from the LRAM.
563 //!
564 //! @param ui32Offset - offset into the LRAM to read.
565 //!
566 //! This function read from offset ui32Offset inside the LRAM.
567 //!
568 //! @return the value at ui32Offset.
569 //
570 //*****************************************************************************
571 uint8_t
am_hal_ios_lram_read(uint32_t ui32Offset)572 am_hal_ios_lram_read(uint32_t ui32Offset)
573 {
574     //
575     // Read the LRAM.
576     //
577     return am_hal_ios_pui8LRAM[ui32Offset];
578 }
579 
580 //*****************************************************************************
581 //
582 //! @brief Check the status of an IOS Interrupt.
583 //!
584 //! @param bEnabledOnly - return only the enabled interrupt status.
585 //!
586 //! This function may be used to return the enabled interrupt status.
587 //!
588 //! @return the enabled interrupt status.
589 //
590 //*****************************************************************************
591 uint32_t
am_hal_ios_int_status_get(bool bEnabledOnly)592 am_hal_ios_int_status_get(bool bEnabledOnly)
593 {
594     if ( bEnabledOnly )
595     {
596         uint32_t u32RetVal = AM_REG(IOSLAVE, INTSTAT);
597         return u32RetVal & AM_REG(IOSLAVE, INTEN);
598 
599     }
600     else
601     {
602         return AM_REG(IOSLAVE, INTSTAT);
603     }
604 }
605 
606 //*****************************************************************************
607 //
608 //! @brief Check the amount of space used in the FIFO
609 //!
610 //! This function returns the available data in the overall FIFO yet to be
611 //! read by the host. This takes into account the SRAM buffer and hardware FIFO
612 //!
613 //! @return Bytes used in the Overall FIFO.
614 //
615 //*****************************************************************************
616 uint32_t
am_hal_ios_fifo_space_used(void)617 am_hal_ios_fifo_space_used(void)
618 {
619     uint32_t ui32Val;
620     uint32_t ui32Primask;
621     //
622     // Start a critical section for thread safety.
623     //
624     ui32Primask = am_hal_interrupt_master_disable();
625     ui32Val = g_sSRAMBuffer.ui32Length;
626     ui32Val += AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
627     //
628     // End the critical section
629     //
630     am_hal_interrupt_master_set(ui32Primask);
631     return ui32Val;
632 }
633 
634 
635 
636 //*****************************************************************************
637 //
638 //! @brief Check the amount of space left in the FIFO
639 //!
640 //! This function returns the available space in the overall FIFO to accept
641 //! new data. This takes into account the SRAM buffer and hardware FIFO
642 //!
643 //! @return Bytes left in the Overall FIFO.
644 //
645 //*****************************************************************************
646 uint32_t
am_hal_ios_fifo_space_left(void)647 am_hal_ios_fifo_space_left(void)
648 {
649     uint32_t ui32Val;
650     uint32_t ui32Primask;
651     //
652     // Start a critical section for thread safety.
653     //
654     ui32Primask = am_hal_interrupt_master_disable();
655     //
656     // We waste one byte in HW FIFO
657     //
658     ui32Val = g_sSRAMBuffer.ui32Capacity + g_ui32HwFifoSize - 1;
659     ui32Val -= g_sSRAMBuffer.ui32Length;
660     ui32Val -= AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
661     //
662     // End the critical section
663     //
664     am_hal_interrupt_master_set(ui32Primask);
665     return ui32Val;
666 }
667 
668 //*****************************************************************************
669 //
670 //! @brief Check the amount of space left in the hardware FIFO
671 //!
672 //! This function reads the IOSLAVE FIFOPTR register and determines the amount
673 //! of space left in the IOS LRAM FIFO.
674 //!
675 //! @return Bytes left in the IOS FIFO.
676 //
677 //*****************************************************************************
678 static uint32_t
fifo_space_left(void)679 fifo_space_left(void)
680 {
681     //
682     // We waste one byte in HW FIFO
683     //
684     return ((uint32_t)g_ui32HwFifoSize- AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ) - 1);
685 }
686 
687 //*****************************************************************************
688 //
689 // Helper function for managing IOS FIFO writes.
690 //
691 //*****************************************************************************
692 static void
fifo_write(uint8_t * pui8Data,uint32_t ui32NumBytes)693 fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
694 {
695     uint8_t *pFifoPtr = g_pui8FIFOPtr;
696     uint8_t *pFifoBase = g_pui8FIFOBase;
697     uint8_t *pFifoEnd = g_pui8FIFOEnd;
698     while ( ui32NumBytes )
699     {
700         //
701         // Write the data to the FIFO
702         //
703         *pFifoPtr++ = *pui8Data++;
704         ui32NumBytes--;
705 
706         //
707         // Make sure to wrap the FIFO pointer if necessary.
708         //
709         if ( pFifoPtr == pFifoEnd )
710         {
711             pFifoPtr = pFifoBase;
712         }
713     }
714     g_pui8FIFOPtr = pFifoPtr;
715 }
716 
717 //
718 // Assembly code below assumes 8bit FIFOSIZ field aligned at a byte boundary
719 //
720 #if (((AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S) != 0xFF) \
721         || (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S & 0x3))
722 #error "FIFOSIZ not 8bit value aligned at byte offset"
723 #endif
724 
725 //
726 // Byte offset of FIFOSIZ field in FIFOPTR register
727 //
728 #define BYTEOFFSET_FIFOSIZE             (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S >> 3)
729 
730 //*****************************************************************************
731 //
732 // Helper function in assembly for implementing the ReSync
733 //
734 //*****************************************************************************
735 #if defined(__GNUC_STDC_INLINE__)
736 #if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
737 #error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
738 #endif
739 __attribute__((naked))
740 static void
internal_resync_fifoSize(uint32_t wrOffset,uint32_t maxFifoSize,uint32_t hwFifoPtrRegAddr)741 internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
742 {
743     __asm
744     (
745         "   push    {r3,r4}\n\t"                  // Save r3, r4 - used by this function
746         "__internal_resync_fifoSize_loop:\n\t"
747         "   ldr     r4, [r2]\n\t"                 // Load FIFOPTR register in r4
748         "   ubfx    r3, r4, #8, #8\n\t"           // Extract hwFifoSize to r3
749         "   uxtb    r4, r4\n\t"                   // Extract rdOffset in r4
750         "   subs    r4, r0, r4\n\t"               // fifoSize in r4 = wrOffset - rdOffset
751         "   it      cc\n\t"                       // if (wrOffset < rdOffset)
752         "   addcc   r4, r4, r1\n\t"               //     fifoSize = maxFifoSize - (rdOffset - wrOffset)
753         "   cmp     r3, r4\n\t"                   // (hwFifoSize != fifoSize)
754         "   beq     __internal_resync_fifosize_done\n\t"
755         "   strb    r4, [r2, #1]\n\t"             // Overwrite FIFOSIZ value with fifoSize
756         "   b       __internal_resync_fifoSize_loop\n\t" // Repeat the check
757         "__internal_resync_fifosize_done:\n\t"
758         "   pop     {r3,r4}\n\t"                  // Restore registers
759         "   bx      lr\n\t"
760     );
761 }
762 
763 #elif defined(__ARMCC_VERSION)
764 __asm static void
internal_resync_fifoSize(uint32_t wrOffset,uint32_t maxFifoSize,uint32_t hwFifoPtrRegAddr)765 internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
766 {
767     push    {r3, r4}                 // Save r3, r4 - used by this function
768 internal_resync_fifoSize_loop
769     ldr     r4, [r2]                 // Load FIFOPTR register in r4
770     ubfx    r3, r4, #AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S, #8 // Extract hwFifoSize to r3
771     uxtb    r4, r4                   // Extract rdOffset in r4
772     subs    r4, r0, r4               // fifoSize in r4 = wrOffset - rdOffset
773     it      cc                       // if (wrOffset < rdOffset),
774     addcc   r4, r4, r1               //     fifoSize = maxFifoSize - (rdOffset - wrOffset)
775     cmp     r3, r4                   // (hwFifoSize != fifoSize)
776     beq     internal_resync_fifosize_done
777     strb    r4, [r2, #1]             // Overwrite FIFOSIZ value with fifoSize
778     b       internal_resync_fifoSize_loop // Repeat the check
779 internal_resync_fifosize_done
780     pop     {r3, r4}                 // Restore registers
781     bx      lr
782 }
783 
784 #elif defined(__IAR_SYSTEMS_ICC__)
785 #if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
786 #error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
787 #endif
788 __stackless static void
internal_resync_fifoSize(uint32_t wrOffset,uint32_t maxFifoSize,uint32_t hwFifoPtrRegAddr)789 internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
790 {
791     __asm volatile (
792           "    push    {r3,r4}\n"                  // Save r3, r4 - used by this function
793           "__internal_resync_fifoSize_loop:\n"
794           "    ldr     r4, [r2]\n"                 // Load FIFOPTR register in r4
795           "    ubfx    r3, r4, #8, #8\n"           // Extract hwFifoSize to r3
796           "    uxtb    r4, r4\n"                   // Extract rdOffset in r4
797           "    subs    r4, r0, r4\n"               // fifoSize in r4 = wrOffset - rdOffset
798           "    it      cc\n"
799           "    addcc   r4, r4, r1\n"               //     fifoSize = maxFifoSize - (rdOffset - wrOffset)
800           "    cmp     r3, r4\n"                   // (fifoSize != hwFifoSize)
801           "    beq     __internal_resync_fifosize_done\n"
802           "    strb    r4, [r2, #1]\n"             // Overwrite FIFOSIZ value with fifoSize
803           "    b       __internal_resync_fifoSize_loop\n" // Repeat the check
804           "__internal_resync_fifosize_done:\n"
805           "    pop     {r3,r4}\n"                  // Restore registers
806           "    bx      lr\n"
807           );
808 }
809 
810 #else
811 static void
internal_resync_fifoSize(uint32_t wrOffset,uint32_t maxFifoSize,uint32_t hwFifoPtrRegAddr)812 internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
813 {
814     uint32_t fifoSize;
815     uint32_t hwFifoPtrReg;
816     uint32_t rdOffset;
817     uint32_t hwFifoSize;
818 
819     hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
820     rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
821     hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
822     // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
823     fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (maxFifoSize - (rdOffset - wrOffset)));
824     while ( fifoSize != hwFifoSize )
825     {
826         // Overwite correct FIFOSIZ
827         // Need to do a Byte Write to make sure the FIFOPTR is not overwritten
828         *((uint8_t *)(hwFifoPtrRegAddr + BYTEOFFSET_FIFOSIZE)) = fifoSize;
829         // Read back the register and check for consistency
830         hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
831         rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
832         hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
833         // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
834         fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (hwFifoSize - (rdOffset - wrOffset)));
835     }
836 }
837 #endif
838 
839 //
840 // Address of the FIFOPTR register
841 //
842 #define AM_REG_IOS_FIFOPTR      (REG_IOSLAVE_BASEADDR + AM_REG_IOSLAVE_FIFOPTR_O)
843 
844 // When the FIFO is being replenished by the SW, at the same time as host is
845 // reading from it, there is a possible race condition, where the hardware decrement
846 // of FIFOSIZ as a result of read gets overwritten by hardware increment due to
847 // write.
848 // This function re-sync's the FIFOSIZ to ensure such errors do not accumulate
849 void
resync_fifoSize(void)850 resync_fifoSize(void)
851 {
852     uint32_t ui32Primask;
853     uint32_t wrOffset = (uint32_t)g_pui8FIFOPtr - (uint32_t)am_hal_ios_pui8LRAM;
854     //
855     // Start a critical section for thread safety.
856     //
857     ui32Primask = am_hal_interrupt_master_disable();
858     internal_resync_fifoSize(wrOffset, g_ui32HwFifoSize, AM_REG_IOS_FIFOPTR);
859     // Clear interrupts for IOS which could be spuriously triggered
860     AM_REG(IOSLAVE, REGACCINTCLR) = (AM_HAL_IOS_INT_FSIZE | AM_HAL_IOS_INT_FOVFL | AM_HAL_IOS_INT_FUNDFL);
861     //
862     // End the critical section
863     //
864     am_hal_interrupt_master_set(ui32Primask);
865     return;
866 }
867 
868 //*****************************************************************************
869 //
870 //! @brief Transfer any available data from the IOS SRAM buffer to the FIFO.
871 //!
872 //! This function is meant to be called from an interrupt handler for the
873 //! ioslave module. It checks the IOS FIFO interrupt status for a threshold
874 //! event, and transfers data from an SRAM buffer into the IOS FIFO.
875 //!
876 //! @param ui32Status should be set to the ios interrupt status at the time of
877 //! ISR entry.
878 //!
879 //! @return None.
880 //
881 //*****************************************************************************
882 void
am_hal_ios_fifo_service(uint32_t ui32Status)883 am_hal_ios_fifo_service(uint32_t ui32Status)
884 {
885     uint32_t thresh;
886     uint32_t freeSpace, usedSpace, chunk1, chunk2, ui32WriteIndex;
887 
888     //
889     // Check for FIFO size interrupts.
890     //
891     if ( ui32Status & AM_HAL_IOS_INT_FSIZE )
892     {
893         thresh = AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR);
894 
895         //
896         // While the FIFO is at or below threshold Add more data
897         // If Fifo level is above threshold, we're guaranteed an FSIZ interrupt
898         //
899         while ( g_sSRAMBuffer.ui32Length &&
900                 ((usedSpace = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ)) <= thresh) )
901         {
902             //
903             // So, we do have some data in SRAM which needs to be moved to FIFO.
904             // A chunk of data is a continguous set of bytes in SRAM that can be
905             //  written to FIFO. Determine the chunks of data from SRAM that can
906             //  be written. Up to two chunks possible
907             //
908             ui32WriteIndex = g_sSRAMBuffer.ui32WriteIndex;
909             chunk1 = ((ui32WriteIndex > (uint32_t)g_sSRAMBuffer.ui32ReadIndex) ?   \
910                         (ui32WriteIndex - (uint32_t)g_sSRAMBuffer.ui32ReadIndex) : \
911                         (g_sSRAMBuffer.ui32Capacity - (uint32_t)g_sSRAMBuffer.ui32ReadIndex));
912             chunk2 = g_sSRAMBuffer.ui32Length - chunk1;
913             // We waste one byte in HW FIFO
914             freeSpace = g_ui32HwFifoSize - usedSpace - 1;
915             // Write data in chunks
916             // Determine the chunks of data from SRAM that can be written
917             if ( chunk1 > freeSpace )
918             {
919                 fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
920                 //
921                 // Advance the read index, wrapping if needed.
922                 //
923                 g_sSRAMBuffer.ui32ReadIndex += freeSpace;
924                 // No need to check for wrap as we wrote less than chunk1
925                 //
926                 // Adjust the length value to reflect the change.
927                 //
928                 g_sSRAMBuffer.ui32Length -= freeSpace;
929             }
930             else
931             {
932                 fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk1);
933 
934                 //
935                 // Update the read index - wrapping as needed
936                 //
937                 g_sSRAMBuffer.ui32ReadIndex += chunk1;
938                 g_sSRAMBuffer.ui32ReadIndex %= g_sSRAMBuffer.ui32Capacity;
939                 //
940                 // Adjust the length value to reflect the change.
941                 //
942                 g_sSRAMBuffer.ui32Length -= chunk1;
943                 freeSpace -= chunk1;
944 
945                 if ( freeSpace && chunk2 )
946                 {
947                     if ( chunk2 > freeSpace )
948                     {
949                         fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
950 
951                         //
952                         // Advance the read index, wrapping if needed.
953                         //
954                         g_sSRAMBuffer.ui32ReadIndex += freeSpace;
955 
956                         // No need to check for wrap in chunk2
957                         //
958                         // Adjust the length value to reflect the change.
959                         //
960                         g_sSRAMBuffer.ui32Length -= freeSpace;
961                     }
962                     else
963                     {
964                         fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk2);
965                         //
966                         // Advance the read index, wrapping if needed.
967                         //
968                         g_sSRAMBuffer.ui32ReadIndex += chunk2;
969 
970                         // No need to check for wrap in chunk2
971                         //
972                         // Adjust the length value to reflect the change.
973                         //
974                         g_sSRAMBuffer.ui32Length -= chunk2;
975                     }
976                 }
977             }
978             if (!isRevB2())
979             {
980                 resync_fifoSize();
981             }
982 
983             //
984             // Need to retake the FIFO space, after Threshold interrupt has been reenabled
985             // Clear any spurious FSIZE interrupt that might have got raised
986             //
987             AM_BFW(IOSLAVE, INTCLR, FSIZE, 1);
988         }
989     }
990 }
991 
992 //*****************************************************************************
993 //
994 //! @brief Writes the specified number of bytes to the IOS fifo.
995 //!
996 //! @param pui8Data is a pointer to the data to be written to the fifo.
997 //! @param ui32NumBytes is the number of bytes to send.
998 //!
999 //! This function will write data from the caller-provided array to the IOS
1000 //! LRAM FIFO. If there is no space in the LRAM FIFO, the data will be copied
1001 //! to a temporary SRAM buffer instead.
1002 //!
1003 //! The maximum message size for the IO Slave is 1023 bytes.
1004 //!
1005 //! @note In order for SRAM copy operations in the function to work correctly,
1006 //! the \e am_hal_ios_buffer_service() function must be called in the ISR for
1007 //! the ioslave module.
1008 //!
1009 //! @return Number of bytes written (could be less than ui32NumBytes, if not enough space)
1010 //
1011 //*****************************************************************************
1012 uint32_t
am_hal_ios_fifo_write(uint8_t * pui8Data,uint32_t ui32NumBytes)1013 am_hal_ios_fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
1014 {
1015     uint32_t ui32FIFOSpace;
1016     uint32_t ui32SRAMSpace;
1017     uint32_t ui32SRAMLength;
1018     uint32_t ui32Primask;
1019     uint32_t totalBytes = ui32NumBytes;
1020 
1021     //
1022     // This operation will only work properly if an SRAM buffer has been
1023     // allocated. Make sure that am_hal_ios_fifo_buffer_init() has been called,
1024     // and the buffer pointer looks valid.
1025     //
1026     am_hal_debug_assert(g_sSRAMBuffer.pui8Data != 0);
1027 
1028     if ( ui32NumBytes == 0 )
1029     {
1030         return 0;
1031     }
1032 
1033     //
1034     // Start a critical section for thread safety.
1035     //
1036     ui32Primask = am_hal_interrupt_master_disable();
1037 
1038     ui32SRAMLength = g_sSRAMBuffer.ui32Length;
1039     //
1040     // End the critical section
1041     //
1042     am_hal_interrupt_master_set(ui32Primask);
1043 
1044     //
1045     // If the SRAM buffer is empty, we should just write directly to the FIFO.
1046     //
1047     if ( ui32SRAMLength == 0 )
1048     {
1049         ui32FIFOSpace = fifo_space_left();
1050 
1051         //
1052         // If the whole message fits, send it now.
1053         //
1054         if ( ui32NumBytes <= ui32FIFOSpace )
1055         {
1056             fifo_write(pui8Data, ui32NumBytes);
1057             ui32NumBytes = 0;
1058         }
1059         else
1060         {
1061             fifo_write(pui8Data, ui32FIFOSpace);
1062             ui32NumBytes -= ui32FIFOSpace;
1063             pui8Data += ui32FIFOSpace;
1064         };
1065         if (!isRevB2())
1066         {
1067             resync_fifoSize();
1068         }
1069     }
1070 
1071     //
1072     // If there's still data, write it to the SRAM buffer.
1073     //
1074     if ( ui32NumBytes )
1075     {
1076         uint32_t idx, writeIdx, capacity, fifoSize;
1077         ui32SRAMSpace = g_sSRAMBuffer.ui32Capacity - ui32SRAMLength;
1078 
1079         writeIdx = g_sSRAMBuffer.ui32WriteIndex;
1080         capacity = g_sSRAMBuffer.ui32Capacity;
1081         //
1082         // Make sure that the data will fit inside the SRAM buffer.
1083         //
1084         if ( ui32SRAMSpace > ui32NumBytes )
1085         {
1086             ui32SRAMSpace = ui32NumBytes;
1087         }
1088 
1089         //
1090         // If the data will fit, write it to the SRAM buffer.
1091         //
1092         for ( idx = 0; idx < ui32SRAMSpace; idx++ )
1093         {
1094             g_sSRAMBuffer.pui8Data[(idx + writeIdx) % capacity] = pui8Data[idx];
1095         }
1096 
1097         ui32NumBytes -= idx;
1098         //
1099         // Start a critical section for thread safety before updating length & wrIdx.
1100         //
1101         ui32Primask = am_hal_interrupt_master_disable();
1102         //
1103         // Advance the write index, making sure to wrap if necessary.
1104         //
1105         g_sSRAMBuffer.ui32WriteIndex = (idx + writeIdx) % capacity;
1106 
1107         //
1108         // Update the length value appropriately.
1109         //
1110         g_sSRAMBuffer.ui32Length += idx;
1111         //
1112         // End the critical section
1113         //
1114         am_hal_interrupt_master_set(ui32Primask);
1115 
1116         // It is possible that there is a race condition that the FIFO level has
1117         // gone below the threshold by the time we set the wrIdx above, and hence
1118         // we may never get the threshold interrupt to serve the SRAM data we
1119         // just wrote
1120 
1121         // If that is the case, explicitly generate the FSIZE interrupt from here
1122         fifoSize = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
1123         if ( fifoSize <= AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR) )
1124         {
1125             AM_BFW(IOSLAVE, INTSET, FSIZE, 1);
1126         }
1127     }
1128 
1129     // Number of bytes written
1130     g_sSRAMBuffer.ui32FifoInc += totalBytes - ui32NumBytes;
1131     return (totalBytes - ui32NumBytes);
1132 }
1133 
1134 //*****************************************************************************
1135 //
1136 //! @brief Writes the specified number of bytes to the IOS fifo simply.
1137 //!
1138 //! @param pui8Data is a pointer to the data to be written to the fifo.
1139 //! @param ui32NumBytes is the number of bytes to send.
1140 //!
1141 //! This function will write data from the caller-provided array to the IOS
1142 //! LRAM FIFO. This simple routine does not use SRAM buffering for large
1143 //! messages. This function also updates the FIFOCTR.
1144 //!
1145 //! The maximum message size for the IO Slave is 128 bytes.
1146 //!
1147 //! @note Do note call the \e am_hal_ios_buffer_service() function in the ISR for
1148 //! the ioslave module.
1149 //!
1150 //! @return
1151 //
1152 //*****************************************************************************
1153 void
am_hal_ios_fifo_write_simple(uint8_t * pui8Data,uint32_t ui32NumBytes)1154 am_hal_ios_fifo_write_simple(uint8_t *pui8Data, uint32_t ui32NumBytes)
1155 {
1156     uint32_t ui32FIFOSpace;
1157 
1158     //
1159     // Check the FIFO and the SRAM buffer to see where we have space.
1160     //
1161     ui32FIFOSpace = fifo_space_left();
1162 
1163     //
1164     // If the whole message fits, send it now.
1165     //
1166     if ( ui32NumBytes <= ui32FIFOSpace )
1167     {
1168         fifo_write(pui8Data, ui32NumBytes);
1169         // Write FIFOINC
1170         AM_BFW(IOSLAVE, FIFOINC, FIFOINC, ui32NumBytes);
1171     }
1172     else
1173     {
1174         //
1175         // The message didn't fit. Try using am_hal_ios_fifo_write() instead.
1176         //
1177         am_hal_debug_assert_msg(0, "The requested IOS transfer didn't fit in"
1178                                    "the LRAM FIFO. Try using am_hal_ios_fifo_write().");
1179     }
1180 }
1181 
1182 //*****************************************************************************
1183 //
1184 //! @brief Sets the IOS FIFO pointer to the specified LRAM offset.
1185 //!
1186 //! @param ui32Offset is LRAM offset to set the FIFO pointer to.
1187 //!
1188 //! @return None.
1189 //
1190 //*****************************************************************************
1191 void
am_hal_ios_fifo_ptr_set(uint32_t ui32Offset)1192 am_hal_ios_fifo_ptr_set(uint32_t ui32Offset)
1193 {
1194     uint32_t ui32Primask;
1195 
1196     //
1197     // Start a critical section for thread safety.
1198     //
1199     ui32Primask = am_hal_interrupt_master_disable();
1200 
1201     //
1202     // Set the FIFO Update bit.
1203     //
1204     AM_REG(IOSLAVE, FUPD) = 0x1;
1205 
1206     //
1207     // Change the FIFO offset.
1208     //
1209     AM_REG(IOSLAVE, FIFOPTR) = ui32Offset;
1210 
1211     //
1212     // Clear the FIFO update bit.
1213     //
1214     AM_REG(IOSLAVE, FUPD) = 0x0;
1215 
1216     //
1217     // Set the global FIFO-pointer tracking variable.
1218     //
1219     g_pui8FIFOPtr = (uint8_t *) (REG_IOSLAVE_BASEADDR + ui32Offset);
1220 
1221     //
1222     // End the critical section.
1223     //
1224     am_hal_interrupt_master_set(ui32Primask);
1225 }
1226 
1227 //*****************************************************************************
1228 //
1229 // Initialize an SRAM buffer for use with the IO Slave.
1230 //
1231 //*****************************************************************************
1232 static void
am_hal_ios_buffer_init(am_hal_ios_buffer_t * psBuffer,void * pvArray,uint32_t ui32Bytes)1233 am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer, void *pvArray,
1234                        uint32_t ui32Bytes)
1235 {
1236     psBuffer->ui32WriteIndex = 0;
1237     psBuffer->ui32ReadIndex = 0;
1238     psBuffer->ui32Length = 0;
1239     psBuffer->ui32Capacity = ui32Bytes;
1240     psBuffer->ui32FifoInc = 0;
1241     psBuffer->pui8Data = (uint8_t *)pvArray;
1242 }
1243 
1244 //*****************************************************************************
1245 //
1246 //! @brief Poll for all host side read activity to complete.
1247 //!
1248 //! Poll for all host side read activity to complete. Use this before
1249 //! calling am_hal_ios_fifo_write_simple().
1250 //!
1251 //! @return None.
1252 //
1253 //*****************************************************************************
1254 void
am_hal_ios_read_poll_complete(void)1255 am_hal_ios_read_poll_complete(void)
1256 {
1257     while ( AM_REG(IOSLAVE, FUPD) & AM_REG_IOSLAVE_FUPD_IOREAD_M );
1258 }
1259 
1260 //*****************************************************************************
1261 //
1262 //! @brief Initializes an SRAM buffer for the IOS FIFO.
1263 //!
1264 //! @param pui8Buffer is the SRAM buffer that will be used for IOS fifo data.
1265 //! @param ui32BufferSize is the size of the SRAM buffer.
1266 //!
1267 //! This function provides the IOS HAL functions with working memory for
1268 //! managing outgoing IOS FIFO transactions. It needs to be called at least
1269 //! once before am_hal_ios_fifo_write() may be used.
1270 //!
1271 //! The recommended buffer size for the IOS FIFO is 1024 bytes.
1272 //!
1273 //! @return None.
1274 //
1275 //*****************************************************************************
1276 void
am_hal_ios_fifo_buffer_init(uint8_t * pui8Buffer,uint32_t ui32NumBytes)1277 am_hal_ios_fifo_buffer_init(uint8_t *pui8Buffer, uint32_t ui32NumBytes)
1278 {
1279     //
1280     // Initialize the global SRAM buffer
1281     // Total size, which is SRAM Buffer plus the hardware FIFO needs to be
1282     // limited to 1023
1283     //
1284     if ( ui32NumBytes > (1023 - g_ui32HwFifoSize + 1) )
1285     {
1286         ui32NumBytes = (1023 - g_ui32HwFifoSize + 1);
1287     }
1288 
1289     am_hal_ios_buffer_init(&g_sSRAMBuffer, pui8Buffer, ui32NumBytes);
1290 
1291     //
1292     // Clear the FIFO State
1293     //
1294     AM_BFW(IOSLAVE, FIFOCTR, FIFOCTR, 0x0);
1295     AM_BFW(IOSLAVE, FIFOPTR, FIFOSIZ, 0x0);
1296 
1297     am_hal_ios_fifo_ptr_set(g_ui32FifoBaseOffset);
1298 }
1299 
1300 //*****************************************************************************
1301 //
1302 //! @brief Update the FIFOCTR to inform host of available data to read.
1303 //!
1304 //! This function allows the application to indicate to HAL when it is safe to
1305 //! update the FIFOCTR. This function needs to be used in conjunction with
1306 //! am_hal_ios_fifo_write(), which itself does not update the FIFOCTR
1307 //!
1308 //! CAUTION:
1309 //! Application needs to implement some sort of
1310 //! synchronization with the host to make sure host is not reading FIFOCTR while
1311 //! it is being updated by the MCU, since the FIFOCTR read over
1312 //! IO is not an atomic operation. Otherwise, some other logic could be implemented
1313 //! by the host to detect and disregard transient values of FIFOCTR (e.g. multiple
1314 //! reads till it gets a stable value).
1315 //! For Pre-B2 parts, it is necessary to have this synchronization guarantee that
1316 //! Host is not doing any READ operation - be it for FIFOCTR or FIFO itself when
1317 //! this call is made, as otherwise the FIFOCTR value may get corrupted.
1318 //!
1319 //!
1320 //! @return None.
1321 //
1322 //*****************************************************************************
1323 void
am_hal_ios_update_fifoctr(void)1324 am_hal_ios_update_fifoctr(void)
1325 {
1326     // Write FIFOINC
1327     AM_BFW(IOSLAVE, FIFOINC, FIFOINC, g_sSRAMBuffer.ui32FifoInc);
1328     g_sSRAMBuffer.ui32FifoInc = 0;
1329     return;
1330 }
1331 
1332 //*****************************************************************************
1333 //
1334 //  End the doxygen group
1335 //! @}
1336 //
1337 //*****************************************************************************
1338