1 //*****************************************************************************
2 //
3 // ssi.c - Driver for Synchronous Serial Interface.
4 //
5 // Copyright (c) 2005-2012 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 9453 of the Stellaris Peripheral Driver Library.
37 //
38 //*****************************************************************************
39 
40 //*****************************************************************************
41 //
42 //! \addtogroup ssi_api
43 //! @{
44 //
45 //*****************************************************************************
46 
47 #include "inc/hw_ints.h"
48 #include "inc/hw_memmap.h"
49 #include "inc/hw_ssi.h"
50 #include "inc/hw_types.h"
51 #include "driverlib/debug.h"
52 #include "driverlib/interrupt.h"
53 #include "driverlib/ssi.h"
54 
55 //*****************************************************************************
56 //
57 // A mapping of timer base address to interupt number.
58 //
59 //*****************************************************************************
60 static const unsigned long g_ppulSSIIntMap[][2] =
61 {
62     { SSI0_BASE, INT_SSI0 },
63     { SSI1_BASE, INT_SSI1 },
64     { SSI2_BASE, INT_SSI2 },
65     { SSI3_BASE, INT_SSI3 },
66 };
67 
68 //*****************************************************************************
69 //
70 //! \internal
71 //! Checks an SSI base address.
72 //!
73 //! \param ulBase specifies the SSI module base address.
74 //!
75 //! This function determines if a SSI module base address is valid.
76 //!
77 //! \return Returns \b true if the base address is valid and \b false
78 //! otherwise.
79 //
80 //*****************************************************************************
81 #ifdef DEBUG
82 static tBoolean
SSIBaseValid(unsigned long ulBase)83 SSIBaseValid(unsigned long ulBase)
84 {
85     return((ulBase == SSI0_BASE) || (ulBase == SSI1_BASE) ||
86            (ulBase == SSI2_BASE) || (ulBase == SSI3_BASE));
87 }
88 #endif
89 
90 //*****************************************************************************
91 //
92 //! \internal
93 //! Gets the SSI interrupt number.
94 //!
95 //! \param ulBase specifies the SSI module base address.
96 //!
97 //! Given a SSI base address, returns the corresponding interrupt number.
98 //!
99 //! \return Returns an SSI interrupt number, or -1 if \e ulBase is invalid.
100 //
101 //*****************************************************************************
102 static long
SSIIntNumberGet(unsigned long ulBase)103 SSIIntNumberGet(unsigned long ulBase)
104 {
105     unsigned long ulIdx;
106 
107     //
108     // Loop through the table that maps SSI base addresses to interrupt
109     // numbers.
110     //
111     for(ulIdx = 0; ulIdx < (sizeof(g_ppulSSIIntMap) /
112                             sizeof(g_ppulSSIIntMap[0])); ulIdx++)
113     {
114         //
115         // See if this base address matches.
116         //
117         if(g_ppulSSIIntMap[ulIdx][0] == ulBase)
118         {
119             //
120             // Return the corresponding interrupt number.
121             //
122             return(g_ppulSSIIntMap[ulIdx][1]);
123         }
124     }
125 
126     //
127     // The base address could not be found, so return an error.
128     //
129     return(-1);
130 }
131 
132 //*****************************************************************************
133 //
134 //! Configures the synchronous serial interface.
135 //!
136 //! \param ulBase specifies the SSI module base address.
137 //! \param ulSSIClk is the rate of the clock supplied to the SSI module.
138 //! \param ulProtocol specifies the data transfer protocol.
139 //! \param ulMode specifies the mode of operation.
140 //! \param ulBitRate specifies the clock rate.
141 //! \param ulDataWidth specifies number of bits transferred per frame.
142 //!
143 //! This function configures the synchronous serial interface.  It sets
144 //! the SSI protocol, mode of operation, bit rate, and data width.
145 //!
146 //! The \e ulProtocol parameter defines the data frame format.  The
147 //! \e ulProtocol parameter can be one of the following values:
148 //! \b SSI_FRF_MOTO_MODE_0, \b SSI_FRF_MOTO_MODE_1, \b SSI_FRF_MOTO_MODE_2,
149 //! \b SSI_FRF_MOTO_MODE_3, \b SSI_FRF_TI, or \b SSI_FRF_NMW.  The Motorola
150 //! frame formats encode the following polarity and phase configurations:
151 //!
152 //! <pre>
153 //! Polarity Phase       Mode
154 //!   0       0   SSI_FRF_MOTO_MODE_0
155 //!   0       1   SSI_FRF_MOTO_MODE_1
156 //!   1       0   SSI_FRF_MOTO_MODE_2
157 //!   1       1   SSI_FRF_MOTO_MODE_3
158 //! </pre>
159 //!
160 //! The \e ulMode parameter defines the operating mode of the SSI module.  The
161 //! SSI module can operate as a master or slave; if it is a slave, the SSI can
162 //! be configured to disable output on its serial output line.  The \e ulMode
163 //! parameter can be one of the following values: \b SSI_MODE_MASTER,
164 //! \b SSI_MODE_SLAVE, or \b SSI_MODE_SLAVE_OD.
165 //!
166 //! The \e ulBitRate parameter defines the bit rate for the SSI.  This bit rate
167 //! must satisfy the following clock ratio criteria:
168 //!
169 //! - FSSI >= 2 * bit rate (master mode); this speed cannot exceed 25 MHz.
170 //! - FSSI >= 12 * bit rate or 6 * bit rate (slave modes), depending on the
171 //! capability of the specific microcontroller
172 //!
173 //! where FSSI is the frequency of the clock supplied to the SSI module.
174 //!
175 //! The \e ulDataWidth parameter defines the width of the data transfers and
176 //! can be a value between 4 and 16, inclusive.
177 //!
178 //! The peripheral clock is the same as the processor clock.  This value is
179 //! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is
180 //! constant and known (to save the code/execution overhead of a call to
181 //! SysCtlClockGet()).
182 //!
183 //! This function replaces the original SSIConfig() API and performs the same
184 //! actions.  A macro is provided in <tt>ssi.h</tt> to map the original API to
185 //! this API.
186 //!
187 //! \return None.
188 //
189 //*****************************************************************************
190 void
SSIConfigSetExpClk(unsigned long ulBase,unsigned long ulSSIClk,unsigned long ulProtocol,unsigned long ulMode,unsigned long ulBitRate,unsigned long ulDataWidth)191 SSIConfigSetExpClk(unsigned long ulBase, unsigned long ulSSIClk,
192                    unsigned long ulProtocol, unsigned long ulMode,
193                    unsigned long ulBitRate, unsigned long ulDataWidth)
194 {
195     unsigned long ulMaxBitRate;
196     unsigned long ulRegVal;
197     unsigned long ulPreDiv;
198     unsigned long ulSCR;
199     unsigned long ulSPH_SPO;
200 
201     //
202     // Check the arguments.
203     //
204     ASSERT(SSIBaseValid(ulBase));
205     ASSERT((ulProtocol == SSI_FRF_MOTO_MODE_0) ||
206            (ulProtocol == SSI_FRF_MOTO_MODE_1) ||
207            (ulProtocol == SSI_FRF_MOTO_MODE_2) ||
208            (ulProtocol == SSI_FRF_MOTO_MODE_3) ||
209            (ulProtocol == SSI_FRF_TI) ||
210            (ulProtocol == SSI_FRF_NMW));
211     ASSERT((ulMode == SSI_MODE_MASTER) ||
212            (ulMode == SSI_MODE_SLAVE) ||
213            (ulMode == SSI_MODE_SLAVE_OD));
214     ASSERT(((ulMode == SSI_MODE_MASTER) && (ulBitRate <= (ulSSIClk / 2))) ||
215            ((ulMode != SSI_MODE_MASTER) && (ulBitRate <= (ulSSIClk / 12))));
216     ASSERT((ulSSIClk / ulBitRate) <= (254 * 256));
217     ASSERT((ulDataWidth >= 4) && (ulDataWidth <= 16));
218 
219     //
220     // Set the mode.
221     //
222     ulRegVal = (ulMode == SSI_MODE_SLAVE_OD) ? SSI_CR1_SOD : 0;
223     ulRegVal |= (ulMode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
224     HWREG(ulBase + SSI_O_CR1) = ulRegVal;
225 
226     //
227     // Set the clock predivider.
228     //
229     ulMaxBitRate = ulSSIClk / ulBitRate;
230     ulPreDiv = 0;
231     do
232     {
233         ulPreDiv += 2;
234         ulSCR = (ulMaxBitRate / ulPreDiv) - 1;
235     }
236     while(ulSCR > 255);
237     HWREG(ulBase + SSI_O_CPSR) = ulPreDiv;
238 
239     //
240     // Set protocol and clock rate.
241     //
242     ulSPH_SPO = (ulProtocol & 3) << 6;
243     ulProtocol &= SSI_CR0_FRF_M;
244     ulRegVal = (ulSCR << 8) | ulSPH_SPO | ulProtocol | (ulDataWidth - 1);
245     HWREG(ulBase + SSI_O_CR0) = ulRegVal;
246 }
247 
248 //*****************************************************************************
249 //
250 //! Enables the synchronous serial interface.
251 //!
252 //! \param ulBase specifies the SSI module base address.
253 //!
254 //! This function enables operation of the synchronous serial interface.  The
255 //! synchronous serial interface must be configured before it is enabled.
256 //!
257 //! \return None.
258 //
259 //*****************************************************************************
260 void
SSIEnable(unsigned long ulBase)261 SSIEnable(unsigned long ulBase)
262 {
263     //
264     // Check the arguments.
265     //
266     ASSERT(SSIBaseValid(ulBase));
267 
268     //
269     // Read-modify-write the enable bit.
270     //
271     HWREG(ulBase + SSI_O_CR1) |= SSI_CR1_SSE;
272 }
273 
274 //*****************************************************************************
275 //
276 //! Disables the synchronous serial interface.
277 //!
278 //! \param ulBase specifies the SSI module base address.
279 //!
280 //! This function disables operation of the synchronous serial interface.
281 //!
282 //! \return None.
283 //
284 //*****************************************************************************
285 void
SSIDisable(unsigned long ulBase)286 SSIDisable(unsigned long ulBase)
287 {
288     //
289     // Check the arguments.
290     //
291     ASSERT(SSIBaseValid(ulBase));
292 
293     //
294     // Read-modify-write the enable bit.
295     //
296     HWREG(ulBase + SSI_O_CR1) &= ~(SSI_CR1_SSE);
297 }
298 
299 //*****************************************************************************
300 //
301 //! Registers an interrupt handler for the synchronous serial interface.
302 //!
303 //! \param ulBase specifies the SSI module base address.
304 //! \param pfnHandler is a pointer to the function to be called when the
305 //! synchronous serial interface interrupt occurs.
306 //!
307 //! This function registers the handler to be called when an SSI interrupt
308 //! occurs.  This function enables the global interrupt in the interrupt
309 //! controller; specific SSI interrupts must be enabled via SSIIntEnable().  If
310 //! necessary, it is the interrupt handler's responsibility to clear the
311 //! interrupt source via SSIIntClear().
312 //!
313 //! \sa IntRegister() for important information about registering interrupt
314 //! handlers.
315 //!
316 //! \return None.
317 //
318 //*****************************************************************************
319 void
SSIIntRegister(unsigned long ulBase,void (* pfnHandler)(void))320 SSIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
321 {
322     unsigned long ulInt;
323 
324     //
325     // Check the arguments.
326     //
327     ASSERT(SSIBaseValid(ulBase));
328 
329     //
330     // Determine the interrupt number based on the SSI port.
331     //
332     ulInt = SSIIntNumberGet(ulBase);
333 
334     //
335     // Register the interrupt handler, returning an error if an error occurs.
336     //
337     IntRegister(ulInt, pfnHandler);
338 
339     //
340     // Enable the synchronous serial interface interrupt.
341     //
342     IntEnable(ulInt);
343 }
344 
345 //*****************************************************************************
346 //
347 //! Unregisters an interrupt handler for the synchronous serial interface.
348 //!
349 //! \param ulBase specifies the SSI module base address.
350 //!
351 //! This function clears the handler to be called when an SSI interrupt
352 //! occurs.  This function also masks off the interrupt in the interrupt
353 //! controller so that the interrupt handler no longer is called.
354 //!
355 //! \sa IntRegister() for important information about registering interrupt
356 //! handlers.
357 //!
358 //! \return None.
359 //
360 //*****************************************************************************
361 void
SSIIntUnregister(unsigned long ulBase)362 SSIIntUnregister(unsigned long ulBase)
363 {
364     unsigned long ulInt;
365 
366     //
367     // Check the arguments.
368     //
369     ASSERT(SSIBaseValid(ulBase));
370 
371     //
372     // Determine the interrupt number based on the SSI port.
373     //
374     ulInt = SSIIntNumberGet(ulBase);
375 
376     //
377     // Disable the interrupt.
378     //
379     IntDisable(ulInt);
380 
381     //
382     // Unregister the interrupt handler.
383     //
384     IntUnregister(ulInt);
385 }
386 
387 //*****************************************************************************
388 //
389 //! Enables individual SSI interrupt sources.
390 //!
391 //! \param ulBase specifies the SSI module base address.
392 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
393 //!
394 //! This function enables the indicated SSI interrupt sources.  Only the
395 //! sources that are enabled can be reflected to the processor interrupt;
396 //! disabled sources have no effect on the processor.  The \e ulIntFlags
397 //! parameter can be any of the \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, or
398 //! \b SSI_RXOR values.
399 //!
400 //! \return None.
401 //
402 //*****************************************************************************
403 void
SSIIntEnable(unsigned long ulBase,unsigned long ulIntFlags)404 SSIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
405 {
406     //
407     // Check the arguments.
408     //
409     ASSERT(SSIBaseValid(ulBase));
410 
411     //
412     // Enable the specified interrupts.
413     //
414     HWREG(ulBase + SSI_O_IM) |= ulIntFlags;
415 }
416 
417 //*****************************************************************************
418 //
419 //! Disables individual SSI interrupt sources.
420 //!
421 //! \param ulBase specifies the SSI module base address.
422 //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
423 //!
424 //! This function disables the indicated SSI interrupt sources.  The
425 //! \e ulIntFlags parameter can be any of the \b SSI_TXFF, \b SSI_RXFF,
426 //!  \b SSI_RXTO, or \b SSI_RXOR values.
427 //!
428 //! \return None.
429 //
430 //*****************************************************************************
431 void
SSIIntDisable(unsigned long ulBase,unsigned long ulIntFlags)432 SSIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
433 {
434     //
435     // Check the arguments.
436     //
437     ASSERT(SSIBaseValid(ulBase));
438 
439     //
440     // Disable the specified interrupts.
441     //
442     HWREG(ulBase + SSI_O_IM) &= ~(ulIntFlags);
443 }
444 
445 //*****************************************************************************
446 //
447 //! Gets the current interrupt status.
448 //!
449 //! \param ulBase specifies the SSI module base address.
450 //! \param bMasked is \b false if the raw interrupt status is required or
451 //! \b true if the masked interrupt status is required.
452 //!
453 //! This function returns the interrupt status for the SSI module.  Either the
454 //! raw interrupt status or the status of interrupts that are allowed to
455 //! reflect to the processor can be returned.
456 //!
457 //! \return The current interrupt status, enumerated as a bit field of
458 //! \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, and \b SSI_RXOR.
459 //
460 //*****************************************************************************
461 unsigned long
SSIIntStatus(unsigned long ulBase,tBoolean bMasked)462 SSIIntStatus(unsigned long ulBase, tBoolean bMasked)
463 {
464     //
465     // Check the arguments.
466     //
467     ASSERT(SSIBaseValid(ulBase));
468 
469     //
470     // Return either the interrupt status or the raw interrupt status as
471     // requested.
472     //
473     if(bMasked)
474     {
475         return(HWREG(ulBase + SSI_O_MIS));
476     }
477     else
478     {
479         return(HWREG(ulBase + SSI_O_RIS));
480     }
481 }
482 
483 //*****************************************************************************
484 //
485 //! Clears SSI interrupt sources.
486 //!
487 //! \param ulBase specifies the SSI module base address.
488 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
489 //!
490 //! This function clears the specified SSI interrupt sources so that they no
491 //! longer assert.  This function must be called in the interrupt handler to
492 //! keep the interrupts from being triggered again immediately upon exit.  The
493 //! \e ulIntFlags parameter can consist of either or both the \b SSI_RXTO and
494 //! \b SSI_RXOR values.
495 //!
496 //! \note Because there is a write buffer in the Cortex-M processor, it may
497 //! take several clock cycles before the interrupt source is actually cleared.
498 //! Therefore, it is recommended that the interrupt source be cleared early in
499 //! the interrupt handler (as opposed to the very last action) to avoid
500 //! returning from the interrupt handler before the interrupt source is
501 //! actually cleared.  Failure to do so may result in the interrupt handler
502 //! being immediately reentered (because the interrupt controller still sees
503 //! the interrupt source asserted).
504 //!
505 //! \return None.
506 //
507 //*****************************************************************************
508 void
SSIIntClear(unsigned long ulBase,unsigned long ulIntFlags)509 SSIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
510 {
511     //
512     // Check the arguments.
513     //
514     ASSERT(SSIBaseValid(ulBase));
515 
516     //
517     // Clear the requested interrupt sources.
518     //
519     HWREG(ulBase + SSI_O_ICR) = ulIntFlags;
520 }
521 
522 //*****************************************************************************
523 //
524 //! Puts a data element into the SSI transmit FIFO.
525 //!
526 //! \param ulBase specifies the SSI module base address.
527 //! \param ulData is the data to be transmitted over the SSI interface.
528 //!
529 //! This function places the supplied data into the transmit FIFO of the
530 //! specified SSI module.  If there is no space available in the transmit FIFO,
531 //! this function waits until there is space available before returning.
532 //!
533 //! \note The upper 32 - N bits of \e ulData are discarded by the hardware,
534 //! where N is the data width as configured by SSIConfigSetExpClk().  For
535 //! example, if the interface is configured for 8-bit data width, the upper 24
536 //! bits of \e ulData are discarded.
537 //!
538 //! \return None.
539 //
540 //*****************************************************************************
541 void
SSIDataPut(unsigned long ulBase,unsigned long ulData)542 SSIDataPut(unsigned long ulBase, unsigned long ulData)
543 {
544     //
545     // Check the arguments.
546     //
547     ASSERT(SSIBaseValid(ulBase));
548     ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
549                                      SSI_CR0_DSS_M))) == 0);
550 
551     //
552     // Wait until there is space.
553     //
554     while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF))
555     {
556     }
557 
558     //
559     // Write the data to the SSI.
560     //
561     HWREG(ulBase + SSI_O_DR) = ulData;
562 }
563 
564 //*****************************************************************************
565 //
566 //! Puts a data element into the SSI transmit FIFO.
567 //!
568 //! \param ulBase specifies the SSI module base address.
569 //! \param ulData is the data to be transmitted over the SSI interface.
570 //!
571 //! This function places the supplied data into the transmit FIFO of the
572 //! specified SSI module.  If there is no space in the FIFO, then this function
573 //! returns a zero.
574 //!
575 //! This function replaces the original SSIDataNonBlockingPut() API and
576 //! performs the same actions.  A macro is provided in <tt>ssi.h</tt> to map
577 //! the original API to this API.
578 //!
579 //! \note The upper 32 - N bits of \e ulData are discarded by the hardware,
580 //! where N is the data width as configured by SSIConfigSetExpClk().  For
581 //! example, if the interface is configured for 8-bit data width, the upper 24
582 //! bits of \e ulData are discarded.
583 //!
584 //! \return Returns the number of elements written to the SSI transmit FIFO.
585 //
586 //*****************************************************************************
587 long
SSIDataPutNonBlocking(unsigned long ulBase,unsigned long ulData)588 SSIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData)
589 {
590     //
591     // Check the arguments.
592     //
593     ASSERT(SSIBaseValid(ulBase));
594     ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
595                                      SSI_CR0_DSS_M))) == 0);
596 
597     //
598     // Check for space to write.
599     //
600     if(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF)
601     {
602         HWREG(ulBase + SSI_O_DR) = ulData;
603         return(1);
604     }
605     else
606     {
607         return(0);
608     }
609 }
610 
611 //*****************************************************************************
612 //
613 //! Gets a data element from the SSI receive FIFO.
614 //!
615 //! \param ulBase specifies the SSI module base address.
616 //! \param pulData is a pointer to a storage location for data that was
617 //! received over the SSI interface.
618 //!
619 //! This function gets received data from the receive FIFO of the specified
620 //! SSI module and places that data into the location specified by the
621 //! \e pulData parameter.  If there is no data available, this function waits
622 //! until data is received before returning.
623 //!
624 //! \note Only the lower N bits of the value written to \e pulData contain
625 //! valid data, where N is the data width as configured by
626 //! SSIConfigSetExpClk().  For example, if the interface is configured for
627 //! 8-bit data width, only the lower 8 bits of the value written to \e pulData
628 //! contain valid data.
629 //!
630 //! \return None.
631 //
632 //*****************************************************************************
633 void
SSIDataGet(unsigned long ulBase,unsigned long * pulData)634 SSIDataGet(unsigned long ulBase, unsigned long *pulData)
635 {
636     //
637     // Check the arguments.
638     //
639     ASSERT(SSIBaseValid(ulBase));
640 
641     //
642     // Wait until there is data to be read.
643     //
644     while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE))
645     {
646     }
647 
648     //
649     // Read data from SSI.
650     //
651     *pulData = HWREG(ulBase + SSI_O_DR);
652 }
653 
654 //*****************************************************************************
655 //
656 //! Gets a data element from the SSI receive FIFO.
657 //!
658 //! \param ulBase specifies the SSI module base address.
659 //! \param pulData is a pointer to a storage location for data that was
660 //! received over the SSI interface.
661 //!
662 //! This function gets received data from the receive FIFO of the specified SSI
663 //! module and places that data into the location specified by the \e ulData
664 //! parameter.  If there is no data in the FIFO, then this function returns a
665 //! zero.
666 //!
667 //! This function replaces the original SSIDataNonBlockingGet() API and
668 //! performs the same actions.  A macro is provided in <tt>ssi.h</tt> to map
669 //! the original API to this API.
670 //!
671 //! \note Only the lower N bits of the value written to \e pulData contain
672 //! valid data, where N is the data width as configured by
673 //! SSIConfigSetExpClk().  For example, if the interface is configured for
674 //! 8-bit data width, only the lower 8 bits of the value written to \e pulData
675 //! contain valid data.
676 //!
677 //! \return Returns the number of elements read from the SSI receive FIFO.
678 //
679 //*****************************************************************************
680 long
SSIDataGetNonBlocking(unsigned long ulBase,unsigned long * pulData)681 SSIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)
682 {
683     //
684     // Check the arguments.
685     //
686     ASSERT(SSIBaseValid(ulBase));
687 
688     //
689     // Check for data to read.
690     //
691     if(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE)
692     {
693         *pulData = HWREG(ulBase + SSI_O_DR);
694         return(1);
695     }
696     else
697     {
698         return(0);
699     }
700 }
701 
702 //*****************************************************************************
703 //
704 //! Enables SSI DMA operation.
705 //!
706 //! \param ulBase is the base address of the SSI port.
707 //! \param ulDMAFlags is a bit mask of the DMA features to enable.
708 //!
709 //! This function enables the specified SSI DMA features.  The SSI can be
710 //! configured to use DMA for transmit and/or receive data transfers.
711 //! The \e ulDMAFlags parameter is the logical OR of any of the following
712 //! values:
713 //!
714 //! - SSI_DMA_RX - enable DMA for receive
715 //! - SSI_DMA_TX - enable DMA for transmit
716 //!
717 //! \note The uDMA controller must also be set up before DMA can be used
718 //! with the SSI.
719 //!
720 //! \return None.
721 //
722 //*****************************************************************************
723 void
SSIDMAEnable(unsigned long ulBase,unsigned long ulDMAFlags)724 SSIDMAEnable(unsigned long ulBase, unsigned long ulDMAFlags)
725 {
726     //
727     // Check the arguments.
728     //
729     ASSERT(SSIBaseValid(ulBase));
730 
731     //
732     // Set the requested bits in the SSI DMA control register.
733     //
734     HWREG(ulBase + SSI_O_DMACTL) |= ulDMAFlags;
735 }
736 
737 //*****************************************************************************
738 //
739 //! Disables SSI DMA operation.
740 //!
741 //! \param ulBase is the base address of the SSI port.
742 //! \param ulDMAFlags is a bit mask of the DMA features to disable.
743 //!
744 //! This function is used to disable SSI DMA features that were enabled
745 //! by SSIDMAEnable().  The specified SSI DMA features are disabled.  The
746 //! \e ulDMAFlags parameter is the logical OR of any of the following values:
747 //!
748 //! - SSI_DMA_RX - disable DMA for receive
749 //! - SSI_DMA_TX - disable DMA for transmit
750 //!
751 //! \return None.
752 //
753 //*****************************************************************************
754 void
SSIDMADisable(unsigned long ulBase,unsigned long ulDMAFlags)755 SSIDMADisable(unsigned long ulBase, unsigned long ulDMAFlags)
756 {
757     //
758     // Check the arguments.
759     //
760     ASSERT(SSIBaseValid(ulBase));
761 
762     //
763     // Clear the requested bits in the SSI DMA control register.
764     //
765     HWREG(ulBase + SSI_O_DMACTL) &= ~ulDMAFlags;
766 }
767 
768 //*****************************************************************************
769 //
770 //! Determines whether the SSI transmitter is busy or not.
771 //!
772 //! \param ulBase is the base address of the SSI port.
773 //!
774 //! This function allows the caller to determine whether all transmitted bytes
775 //! have cleared the transmitter hardware.  If \b false is returned, then the
776 //! transmit FIFO is empty and all bits of the last transmitted word have left
777 //! the hardware shift register.
778 //!
779 //! \return Returns \b true if the SSI is transmitting or \b false if all
780 //! transmissions are complete.
781 //
782 //*****************************************************************************
783 tBoolean
SSIBusy(unsigned long ulBase)784 SSIBusy(unsigned long ulBase)
785 {
786     //
787     // Check the arguments.
788     //
789     ASSERT(SSIBaseValid(ulBase));
790 
791     //
792     // Determine if the SSI is busy.
793     //
794     return((HWREG(ulBase + SSI_O_SR) & SSI_SR_BSY) ? true : false);
795 }
796 
797 //*****************************************************************************
798 //
799 //! Sets the data clock source for the specified SSI peripheral.
800 //!
801 //! \param ulBase is the base address of the SSI port.
802 //! \param ulSource is the baud clock source for the SSI.
803 //!
804 //! This function allows the baud clock source for the SSI to be selected.
805 //! The possible clock source are the system clock (\b SSI_CLOCK_SYSTEM) or
806 //! the precision internal oscillator (\b SSI_CLOCK_PIOSC).
807 //!
808 //! Changing the baud clock source changes the data rate generated by the
809 //! SSI.  Therefore, the data rate should be reconfigured after any change to
810 //! the SSI clock source.
811 //!
812 //! \note The ability to specify the SSI baud clock source varies with the
813 //! Stellaris part and SSI in use.  Please consult the data sheet for the part
814 //! in use to determine whether this support is available.
815 //!
816 //! \return None.
817 //
818 //*****************************************************************************
819 void
SSIClockSourceSet(unsigned long ulBase,unsigned long ulSource)820 SSIClockSourceSet(unsigned long ulBase, unsigned long ulSource)
821 {
822     //
823     // Check the arguments.
824     //
825     ASSERT(SSIBaseValid(ulBase));
826     ASSERT((ulSource == SSI_CLOCK_SYSTEM) || (ulSource == SSI_CLOCK_PIOSC));
827 
828     //
829     // Set the SSI clock source.
830     //
831     HWREG(ulBase + SSI_O_CC) = ulSource;
832 }
833 
834 //*****************************************************************************
835 //
836 //! Gets the data clock source for the specified SSI peripheral.
837 //!
838 //! \param ulBase is the base address of the SSI port.
839 //!
840 //! This function returns the data clock source for the specified SSI.  The
841 //! possible data clock source are the system clock (\b SSI_CLOCK_SYSTEM) or
842 //! the precision internal oscillator (\b SSI_CLOCK_PIOSC).
843 //!
844 //! \note The ability to specify the SSI data clock source varies with the
845 //! Stellaris part and SSI in use.  Please consult the data sheet for the part
846 //! in use to determine whether this support is available.
847 //!
848 //! \return None.
849 //
850 //*****************************************************************************
851 unsigned long
SSIClockSourceGet(unsigned long ulBase)852 SSIClockSourceGet(unsigned long ulBase)
853 {
854     //
855     // Check the arguments.
856     //
857     ASSERT(SSIBaseValid(ulBase));
858 
859     //
860     // Return the SSI clock source.
861     //
862     return(HWREG(ulBase + SSI_O_CC));
863 }
864 
865 //*****************************************************************************
866 //
867 // Close the Doxygen group.
868 //! @}
869 //
870 //*****************************************************************************
871