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