1 //*****************************************************************************
3 // ssi.c - Driver for Synchronous Serial Interface.
5 // Copyright (c) 2005,2006 Luminary Micro, Inc. All rights reserved.
7 // Software License Agreement
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10 // exclusively on LMI's Stellaris Family of microcontroller products.
12 // The software is owned by LMI and/or its suppliers, and is protected under
13 // applicable copyright laws. All rights are reserved. Any use in violation
14 // of the foregoing restrictions may subject the user to criminal sanctions
15 // under applicable laws, as well as to civil liability for the breach of the
16 // terms and conditions of this license.
18 // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
24 // This is part of revision 991 of the Stellaris Driver Library.
26 //*****************************************************************************
28 //*****************************************************************************
30 //! \addtogroup ssi_api
33 //*****************************************************************************
35 #include "../hw_ints.h"
36 #include "../hw_memmap.h"
37 #include "../hw_ssi.h"
38 #include "../hw_types.h"
40 #include "interrupt.h"
44 //*****************************************************************************
46 //! Configures the synchronous serial interface.
48 //! \param ulBase specifies the SSI module base address.
49 //! \param ulProtocol specifies the data transfer protocol.
50 //! \param ulMode specifies the mode of operation.
51 //! \param ulBitRate specifies the clock rate.
52 //! \param ulDataWidth specifies number of bits transfered per frame.
54 //! This function configures the synchronous serial interface. It sets
55 //! the SSI protocol, mode of operation, bit rate, and data width.
57 //! The parameter \e ulProtocol defines the data frame format. The parameter
58 //! \e ulProtocol can be one of the following values: SSI_FRF_MOTO_MODE_0,
59 //! SSI_FRF_MOTO_MODE_1, SSI_FRF_MOTO_MODE_2, SSI_FRF_MOTO_MODE_3,
60 //! SSI_FRF_TI, or SSI_FRF_NMW. The Motorola frame formats imply the
61 //! following polarity and phase configurations:
63 //! Polarity Phase Mode
64 //! 0 0 SSI_FRF_MOTO_MODE_0
65 //! 0 1 SSI_FRF_MOTO_MODE_1
66 //! 1 0 SSI_FRF_MOTO_MODE_2
67 //! 1 1 SSI_FRF_MOTO_MODE_3
70 //! The parameter \e ulMode defines the operating mode of the SSI module. The
71 //! SSI module can operate as a master or slave; if a slave, the SSI can be
72 //! configured to disable output on its serial output line. The parameter
73 //! \e ulMode can be one of the following values: SSI_MODE_MASTER,
74 //! SSI_MODE_SLAVE, or SSI_MODE_SLAVE_OD.
76 //! The parameter \e ulBitRate defines the bit rate for the SSI. This bit rate
77 //! must satisfy the following clock ratio criteria:
78 //! - FSSI >= 2 * bit rate (master mode)
79 //! - FSSI >= 12 * bit rate (slave modes)
81 //! where FSSI is the frequency of the clock supplied to the SSI module.
83 //! The parameter \e ulDataWidth defines the width of the data transfers.
84 //! The parameter \e ulDataWidth can be a value between 4 and 16, inclusive.
86 //! The SSI clocking is dependent upon the system clock rate returned by
87 //! SysCtlClockGet(); if it does not return the correct system clock rate then
88 //! the SSI clock rate will be incorrect.
92 //*****************************************************************************
93 #if defined(GROUP_config) || defined(BUILD_ALL) || defined(DOXYGEN)
95 SSIConfig(unsigned long ulBase, unsigned long ulProtocol, unsigned long ulMode,
96 unsigned long ulBitRate, unsigned long ulDataWidth)
98 unsigned long ulMaxBitRate;
99 unsigned long ulRegVal;
100 unsigned long ulPreDiv;
102 unsigned long ulSPH_SPO;
103 unsigned long ulClock;
106 // Check the arguments.
108 ASSERT(ulBase == SSI_BASE);
109 ASSERT((ulProtocol == SSI_FRF_MOTO_MODE_0) ||
110 (ulProtocol == SSI_FRF_MOTO_MODE_1) ||
111 (ulProtocol == SSI_FRF_MOTO_MODE_2) ||
112 (ulProtocol == SSI_FRF_MOTO_MODE_3) ||
113 (ulProtocol == SSI_FRF_TI) ||
114 (ulProtocol == SSI_FRF_NMW));
115 ASSERT((ulMode == SSI_MODE_MASTER) ||
116 (ulMode == SSI_MODE_SLAVE) ||
117 (ulMode == SSI_MODE_SLAVE_OD));
118 ASSERT((ulDataWidth >= 4) && (ulDataWidth <= 16));
121 // Get the processor clock rate.
123 ulClock = SysCtlClockGet();
126 // Validate the clock speed.
128 ASSERT(((ulMode == SSI_MODE_MASTER) && (ulBitRate <= (ulClock / 2))) ||
129 ((ulMode != SSI_MODE_MASTER) && (ulBitRate <= (ulClock / 12))));
130 ASSERT((ulClock / ulBitRate) <= (254 * 256));
135 ulRegVal = (ulMode == SSI_MODE_SLAVE_OD) ? SSI_CR1_SOD : 0;
136 ulRegVal |= (ulMode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
137 HWREG(ulBase + SSI_O_CR1) = ulRegVal;
140 // Set the clock predivider.
142 ulMaxBitRate = ulClock / ulBitRate;
147 ulSCR = (ulMaxBitRate / ulPreDiv) - 1;
150 HWREG(ulBase + SSI_O_CPSR) = ulPreDiv;
153 // Set protocol and clock rate.
155 ulSPH_SPO = ulProtocol << 6;
156 ulProtocol &= SSI_CR0_FRF_MASK;
157 ulRegVal = (ulSCR << 8) | ulSPH_SPO | ulProtocol | (ulDataWidth - 1);
158 HWREG(ulBase + SSI_O_CR0) = ulRegVal;
162 //*****************************************************************************
164 //! Enables the synchronous serial interface.
166 //! \param ulBase specifies the SSI module base address.
168 //! This will enable operation of the synchronous serial interface. It must be
169 //! configured before it is enabled.
173 //*****************************************************************************
174 #if defined(GROUP_enable) || defined(BUILD_ALL) || defined(DOXYGEN)
176 SSIEnable(unsigned long ulBase)
179 // Check the arguments.
181 ASSERT(ulBase == SSI_BASE);
184 // Read-modify-write the enable bit.
186 HWREG(ulBase + SSI_O_CR1) |= SSI_CR1_SSE;
190 //*****************************************************************************
192 //! Disables the synchronous serial interface.
194 //! \param ulBase specifies the SSI module base address.
196 //! This will disable operation of the synchronous serial interface.
200 //*****************************************************************************
201 #if defined(GROUP_disable) || defined(BUILD_ALL) || defined(DOXYGEN)
203 SSIDisable(unsigned long ulBase)
206 // Check the arguments.
208 ASSERT(ulBase == SSI_BASE);
211 // Read-modify-write the enable bit.
213 HWREG(ulBase + SSI_O_CR1) &= ~(SSI_CR1_SSE);
217 //*****************************************************************************
219 //! Registers an interrupt handler for the synchronous serial interface.
221 //! \param ulBase specifies the SSI module base address.
222 //! \param pfnHandler is a pointer to the function to be called when the
223 //! synchronous serial interface interrupt occurs.
225 //! This sets the handler to be called when an SSI interrupt
226 //! occurs. This will enable the global interrupt in the interrupt controller;
227 //! specific SSI interrupts must be enabled via SSIIntEnable(). If necessary,
228 //! it is the interrupt handler's responsibility to clear the interrupt source
229 //! via SSIIntClear().
231 //! \sa IntRegister() for important information about registering interrupt
236 //*****************************************************************************
237 #if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN)
239 SSIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
242 // Check the arguments.
244 ASSERT(ulBase == SSI_BASE);
247 // Register the interrupt handler, returning an error if an error occurs.
249 IntRegister(INT_SSI, pfnHandler);
252 // Enable the synchronous serial interface interrupt.
258 //*****************************************************************************
260 //! Unregisters an interrupt handler for the synchronous serial interface.
262 //! \param ulBase specifies the SSI module base address.
264 //! This function will clear the handler to be called when a SSI
265 //! interrupt occurs. This will also mask off the interrupt in the interrupt
266 //! controller so that the interrupt handler no longer is called.
268 //! \sa IntRegister() for important information about registering interrupt
273 //*****************************************************************************
274 #if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN)
276 SSIIntUnregister(unsigned long ulBase)
279 // Check the arguments.
281 ASSERT(ulBase == SSI_BASE);
284 // Disable the interrupt.
289 // Unregister the interrupt handler.
291 IntUnregister(INT_SSI);
295 //*****************************************************************************
297 //! Enables individual SSI interrupt sources.
299 //! \param ulBase specifies the SSI module base address.
300 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
302 //! Enables the indicated SSI interrupt sources. Only the sources that are
303 //! enabled can be reflected to the processor interrupt; disabled sources
304 //! have no effect on the processor. The parameter \e ulIntFlags Can be
305 //! any of the SSI_TXFF, SSI_RXFF, SSI_RXTO, or SSI_RXOR values.
309 //*****************************************************************************
310 #if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN)
312 SSIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
315 // Check the arguments.
317 ASSERT(ulBase == SSI_BASE);
320 // Enable the specified interrupts.
322 HWREG(ulBase + SSI_O_IM) |= ulIntFlags;
326 //*****************************************************************************
328 //! Disables individual SSI interrupt sources.
330 //! \param ulBase specifies the SSI module base address.
331 //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
333 //! Disables the indicated SSI interrupt sources. The parameter
334 //! \e ulIntFlags Can be any of the SSI_TXFF, SSI_RXFF, SSI_RXTO,
335 //! or SSI_RXOR values.
339 //*****************************************************************************
340 #if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN)
342 SSIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
345 // Check the arguments.
347 ASSERT(ulBase == SSI_BASE);
350 // Disable the specified interrupts.
352 HWREG(ulBase + SSI_O_IM) &= ~(ulIntFlags);
356 //*****************************************************************************
358 //! Gets the current interrupt status.
360 //! \param ulBase specifies the SSI module base address.
361 //! \param bMasked is false if the raw interrupt status is required and
362 //! true if the masked interrupt status is required.
364 //! This returns the interrupt status for the SSI module.
365 //! Either the raw interrupt status or the status of interrupts that are
366 //! allowed to reflect to the processor can be returned.
368 //! \return The current interrupt status, enumerated as a bit field of
369 //! SSI_TXFF, SSI_RXFF, SSI_RXTO, and SSI_RXOR.
371 //*****************************************************************************
372 #if defined(GROUP_intstatus) || defined(BUILD_ALL) || defined(DOXYGEN)
374 SSIIntStatus(unsigned long ulBase, tBoolean bMasked)
377 // Check the arguments.
379 ASSERT(ulBase == SSI_BASE);
382 // Return either the interrupt status or the raw interrupt status as
387 return(HWREG(ulBase + SSI_O_MIS));
391 return(HWREG(ulBase + SSI_O_RIS));
396 //*****************************************************************************
398 //! Clears SSI interrupt sources.
400 //! \param ulBase specifies the SSI module base address.
401 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
403 //! The specified SSI interrupt sources are cleared, so that
404 //! they no longer assert. This must be done in the interrupt handler to
405 //! keep it from being called again immediately upon exit.
406 //! The parameter \e ulIntFlags can consist of either or both the SSI_RXTO
407 //! and SSI_RXOR values.
411 //*****************************************************************************
412 #if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN)
414 SSIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
417 // Check the arguments.
419 ASSERT(ulBase == SSI_BASE);
422 // Clear the requested interrupt sources.
424 HWREG(ulBase + SSI_O_ICR) = ulIntFlags;
428 //*****************************************************************************
430 //! Puts a data element into the SSI transmit FIFO.
432 //! \param ulBase specifies the SSI module base address.
433 //! \param ulData data to be transmitted over the SSI interface.
435 //! This function will place the supplied data into the transmit FIFO of
436 //! the specified SSI module.
438 //! \note The upper 32 - N bits of the \e ulData will be discarded by the
439 //! hardware, where N is the data width as configured by SSIConfig(). For
440 //! example, if the interface is configured for 8 bit data width, the upper 24
441 //! bits of \e ulData will be discarded.
445 //*****************************************************************************
446 #if defined(GROUP_dataput) || defined(BUILD_ALL) || defined(DOXYGEN)
448 SSIDataPut(unsigned long ulBase, unsigned long ulData)
451 // Check the arguments.
453 ASSERT(ulBase == SSI_BASE);
454 ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
455 SSI_CR0_DSS))) == 0);
458 // Wait until there is space.
460 while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF))
465 // Write the data to the SSI.
467 HWREG(ulBase + SSI_O_DR) = ulData;
471 //*****************************************************************************
473 //! Puts a data element into the SSI transmit FIFO.
475 //! \param ulBase specifies the SSI module base address.
476 //! \param ulData data to be transmitted over the SSI interface.
478 //! This function will place the supplied data into the transmit FIFO of
479 //! the specified SSI module. If there is no space in the FIFO, then this
480 //! function will return a zero.
482 //! \note The upper 32 - N bits of the \e ulData will be discarded by the
483 //! hardware, where N is the data width as configured by SSIConfig(). For
484 //! example, if the interface is configured for 8 bit data width, the upper 24
485 //! bits of \e ulData will be discarded.
487 //! \return Returns the number of elements written to the SSI transmit FIFO.
489 //*****************************************************************************
490 #if defined(GROUP_datanonblockingput) || defined(BUILD_ALL) || defined(DOXYGEN)
492 SSIDataNonBlockingPut(unsigned long ulBase, unsigned long ulData)
495 // Check the arguments.
497 ASSERT(ulBase == SSI_BASE);
498 ASSERT((ulData & (0xfffffffe << (HWREG(ulBase + SSI_O_CR0) &
499 SSI_CR0_DSS))) == 0);
502 // Check for space to write.
504 if(HWREG(ulBase + SSI_O_SR) & SSI_SR_TNF)
506 HWREG(ulBase + SSI_O_DR) = ulData;
516 //*****************************************************************************
518 //! Gets a data element from the SSI receive FIFO.
520 //! \param ulBase specifies the SSI module base address.
521 //! \param pulData pointer to a storage location for data that was received
522 //! over the SSI interface.
524 //! This function will get received data from the receive FIFO of the specified
525 //! SSI module, and place that data into the location specified by the
526 //! \e pulData parameter.
528 //! \note Only the lower N bits of the value written to \e pulData will contain
529 //! valid data, where N is the data width as configured by SSIConfig(). For
530 //! example, if the interface is configured for 8 bit data width, only the
531 //! lower 8 bits of the value written to \e pulData will contain valid data.
535 //*****************************************************************************
536 #if defined(GROUP_dataget) || defined(BUILD_ALL) || defined(DOXYGEN)
538 SSIDataGet(unsigned long ulBase, unsigned long *pulData)
541 // Check the arguments.
543 ASSERT(ulBase == SSI_BASE);
546 // Wait until there is data to be read.
548 while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE))
553 // Read data from SSI.
555 *pulData = HWREG(ulBase + SSI_O_DR);
559 //*****************************************************************************
561 //! Gets a data element from the SSI receive FIFO.
563 //! \param ulBase specifies the SSI module base address.
564 //! \param pulData pointer to a storage location for data that was received
565 //! over the SSI interface.
567 //! This function will get received data from the receive FIFO of
568 //! the specified SSI module, and place that data into the location specified
569 //! by the \e ulData parameter. If there is no data in the FIFO, then this
570 //! function will return a zero.
572 //! \note Only the lower N bits of the value written to \e pulData will contain
573 //! valid data, where N is the data width as configured by SSIConfig(). For
574 //! example, if the interface is configured for 8 bit data width, only the
575 //! lower 8 bits of the value written to \e pulData will contain valid data.
577 //! \return Returns the number of elements read from the SSI receive FIFO.
579 //*****************************************************************************
580 #if defined(GROUP_datanonblockingget) || defined(BUILD_ALL) || defined(DOXYGEN)
582 SSIDataNonBlockingGet(unsigned long ulBase, unsigned long *pulData)
585 // Check the arguments.
587 ASSERT(ulBase == SSI_BASE);
590 // Check for data to read.
592 if(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE)
594 *pulData = HWREG(ulBase + SSI_O_DR);
604 //*****************************************************************************
606 // Close the Doxygen group.
609 //*****************************************************************************