1 //*****************************************************************************
2 //
3 // ssi.c - Driver for Synchronous Serial Interface.
4 //
5 // Copyright (c) 2005-2020 Texas Instruments Incorporated.  All rights reserved.
6 // Software License Agreement
7 //
8 //   Redistribution and use in source and binary forms, with or without
9 //   modification, are permitted provided that the following conditions
10 //   are met:
11 //
12 //   Redistributions of source code must retain the above copyright
13 //   notice, this list of conditions and the following disclaimer.
14 //
15 //   Redistributions in binary form must reproduce the above copyright
16 //   notice, this list of conditions and the following disclaimer in the
17 //   documentation and/or other materials provided with the
18 //   distribution.
19 //
20 //   Neither the name of Texas Instruments Incorporated nor the names of
21 //   its contributors may be used to endorse or promote products derived
22 //   from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 //
36 // This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
37 //
38 //*****************************************************************************
39 
40 //*****************************************************************************
41 //
42 //! \addtogroup ssi_api
43 //! @{
44 //
45 //*****************************************************************************
46 
47 #include <stdbool.h>
48 #include <stdint.h>
49 #include "inc/hw_ints.h"
50 #include "inc/hw_memmap.h"
51 #include "inc/hw_ssi.h"
52 #include "inc/hw_sysctl.h"
53 #include "inc/hw_types.h"
54 #include "driverlib/debug.h"
55 #include "driverlib/interrupt.h"
56 #include "driverlib/ssi.h"
57 
58 //*****************************************************************************
59 //
60 // A mapping of timer base address to interrupt number.
61 //
62 //*****************************************************************************
63 static const uint32_t g_ppui32SSIIntMap[][2] =
64 {
65     { SSI0_BASE, INT_SSI0_TM4C123 },
66     { SSI1_BASE, INT_SSI1_TM4C123 },
67     { SSI2_BASE, INT_SSI2_TM4C123 },
68     { SSI3_BASE, INT_SSI3_TM4C123 },
69 };
70 static const uint_fast8_t g_ui8SSIIntMapRows =
71     sizeof(g_ppui32SSIIntMap) / sizeof(g_ppui32SSIIntMap[0]);
72 
73 static const uint32_t g_ppui32SSIIntMapSnowflake[][2] =
74 {
75     { SSI0_BASE, INT_SSI0_TM4C129 },
76     { SSI1_BASE, INT_SSI1_TM4C129 },
77     { SSI2_BASE, INT_SSI2_TM4C129 },
78     { SSI3_BASE, INT_SSI3_TM4C129 },
79 };
80 static const uint_fast8_t g_ui8SSIIntMapSnowflakeRows =
81     sizeof(g_ppui32SSIIntMapSnowflake) / sizeof(g_ppui32SSIIntMapSnowflake[0]);
82 
83 //*****************************************************************************
84 //
85 //! \internal
86 //! Checks an SSI base address.
87 //!
88 //! \param ui32Base specifies the SSI module base address.
89 //!
90 //! This function determines if a SSI module base address is valid.
91 //!
92 //! \return Returns \b true if the base address is valid and \b false
93 //! otherwise.
94 //
95 //*****************************************************************************
96 #ifdef DEBUG
97 static bool
_SSIBaseValid(uint32_t ui32Base)98 _SSIBaseValid(uint32_t ui32Base)
99 {
100     return((ui32Base == SSI0_BASE) || (ui32Base == SSI1_BASE) ||
101            (ui32Base == SSI2_BASE) || (ui32Base == SSI3_BASE));
102 }
103 #endif
104 
105 //*****************************************************************************
106 //
107 //! Returns the interrupt number of SSI module .
108 //!
109 //! \param ui32Base is the base address of the SSI module.
110 //!
111 //! This function returns the interrupt number for the SSI module with the base
112 //! address passed in the \e ui32Base parameter.
113 //!
114 //! \return Returns an SSI interrupt number, or 0 if the interrupt does not
115 //! exist.
116 //
117 //*****************************************************************************
118 static uint32_t
_SSIIntNumberGet(uint32_t ui32Base)119 _SSIIntNumberGet(uint32_t ui32Base)
120 {
121     uint_fast8_t ui8Idx, ui8Rows;
122     const uint32_t (*ppui32SSIIntMap)[2];
123 
124     //
125     // Check the arguments.
126     //
127     ASSERT(_SSIBaseValid(ui32Base));
128 
129     ppui32SSIIntMap = g_ppui32SSIIntMap;
130     ui8Rows = g_ui8SSIIntMapRows;
131 
132     if(CLASS_IS_TM4C129)
133     {
134         ppui32SSIIntMap = g_ppui32SSIIntMapSnowflake;
135         ui8Rows = g_ui8SSIIntMapSnowflakeRows;
136     }
137 
138     //
139     // Loop through the table that maps SSI base addresses to interrupt
140     // numbers.
141     //
142     for(ui8Idx = 0; ui8Idx < ui8Rows; ui8Idx++)
143     {
144         //
145         // See if this base address matches.
146         //
147         if(ppui32SSIIntMap[ui8Idx][0] == ui32Base)
148         {
149             //
150             // Return the corresponding interrupt number.
151             //
152             return(ppui32SSIIntMap[ui8Idx][1]);
153         }
154     }
155 
156     //
157     // The base address could not be found, so return an error.
158     //
159     return(0);
160 }
161 
162 //*****************************************************************************
163 //
164 //! Configures the synchronous serial interface.
165 //!
166 //! \param ui32Base specifies the SSI module base address.
167 //! \param ui32SSIClk is the rate of the clock supplied to the SSI module.
168 //! \param ui32Protocol specifies the data transfer protocol.
169 //! \param ui32Mode specifies the mode of operation.
170 //! \param ui32BitRate specifies the clock rate.
171 //! \param ui32DataWidth specifies number of bits transferred per frame.
172 //!
173 //! This function configures the synchronous serial interface.  It sets
174 //! the SSI protocol, mode of operation, bit rate, and data width.
175 //!
176 //! The \e ui32Protocol parameter defines the data frame format.  The
177 //! \e ui32Protocol parameter can be one of the following values:
178 //! \b SSI_FRF_MOTO_MODE_0, \b SSI_FRF_MOTO_MODE_1, \b SSI_FRF_MOTO_MODE_2,
179 //! \b SSI_FRF_MOTO_MODE_3, \b SSI_FRF_TI, or \b SSI_FRF_NMW. Note that
180 //! the \b SSI_FRF_NMW option is only available on some devices. Refer to the
181 //! device data sheet to determine if the Microwire format is supported on
182 //! a particular device.  The Motorola  frame formats encode the following
183 //! polarity and phase configurations:
184 //!
185 //! <pre>
186 //! Polarity Phase       Mode
187 //!   0       0   SSI_FRF_MOTO_MODE_0
188 //!   0       1   SSI_FRF_MOTO_MODE_1
189 //!   1       0   SSI_FRF_MOTO_MODE_2
190 //!   1       1   SSI_FRF_MOTO_MODE_3
191 //! </pre>
192 //!
193 //! The \e ui32Mode parameter defines the operating mode of the SSI module.
194 //! The SSI module can operate as a master or slave; if it is a slave, the SSI
195 //! can be configured to disable output on its serial output line.  The
196 //! \e ui32Mode parameter can be one of the following values:
197 //! \b SSI_MODE_MASTER, \b SSI_MODE_SLAVE, or \b SSI_MODE_SLAVE_OD.
198 //!
199 //! The \e ui32BitRate parameter defines the bit rate for the SSI.  This bit
200 //! rate must satisfy the following clock ratio criteria:
201 //!
202 //! - FSSI >= 2 * bit rate (master mode)
203 //! - FSSI >= 12 * bit rate (slave modes)
204 //!
205 //! where FSSI is the frequency of the clock supplied to the SSI module. Note
206 //! that there are frequency limits for FSSI that are described in the Bit Rate
207 //! Generation section of the SSI chapter in the data sheet.
208 //!
209 //! The \e ui32DataWidth parameter defines the width of the data transfers and
210 //! can be a value between 4 and 16, inclusive.
211 //!
212 //! The peripheral clock is the same as the processor clock.  The frequency of
213 //! the system clock is the value returned by SysCtlClockGet() for TM4C123x
214 //! devices or the value returned by SysCtlClockFreqSet() for TM4C129x devices,
215 //! or it can be explicitly hard coded if it is constant and known (to save the
216 //! code/execution overhead of a call to SysCtlClockGet() or fetch of the
217 //! variable call holding the return value of SysCtlClockFreqSet()).
218 //!
219 //! \return None.
220 //
221 //*****************************************************************************
222 void
SSIConfigSetExpClk(uint32_t ui32Base,uint32_t ui32SSIClk,uint32_t ui32Protocol,uint32_t ui32Mode,uint32_t ui32BitRate,uint32_t ui32DataWidth)223 SSIConfigSetExpClk(uint32_t ui32Base, uint32_t ui32SSIClk,
224                    uint32_t ui32Protocol, uint32_t ui32Mode,
225                    uint32_t ui32BitRate, uint32_t ui32DataWidth)
226 {
227     uint32_t ui32MaxBitRate;
228     uint32_t ui32RegVal;
229     uint32_t ui32PreDiv;
230     uint32_t ui32SCR;
231     uint32_t ui32SPH_SPO;
232 
233     //
234     // Check the arguments.
235     //
236     ASSERT(_SSIBaseValid(ui32Base));
237     ASSERT((ui32Protocol == SSI_FRF_MOTO_MODE_0) ||
238            (ui32Protocol == SSI_FRF_MOTO_MODE_1) ||
239            (ui32Protocol == SSI_FRF_MOTO_MODE_2) ||
240            (ui32Protocol == SSI_FRF_MOTO_MODE_3) ||
241            (ui32Protocol == SSI_FRF_TI) ||
242            (ui32Protocol == SSI_FRF_NMW));
243     ASSERT((ui32Mode == SSI_MODE_MASTER) ||
244            (ui32Mode == SSI_MODE_SLAVE));
245     ASSERT(((ui32Mode == SSI_MODE_MASTER) &&
246             (ui32BitRate <= (ui32SSIClk / 2))) ||
247            ((ui32Mode != SSI_MODE_MASTER) &&
248             (ui32BitRate <= (ui32SSIClk / 12))));
249     ASSERT((ui32SSIClk / ui32BitRate) <= (254 * 256));
250     ASSERT((ui32DataWidth >= 4) && (ui32DataWidth <= 16));
251 
252     //
253     // Set the mode.
254     //
255     ui32RegVal = (ui32Mode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
256     HWREG(ui32Base + SSI_O_CR1) = ui32RegVal;
257 
258     //
259     // Set the clock predivider.
260     //
261     ui32MaxBitRate = ui32SSIClk / ui32BitRate;
262     ui32PreDiv = 0;
263     do
264     {
265         ui32PreDiv += 2;
266         ui32SCR = (ui32MaxBitRate / ui32PreDiv) - 1;
267     }
268     while(ui32SCR > 255);
269     HWREG(ui32Base + SSI_O_CPSR) = ui32PreDiv;
270 
271     //
272     // Set protocol and clock rate.
273     //
274     ui32SPH_SPO = (ui32Protocol & 3) << 6;
275     ui32Protocol &= SSI_CR0_FRF_M;
276     ui32RegVal = (ui32SCR << 8) | ui32SPH_SPO | ui32Protocol |
277                  (ui32DataWidth - 1);
278     HWREG(ui32Base + SSI_O_CR0) = ui32RegVal;
279 }
280 
281 //*****************************************************************************
282 //
283 //! Enables the synchronous serial interface.
284 //!
285 //! \param ui32Base specifies the SSI module base address.
286 //!
287 //! This function enables operation of the synchronous serial interface.  The
288 //! synchronous serial interface must be configured before it is enabled.
289 //!
290 //! \return None.
291 //
292 //*****************************************************************************
293 void
SSIEnable(uint32_t ui32Base)294 SSIEnable(uint32_t ui32Base)
295 {
296     //
297     // Check the arguments.
298     //
299     ASSERT(_SSIBaseValid(ui32Base));
300 
301     //
302     // Read-modify-write the enable bit.
303     //
304     HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_SSE;
305 }
306 
307 //*****************************************************************************
308 //
309 //! Disables the synchronous serial interface.
310 //!
311 //! \param ui32Base specifies the SSI module base address.
312 //!
313 //! This function disables operation of the synchronous serial interface.
314 //!
315 //! \return None.
316 //
317 //*****************************************************************************
318 void
SSIDisable(uint32_t ui32Base)319 SSIDisable(uint32_t ui32Base)
320 {
321     //
322     // Check the arguments.
323     //
324     ASSERT(_SSIBaseValid(ui32Base));
325 
326     //
327     // Read-modify-write the enable bit.
328     //
329     HWREG(ui32Base + SSI_O_CR1) &= ~(SSI_CR1_SSE);
330 }
331 
332 //*****************************************************************************
333 //
334 //! Registers an interrupt handler for the synchronous serial interface.
335 //!
336 //! \param ui32Base specifies the SSI module base address.
337 //! \param pfnHandler is a pointer to the function to be called when the
338 //! synchronous serial interface interrupt occurs.
339 //!
340 //! This function registers the handler to be called when an SSI interrupt
341 //! occurs.  This function enables the global interrupt in the interrupt
342 //! controller; specific SSI interrupts must be enabled via SSIIntEnable().  If
343 //! necessary, it is the interrupt handler's responsibility to clear the
344 //! interrupt source via SSIIntClear().
345 //!
346 //! \sa IntRegister() for important information about registering interrupt
347 //! handlers.
348 //!
349 //! \return None.
350 //
351 //*****************************************************************************
352 void
SSIIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))353 SSIIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
354 {
355     uint32_t ui32Int;
356 
357     //
358     // Check the arguments.
359     //
360     ASSERT(_SSIBaseValid(ui32Base));
361 
362     //
363     // Determine the interrupt number based on the SSI module.
364     //
365     ui32Int = _SSIIntNumberGet(ui32Base);
366 
367     ASSERT(ui32Int != 0);
368 
369     //
370     // Register the interrupt handler, returning an error if an error occurs.
371     //
372     IntRegister(ui32Int, pfnHandler);
373 
374     //
375     // Enable the synchronous serial interface interrupt.
376     //
377     IntEnable(ui32Int);
378 }
379 
380 //*****************************************************************************
381 //
382 //! Unregisters an interrupt handler for the synchronous serial interface.
383 //!
384 //! \param ui32Base specifies the SSI module base address.
385 //!
386 //! This function clears the handler to be called when an SSI interrupt
387 //! occurs.  This function also masks off the interrupt in the interrupt
388 //! controller so that the interrupt handler no longer is called.
389 //!
390 //! \sa IntRegister() for important information about registering interrupt
391 //! handlers.
392 //!
393 //! \return None.
394 //
395 //*****************************************************************************
396 void
SSIIntUnregister(uint32_t ui32Base)397 SSIIntUnregister(uint32_t ui32Base)
398 {
399     uint32_t ui32Int;
400 
401     //
402     // Check the arguments.
403     //
404     ASSERT(_SSIBaseValid(ui32Base));
405 
406     //
407     // Determine the interrupt number based on the SSI module.
408     //
409     ui32Int = _SSIIntNumberGet(ui32Base);
410 
411     ASSERT(ui32Int != 0);
412 
413     //
414     // Disable the interrupt.
415     //
416     IntDisable(ui32Int);
417 
418     //
419     // Unregister the interrupt handler.
420     //
421     IntUnregister(ui32Int);
422 }
423 
424 //*****************************************************************************
425 //
426 //! Enables individual SSI interrupt sources.
427 //!
428 //! \param ui32Base specifies the SSI module base address.
429 //! \param ui32IntFlags is a bit mask of the interrupt sources to be enabled.
430 //!
431 //! This function enables the indicated SSI interrupt sources.  Only the
432 //! sources that are enabled can be reflected to the processor interrupt;
433 //! disabled sources have no effect on the processor.  The \e ui32IntFlags
434 //! parameter can be any of the \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, or
435 //! \b SSI_RXOR values.
436 //!
437 //! \return None.
438 //
439 //*****************************************************************************
440 void
SSIIntEnable(uint32_t ui32Base,uint32_t ui32IntFlags)441 SSIIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
442 {
443     //
444     // Check the arguments.
445     //
446     ASSERT(_SSIBaseValid(ui32Base));
447 
448     //
449     // Enable the specified interrupts.
450     //
451     HWREG(ui32Base + SSI_O_IM) |= ui32IntFlags;
452 }
453 
454 //*****************************************************************************
455 //
456 //! Disables individual SSI interrupt sources.
457 //!
458 //! \param ui32Base specifies the SSI module base address.
459 //! \param ui32IntFlags is a bit mask of the interrupt sources to be disabled.
460 //!
461 //! This function disables the indicated SSI interrupt sources.  The
462 //! \e ui32IntFlags parameter can be any of the \b SSI_TXFF, \b SSI_RXFF,
463 //!  \b SSI_RXTO, or \b SSI_RXOR values.
464 //!
465 //! \return None.
466 //
467 //*****************************************************************************
468 void
SSIIntDisable(uint32_t ui32Base,uint32_t ui32IntFlags)469 SSIIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
470 {
471     //
472     // Check the arguments.
473     //
474     ASSERT(_SSIBaseValid(ui32Base));
475 
476     //
477     // Disable the specified interrupts.
478     //
479     HWREG(ui32Base + SSI_O_IM) &= ~(ui32IntFlags);
480 }
481 
482 //*****************************************************************************
483 //
484 //! Gets the current interrupt status.
485 //!
486 //! \param ui32Base specifies the SSI module base address.
487 //! \param bMasked is \b false if the raw interrupt status is required or
488 //! \b true if the masked interrupt status is required.
489 //!
490 //! This function returns the interrupt status for the SSI module.  Either the
491 //! raw interrupt status or the status of interrupts that are allowed to
492 //! reflect to the processor can be returned.
493 //!
494 //! \return The current interrupt status, enumerated as a bit field of
495 //! \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, and \b SSI_RXOR.
496 //
497 //*****************************************************************************
498 uint32_t
SSIIntStatus(uint32_t ui32Base,bool bMasked)499 SSIIntStatus(uint32_t ui32Base, bool bMasked)
500 {
501     //
502     // Check the arguments.
503     //
504     ASSERT(_SSIBaseValid(ui32Base));
505 
506     //
507     // Return either the interrupt status or the raw interrupt status as
508     // requested.
509     //
510     if(bMasked)
511     {
512         return(HWREG(ui32Base + SSI_O_MIS));
513     }
514     else
515     {
516         return(HWREG(ui32Base + SSI_O_RIS));
517     }
518 }
519 
520 //*****************************************************************************
521 //
522 //! Clears SSI interrupt sources.
523 //!
524 //! \param ui32Base specifies the SSI module base address.
525 //! \param ui32IntFlags is a bit mask of the interrupt sources to be cleared.
526 //!
527 //! This function clears the specified SSI interrupt sources so that they no
528 //! longer assert.  This function must be called in the interrupt handler to
529 //! keep the interrupts from being triggered again immediately upon exit.  The
530 //! \e ui32IntFlags parameter can consist of either or both the \b SSI_RXTO and
531 //! \b SSI_RXOR values.
532 //!
533 //! \note Because there is a write buffer in the Cortex-M processor, it may
534 //! take several clock cycles before the interrupt source is actually cleared.
535 //! Therefore, it is recommended that the interrupt source be cleared early in
536 //! the interrupt handler (as opposed to the very last action) to avoid
537 //! returning from the interrupt handler before the interrupt source is
538 //! actually cleared.  Failure to do so may result in the interrupt handler
539 //! being immediately reentered (because the interrupt controller still sees
540 //! the interrupt source asserted).
541 //!
542 //! \return None.
543 //
544 //*****************************************************************************
545 void
SSIIntClear(uint32_t ui32Base,uint32_t ui32IntFlags)546 SSIIntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
547 {
548     //
549     // Check the arguments.
550     //
551     ASSERT(_SSIBaseValid(ui32Base));
552 
553     //
554     // Clear the requested interrupt sources.
555     //
556     HWREG(ui32Base + SSI_O_ICR) = ui32IntFlags;
557 }
558 
559 //*****************************************************************************
560 //
561 //! Puts a data element into the SSI transmit FIFO.
562 //!
563 //! \param ui32Base specifies the SSI module base address.
564 //! \param ui32Data is the data to be transmitted over the SSI interface.
565 //!
566 //! This function places the supplied data into the transmit FIFO of the
567 //! specified SSI module.  If there is no space available in the transmit FIFO,
568 //! this function waits until there is space available before returning.
569 //!
570 //! \note The upper 32 - N bits of \e ui32Data are discarded by the hardware,
571 //! where N is the data width as configured by SSIConfigSetExpClk().  For
572 //! example, if the interface is configured for 8-bit data width, the upper 24
573 //! bits of \e ui32Data are discarded.
574 //!
575 //! \return None.
576 //
577 //*****************************************************************************
578 void
SSIDataPut(uint32_t ui32Base,uint32_t ui32Data)579 SSIDataPut(uint32_t ui32Base, uint32_t ui32Data)
580 {
581     //
582     // Check the arguments.
583     //
584     ASSERT(_SSIBaseValid(ui32Base));
585     ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
586                                        SSI_CR0_DSS_M))) == 0);
587 
588     //
589     // Wait until there is space.
590     //
591     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
592     {
593     }
594 
595     //
596     // Write the data to the SSI.
597     //
598     HWREG(ui32Base + SSI_O_DR) = ui32Data;
599 }
600 
601 //*****************************************************************************
602 //
603 //! Puts a data element into the SSI transmit FIFO.
604 //!
605 //! \param ui32Base specifies the SSI module base address.
606 //! \param ui32Data is the data to be transmitted over the SSI interface.
607 //!
608 //! This function places the supplied data into the transmit FIFO of the
609 //! specified SSI module.  If there is no space in the FIFO, then this function
610 //! returns a zero.
611 //!
612 //! \note The upper 32 - N bits of \e ui32Data are discarded by the hardware,
613 //! where N is the data width as configured by SSIConfigSetExpClk().  For
614 //! example, if the interface is configured for 8-bit data width, the upper 24
615 //! bits of \e ui32Data are discarded.
616 //!
617 //! \return Returns the number of elements written to the SSI transmit FIFO.
618 //
619 //*****************************************************************************
620 int32_t
SSIDataPutNonBlocking(uint32_t ui32Base,uint32_t ui32Data)621 SSIDataPutNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
622 {
623     //
624     // Check the arguments.
625     //
626     ASSERT(_SSIBaseValid(ui32Base));
627     ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
628                                        SSI_CR0_DSS_M))) == 0);
629 
630     //
631     // Check for space to write.
632     //
633     if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
634     {
635         HWREG(ui32Base + SSI_O_DR) = ui32Data;
636         return(1);
637     }
638     else
639     {
640         return(0);
641     }
642 }
643 
644 //*****************************************************************************
645 //
646 //! Gets a data element from the SSI receive FIFO.
647 //!
648 //! \param ui32Base specifies the SSI module base address.
649 //! \param pui32Data is a pointer to a storage location for data that was
650 //! received over the SSI interface.
651 //!
652 //! This function gets received data from the receive FIFO of the specified
653 //! SSI module and places that data into the location specified by the
654 //! \e pui32Data parameter.  If there is no data available, this function waits
655 //! until data is received before returning.
656 //!
657 //! \note Only the lower N bits of the value written to \e pui32Data contain
658 //! valid data, where N is the data width as configured by
659 //! SSIConfigSetExpClk().  For example, if the interface is configured for
660 //! 8-bit data width, only the lower 8 bits of the value written to
661 //! \e pui32Data contain valid data.
662 //!
663 //! \return None.
664 //
665 //*****************************************************************************
666 void
SSIDataGet(uint32_t ui32Base,uint32_t * pui32Data)667 SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data)
668 {
669     //
670     // Check the arguments.
671     //
672     ASSERT(_SSIBaseValid(ui32Base));
673 
674     //
675     // Wait until there is data to be read.
676     //
677     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE))
678     {
679     }
680 
681     //
682     // Read data from SSI.
683     //
684     *pui32Data = HWREG(ui32Base + SSI_O_DR);
685 }
686 
687 //*****************************************************************************
688 //
689 //! Gets a data element from the SSI receive FIFO.
690 //!
691 //! \param ui32Base specifies the SSI module base address.
692 //! \param pui32Data is a pointer to a storage location for data that was
693 //! received over the SSI interface.
694 //!
695 //! This function gets one received data element from the receive FIFO of the
696 //! specified SSI module and places that data into the location specified by
697 //! the \e ui32Data parameter.  If there is no data in the FIFO, then this
698 //! function returns a zero.
699 //!
700 //! \note Only the lower N bits of the value written to \e pui32Data contain
701 //! valid data, where N is the data width as configured by
702 //! SSIConfigSetExpClk().  For example, if the interface is configured for
703 //! 8-bit data width, only the lower 8 bits of the value written to
704 //! \e pui32Data contain valid data.
705 //!
706 //! \return Returns 1 if there is data element read or 0 if no data in FIFO
707 //
708 //*****************************************************************************
709 int32_t
SSIDataGetNonBlocking(uint32_t ui32Base,uint32_t * pui32Data)710 SSIDataGetNonBlocking(uint32_t ui32Base, uint32_t *pui32Data)
711 {
712     //
713     // Check the arguments.
714     //
715     ASSERT(_SSIBaseValid(ui32Base));
716 
717     //
718     // Check for data to read.
719     //
720     if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE)
721     {
722         *pui32Data = HWREG(ui32Base + SSI_O_DR);
723         return(1);
724     }
725     else
726     {
727         return(0);
728     }
729 }
730 
731 //*****************************************************************************
732 //
733 //! Enables SSI DMA operation.
734 //!
735 //! \param ui32Base is the base address of the SSI module.
736 //! \param ui32DMAFlags is a bit mask of the DMA features to enable.
737 //!
738 //! This function enables the specified SSI DMA features.  The SSI can be
739 //! configured to use DMA for transmit and/or receive data transfers.
740 //! The \e ui32DMAFlags parameter is the logical OR of any of the following
741 //! values:
742 //!
743 //! - SSI_DMA_RX - enable DMA for receive
744 //! - SSI_DMA_TX - enable DMA for transmit
745 //!
746 //! \note The uDMA controller must also be set up before DMA can be used
747 //! with the SSI.
748 //!
749 //! \return None.
750 //
751 //*****************************************************************************
752 void
SSIDMAEnable(uint32_t ui32Base,uint32_t ui32DMAFlags)753 SSIDMAEnable(uint32_t ui32Base, uint32_t ui32DMAFlags)
754 {
755     //
756     // Check the arguments.
757     //
758     ASSERT(_SSIBaseValid(ui32Base));
759 
760     //
761     // Set the requested bits in the SSI DMA control register.
762     //
763     HWREG(ui32Base + SSI_O_DMACTL) |= ui32DMAFlags;
764 }
765 
766 //*****************************************************************************
767 //
768 //! Disables SSI DMA operation.
769 //!
770 //! \param ui32Base is the base address of the SSI module.
771 //! \param ui32DMAFlags is a bit mask of the DMA features to disable.
772 //!
773 //! This function is used to disable SSI DMA features that were enabled
774 //! by SSIDMAEnable().  The specified SSI DMA features are disabled.  The
775 //! \e ui32DMAFlags parameter is the logical OR of any of the following values:
776 //!
777 //! - SSI_DMA_RX - disable DMA for receive
778 //! - SSI_DMA_TX - disable DMA for transmit
779 //!
780 //! \return None.
781 //
782 //*****************************************************************************
783 void
SSIDMADisable(uint32_t ui32Base,uint32_t ui32DMAFlags)784 SSIDMADisable(uint32_t ui32Base, uint32_t ui32DMAFlags)
785 {
786     //
787     // Check the arguments.
788     //
789     ASSERT(_SSIBaseValid(ui32Base));
790 
791     //
792     // Clear the requested bits in the SSI DMA control register.
793     //
794     HWREG(ui32Base + SSI_O_DMACTL) &= ~ui32DMAFlags;
795 }
796 
797 //*****************************************************************************
798 //
799 //! Determines whether the SSI transmitter is busy or not.
800 //!
801 //! \param ui32Base is the base address of the SSI module.
802 //!
803 //! This function allows the caller to determine whether all transmitted bytes
804 //! have cleared the transmitter hardware.  If \b false is returned, then the
805 //! transmit FIFO is empty and all bits of the last transmitted word have left
806 //! the hardware shift register.
807 //!
808 //! \return Returns \b true if the SSI is transmitting or \b false if all
809 //! transmissions are complete.
810 //
811 //*****************************************************************************
812 bool
SSIBusy(uint32_t ui32Base)813 SSIBusy(uint32_t ui32Base)
814 {
815     //
816     // Check the arguments.
817     //
818     ASSERT(_SSIBaseValid(ui32Base));
819 
820     //
821     // Determine if the SSI is busy.
822     //
823     return((HWREG(ui32Base + SSI_O_SR) & SSI_SR_BSY) ? true : false);
824 }
825 
826 //*****************************************************************************
827 //
828 //! Sets the data clock source for the specified SSI peripheral.
829 //!
830 //! \param ui32Base is the base address of the SSI module.
831 //! \param ui32Source is the baud clock source for the SSI.
832 //!
833 //! This function allows the baud clock source for the SSI to be selected.
834 //! The possible clock source are the system clock (\b SSI_CLOCK_SYSTEM) or
835 //! the precision internal oscillator (\b SSI_CLOCK_PIOSC).
836 //!
837 //! Changing the baud clock source changes the data rate generated by the
838 //! SSI.  Therefore, the data rate should be reconfigured after any change to
839 //! the SSI clock source.
840 //!
841 //! \note The ability to specify the SSI baud clock source varies with the
842 //! Tiva part and SSI in use.  Please consult the data sheet for the part
843 //! in use to determine whether this support is available.
844 //!
845 //! \return None.
846 //
847 //*****************************************************************************
848 void
SSIClockSourceSet(uint32_t ui32Base,uint32_t ui32Source)849 SSIClockSourceSet(uint32_t ui32Base, uint32_t ui32Source)
850 {
851     //
852     // Check the arguments.
853     //
854     ASSERT(_SSIBaseValid(ui32Base));
855     ASSERT((ui32Source == SSI_CLOCK_SYSTEM) ||
856            (ui32Source == SSI_CLOCK_PIOSC));
857 
858     //
859     // Set the SSI clock source.
860     //
861     HWREG(ui32Base + SSI_O_CC) = ui32Source;
862 }
863 
864 //*****************************************************************************
865 //
866 //! Gets the data clock source for the specified SSI peripheral.
867 //!
868 //! \param ui32Base is the base address of the SSI module.
869 //!
870 //! This function returns the data clock source for the specified SSI.
871 //!
872 //! \note The ability to specify the SSI data clock source varies with the
873 //! Tiva part and SSI in use.  Please consult the data sheet for the part
874 //! in use to determine whether this support is available.
875 //!
876 //! \return Returns the current clock source, which is either
877 //! \b SSI_CLOCK_SYSTEM or \b SSI_CLOCK_PIOSC.
878 //
879 //*****************************************************************************
880 uint32_t
SSIClockSourceGet(uint32_t ui32Base)881 SSIClockSourceGet(uint32_t ui32Base)
882 {
883     //
884     // Check the arguments.
885     //
886     ASSERT(_SSIBaseValid(ui32Base));
887 
888     //
889     // Return the SSI clock source.
890     //
891     return(HWREG(ui32Base + SSI_O_CC));
892 }
893 
894 //*****************************************************************************
895 //
896 //! Selects the advanced mode of operation for the SSI module.
897 //!
898 //! \param ui32Base is the base address of the SSI module.
899 //! \param ui32Mode is the mode of operation to use.
900 //!
901 //! This function selects the mode of operation for the SSI module, which is
902 //! needed when using the advanced operation modes (Bi- or Quad-SPI).  One of
903 //! the following modes can be selected:
904 //!
905 //! - \b SSI_ADV_MODE_LEGACY - Disables the advanced modes of operation,
906 //!   resulting in legacy, or backwards-compatible, operation.  When this mode
907 //!   is selected, it is not valid to switch to Bi- or Quad-SPI operation.
908 //!   This mode is the default.
909 //! - \b SSI_ADV_MODE_WRITE - The advanced mode of operation where data is only
910 //!   written to the slave; any data clocked in via the \b SSIRx pin is thrown
911 //!   away (instead of being placed into the SSI Rx FIFO).
912 //! - \b SSI_ADV_MODE_READ_WRITE - The advanced mode of operation where data is
913 //!   written to and read from the slave; this mode is the same as
914 //!   \b SSI_ADV_MODE_LEGACY but allows transitions to Bi- or Quad-SPI
915 //!   operation.
916 //! - \b SSI_ADV_MODE_BI_READ - The advanced mode of operation where data is
917 //!   read from the slave in Bi-SPI mode, with two bits of data read on every
918 //!   SSI clock.
919 //! - \b SSI_ADV_MODE_BI_WRITE - The advanced mode of operation where data is
920 //!   written to the slave in Bi-SPI mode, with two bits of data written on
921 //!   every SSI clock.
922 //! - \b SSI_ADV_MODE_QUAD_READ - The advanced mode of operation where data is
923 //!   read from the slave in Quad-SPI mode, with four bits of data read on
924 //!   every SSI clock.
925 //! - \b SSI_ADV_MODE_QUAD_WRITE - The advanced mode of operation where data is
926 //!   written to the slave in Quad-SPI mode, with four bits of data written on
927 //!   every SSI clock.
928 //!
929 //! The following mode transitions are valid (other transitions produce
930 //! undefined results):
931 //!
932 //! \verbatim
933 //! +----------+-------------------------------------------------------------+
934 //! |FROM      |                             TO                              |
935 //! |          |Legacy|Write|Read Write|Bi Read|Bi Write|Quad Read|Quad Write|
936 //! +----------+------+-----+----------+-------+--------+---------+----------+
937 //! |Legacy    | yes  | yes |   yes    |       |        |         |          |
938 //! |Write     | yes  | yes |   yes    |  yes  |  yes   |   yes   |   yes    |
939 //! |Read/Write| yes  | yes |   yes    |  yes  |  yes   |   yes   |   yes    |
940 //! |Bi Read   |      | yes |   yes    |  yes  |  yes   |         |          |
941 //! |Bi write  |      | yes |   yes    |  yes  |  yes   |         |          |
942 //! |Quad read |      | yes |   yes    |       |        |   yes   |   yes    |
943 //! |Quad write|      | yes |   yes    |       |        |   yes   |   yes    |
944 //! +----------+------+-----+----------+-------+--------+---------+----------+
945 //! \endverbatim
946 //!
947 //! When using an advanced mode of operation, the SSI module must have been
948 //! configured for eight data bits and the \b SSI_FRF_MOTO_MODE_0 protocol.
949 //! The advanced mode operation that is selected applies only to data newly
950 //! written into the FIFO; the data that is already present in the FIFO is
951 //! handled using the advanced mode of operation in effect when that data was
952 //! written.
953 //!
954 //! Switching into and out of legacy mode should only occur when the FIFO is
955 //! empty.
956 //!
957 //! \note The availability of the advanced mode of SSI operation varies with
958 //! the Tiva part and SSI in use.  Please consult the data sheet for the
959 //! part in use to determine whether this support is available.
960 //!
961 //! \return None.
962 //
963 //*****************************************************************************
964 void
SSIAdvModeSet(uint32_t ui32Base,uint32_t ui32Mode)965 SSIAdvModeSet(uint32_t ui32Base, uint32_t ui32Mode)
966 {
967     //
968     // Check the arguments.
969     //
970     ASSERT(_SSIBaseValid(ui32Base));
971     ASSERT((ui32Mode == SSI_ADV_MODE_LEGACY) ||
972            (ui32Mode == SSI_ADV_MODE_WRITE) ||
973            (ui32Mode == SSI_ADV_MODE_READ_WRITE) ||
974            (ui32Mode == SSI_ADV_MODE_BI_READ) ||
975            (ui32Mode == SSI_ADV_MODE_BI_WRITE) ||
976            (ui32Mode == SSI_ADV_MODE_QUAD_READ) ||
977            (ui32Mode == SSI_ADV_MODE_QUAD_WRITE));
978 
979     //
980     // Set the SSI mode of operation.
981     //
982     HWREG(ui32Base + SSI_O_CR1) =
983         ((HWREG(ui32Base + SSI_O_CR1) & ~(SSI_CR1_DIR | SSI_CR1_MODE_M)) |
984          ui32Mode);
985 }
986 
987 //*****************************************************************************
988 //
989 //! Puts a data element into the SSI transmit FIFO as the end of a frame.
990 //!
991 //! \param ui32Base specifies the SSI module base address.
992 //! \param ui32Data is the data to be transmitted over the SSI interface.
993 //!
994 //! This function places the supplied data into the transmit FIFO of the
995 //! specified SSI module, marking it as the end of a frame.  If there is no
996 //! space available in the transmit FIFO, this function waits until there is
997 //! space available before returning.  After this byte is transmitted by the
998 //! SSI module, the FSS signal de-asserts for at least one SSI clock.
999 //!
1000 //! \note The upper 24 bits of \e ui32Data are discarded by the hardware.
1001 //!
1002 //! \note The availability of the advanced mode of SSI operation varies with
1003 //! the Tiva part and SSI in use.  Please consult the data sheet for the
1004 //! part in use to determine whether this support is available.
1005 //!
1006 //! \return None.
1007 //
1008 //*****************************************************************************
1009 void
SSIAdvDataPutFrameEnd(uint32_t ui32Base,uint32_t ui32Data)1010 SSIAdvDataPutFrameEnd(uint32_t ui32Base, uint32_t ui32Data)
1011 {
1012     //
1013     // Check the arguments.
1014     //
1015     ASSERT(_SSIBaseValid(ui32Base));
1016     ASSERT((ui32Data & 0xffffff00) == 0);
1017 
1018     //
1019     // Wait until there is space.
1020     //
1021     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
1022     {
1023     }
1024 
1025     //
1026     // Write the data to the SSI.
1027     //
1028     HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_EOM;
1029     HWREG(ui32Base + SSI_O_DR) = ui32Data;
1030 }
1031 
1032 //*****************************************************************************
1033 //
1034 //! Puts a data element into the SSI transmit FIFO as the end of a frame.
1035 //!
1036 //! \param ui32Base specifies the SSI module base address.
1037 //! \param ui32Data is the data to be transmitted over the SSI interface.
1038 //!
1039 //! This function places the supplied data into the transmit FIFO of the
1040 //! specified SSI module, marking it as the end of a frame.  After this byte is
1041 //! transmitted by the SSI module, the FSS signal de-asserts for at least one
1042 //! SSI clock.  If there is no space in the FIFO, then this function returns a
1043 //! zero.
1044 //!
1045 //! \note The upper 24 bits of \e ui32Data are discarded by the hardware.
1046 //!
1047 //! \note The availability of the advanced mode of SSI operation varies with
1048 //! the Tiva part and SSI in use.  Please consult the data sheet for the
1049 //! part in use to determine whether this support is available.
1050 //!
1051 //! \return Returns the number of elements written to the SSI transmit FIFO.
1052 //
1053 //*****************************************************************************
1054 int32_t
SSIAdvDataPutFrameEndNonBlocking(uint32_t ui32Base,uint32_t ui32Data)1055 SSIAdvDataPutFrameEndNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
1056 {
1057     //
1058     // Check the arguments.
1059     //
1060     ASSERT(_SSIBaseValid(ui32Base));
1061     ASSERT((ui32Data & 0xffffff00) == 0);
1062 
1063     //
1064     // Check for space to write.
1065     //
1066     if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
1067     {
1068         HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_EOM;
1069         HWREG(ui32Base + SSI_O_DR) = ui32Data;
1070         return(1);
1071     }
1072     else
1073     {
1074         return(0);
1075     }
1076 }
1077 
1078 //*****************************************************************************
1079 //
1080 //! Configures the SSI advanced mode to hold the SSIFss signal during the full
1081 //! transfer.
1082 //!
1083 //! \param ui32Base is the base address of the SSI module.
1084 //!
1085 //! This function configures the SSI module to de-assert the SSIFss signal
1086 //! during the entire data transfer when using one of the advanced modes
1087 //! (instead of briefly de-asserting it after every byte).  When using this
1088 //! mode, SSIFss can be directly controlled via SSIAdvDataPutFrameEnd() and
1089 //! SSIAdvDataPutFrameEndNonBlocking().
1090 //!
1091 //! \note The availability of the advanced mode of SSI operation varies with
1092 //! the Tiva part and SSI in use.  Please consult the data sheet for the
1093 //! part in use to determine whether this support is available.
1094 //!
1095 //! \return None.
1096 //
1097 //*****************************************************************************
1098 void
SSIAdvFrameHoldEnable(uint32_t ui32Base)1099 SSIAdvFrameHoldEnable(uint32_t ui32Base)
1100 {
1101     //
1102     // Check the arguments.
1103     //
1104     ASSERT(_SSIBaseValid(ui32Base));
1105 
1106     //
1107     // Set the hold frame bit.
1108     //
1109     HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_FSSHLDFRM;
1110 }
1111 
1112 //*****************************************************************************
1113 //
1114 //! Configures the SSI advanced mode to de-assert the SSIFss signal after every
1115 //! byte transfer.
1116 //!
1117 //! \param ui32Base is the base address of the SSI module.
1118 //!
1119 //! This function configures the SSI module to de-assert the SSIFss signal
1120 //! for one SSI clock cycle after every byte is transferred using one of the
1121 //! advanced modes (instead of leaving it asserted for the entire transfer).
1122 //! This mode is the default operation.
1123 //!
1124 //! \note The availability of the advanced mode of SSI operation varies with
1125 //! the Tiva part and SSI in use.  Please consult the data sheet for the
1126 //! part in use to determine whether this support is available.
1127 //!
1128 //! \return None.
1129 //
1130 //*****************************************************************************
1131 void
SSIAdvFrameHoldDisable(uint32_t ui32Base)1132 SSIAdvFrameHoldDisable(uint32_t ui32Base)
1133 {
1134     //
1135     // Check the arguments.
1136     //
1137     ASSERT(_SSIBaseValid(ui32Base));
1138 
1139     //
1140     // Clear the hold frame bit.
1141     //
1142     HWREG(ui32Base + SSI_O_CR1) &= ~(SSI_CR1_FSSHLDFRM);
1143 }
1144 
1145 //*****************************************************************************
1146 //
1147 //! Enables the use of SSI Loopback mode.
1148 //!
1149 //! \param ui32Base is the base address of the SSI module.
1150 //!
1151 //! This function configures the SSI module to enter loopback mode.  When in
1152 //! loopback mode, the output of the transmit serial shift register is
1153 //! connected internally to the input of the receive serial shift register.
1154 //! This mode is useful for diagnostic/debug testing of the SSI module.
1155 //!
1156 //! \return None.
1157 //
1158 //*****************************************************************************
1159 void
SSILoopbackEnable(uint32_t ui32Base)1160 SSILoopbackEnable(uint32_t ui32Base)
1161 {
1162     //
1163     // Check the arguments.
1164     //
1165     ASSERT(_SSIBaseValid(ui32Base));
1166 
1167     //
1168     // Enable Loopback mode
1169     //
1170     HWREG(ui32Base + SSI_O_CR1) |= 1u;
1171 }
1172 
1173 //*****************************************************************************
1174 //
1175 //! Disables the use of SSI Loopback mode.
1176 //!
1177 //! \param ui32Base is the base address of the SSI module.
1178 //!
1179 //! This function restores the SSI module to be in normal serial port operation
1180 //! where the the input of the receive serial shift register is no longer
1181 //! connected internally to the output of the transmit serial shift register.
1182 //!
1183 //! \return None.
1184 //
1185 //*****************************************************************************
1186 void
SSILoopbackDisable(uint32_t ui32Base)1187 SSILoopbackDisable(uint32_t ui32Base)
1188 {
1189     //
1190     // Check the arguments.
1191     //
1192     ASSERT(_SSIBaseValid(ui32Base));
1193 
1194     //
1195     // Disable Loopback mode
1196     //
1197     HWREG(ui32Base + SSI_O_CR1) &= ~(1u);
1198 }
1199 
1200 //*****************************************************************************
1201 //
1202 // Close the Doxygen group.
1203 //! @}
1204 //
1205 //*****************************************************************************
1206