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