1 /******************************************************************************
2 * Filename: ssi.c
3 *
4 * Description: Driver for Synchronous Serial Interface
5 *
6 * Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1) Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2) Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36
37 #include "ssi.h"
38
39 //*****************************************************************************
40 //
41 // Handle support for DriverLib in ROM:
42 // This section will undo prototype renaming made in the header file
43 //
44 //*****************************************************************************
45 #if !defined(DOXYGEN)
46 #undef SSIConfigSetExpClk
47 #define SSIConfigSetExpClk NOROM_SSIConfigSetExpClk
48 #undef SSIDataPut
49 #define SSIDataPut NOROM_SSIDataPut
50 #undef SSIDataPutNonBlocking
51 #define SSIDataPutNonBlocking NOROM_SSIDataPutNonBlocking
52 #undef SSIDataGet
53 #define SSIDataGet NOROM_SSIDataGet
54 #undef SSIDataGetNonBlocking
55 #define SSIDataGetNonBlocking NOROM_SSIDataGetNonBlocking
56 #undef SSIIntRegister
57 #define SSIIntRegister NOROM_SSIIntRegister
58 #undef SSIIntUnregister
59 #define SSIIntUnregister NOROM_SSIIntUnregister
60 #endif
61
62 //*****************************************************************************
63 //
64 // Configures the synchronous serial port
65 //
66 //*****************************************************************************
67 void
SSIConfigSetExpClk(uint32_t ui32Base,uint32_t ui32SSIClk,uint32_t ui32Protocol,uint32_t ui32Mode,uint32_t ui32BitRate,uint32_t ui32DataWidth)68 SSIConfigSetExpClk(uint32_t ui32Base, uint32_t ui32SSIClk,
69 uint32_t ui32Protocol, uint32_t ui32Mode,
70 uint32_t ui32BitRate, uint32_t ui32DataWidth)
71 {
72 uint32_t ui32MaxBitRate;
73 uint32_t ui32RegVal;
74 uint32_t ui32PreDiv;
75 uint32_t ui32SCR;
76 uint32_t ui32SPH_SPO;
77
78 // Check the arguments.
79 ASSERT(SSIBaseValid(ui32Base));
80 ASSERT((ui32Protocol == SSI_FRF_MOTO_MODE_0) ||
81 (ui32Protocol == SSI_FRF_MOTO_MODE_1) ||
82 (ui32Protocol == SSI_FRF_MOTO_MODE_2) ||
83 (ui32Protocol == SSI_FRF_MOTO_MODE_3) ||
84 (ui32Protocol == SSI_FRF_TI) ||
85 (ui32Protocol == SSI_FRF_NMW));
86 ASSERT((ui32Mode == SSI_MODE_MASTER) ||
87 (ui32Mode == SSI_MODE_SLAVE) ||
88 (ui32Mode == SSI_MODE_SLAVE_OD));
89 ASSERT(((ui32Mode == SSI_MODE_MASTER) && (ui32BitRate <= (ui32SSIClk / 2))) ||
90 ((ui32Mode != SSI_MODE_MASTER) && (ui32BitRate <= (ui32SSIClk / 12))));
91 ASSERT((ui32SSIClk / ui32BitRate) <= (254 * 256));
92 ASSERT((ui32DataWidth >= 4) && (ui32DataWidth <= 16));
93
94 // Set the mode.
95 ui32RegVal = (ui32Mode == SSI_MODE_SLAVE_OD) ? SSI_CR1_SOD : 0;
96 ui32RegVal |= (ui32Mode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
97 HWREG(ui32Base + SSI_O_CR1) = ui32RegVal;
98
99 // Set the clock predivider.
100 ui32MaxBitRate = ui32SSIClk / ui32BitRate;
101 ui32PreDiv = 0;
102 do
103 {
104 ui32PreDiv += 2;
105 ui32SCR = (ui32MaxBitRate / ui32PreDiv) - 1;
106 }
107 while(ui32SCR > 255);
108 HWREG(ui32Base + SSI_O_CPSR) = ui32PreDiv;
109
110 // Set protocol and clock rate.
111 ui32SPH_SPO = (ui32Protocol & 3) << 6;
112 ui32Protocol &= SSI_CR0_FRF_M;
113 ui32RegVal = (ui32SCR << 8) | ui32SPH_SPO | ui32Protocol | (ui32DataWidth - 1);
114 HWREG(ui32Base + SSI_O_CR0) = ui32RegVal;
115 }
116
117 //*****************************************************************************
118 //
119 // Puts a data element into the SSI transmit FIFO
120 //
121 //*****************************************************************************
122 int32_t
SSIDataPutNonBlocking(uint32_t ui32Base,uint32_t ui32Data)123 SSIDataPutNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
124 {
125 // Check the arguments.
126 ASSERT(SSIBaseValid(ui32Base));
127 ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
128 SSI_CR0_DSS_M))) == 0);
129
130 // Check for space to write.
131 if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
132 {
133 HWREG(ui32Base + SSI_O_DR) = ui32Data;
134 return(1);
135 }
136 else
137 {
138 return(0);
139 }
140 }
141
142 //*****************************************************************************
143 //
144 // Puts a data element into the SSI transmit FIFO
145 //
146 //*****************************************************************************
147 void
SSIDataPut(uint32_t ui32Base,uint32_t ui32Data)148 SSIDataPut(uint32_t ui32Base, uint32_t ui32Data)
149 {
150 // Check the arguments.
151 ASSERT(SSIBaseValid(ui32Base));
152 ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
153 SSI_CR0_DSS_M))) == 0);
154
155 // Wait until there is space.
156 while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
157 {
158 }
159
160 // Write the data to the SSI.
161 HWREG(ui32Base + SSI_O_DR) = ui32Data;
162 }
163
164 //*****************************************************************************
165 //
166 // Gets a data element from the SSI receive FIFO
167 //
168 //*****************************************************************************
169 void
SSIDataGet(uint32_t ui32Base,uint32_t * pui32Data)170 SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data)
171 {
172 // Check the arguments.
173 ASSERT(SSIBaseValid(ui32Base));
174
175 // Wait until there is data to be read.
176 while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE))
177 {
178 }
179
180 // Read data from SSI.
181 *pui32Data = HWREG(ui32Base + SSI_O_DR);
182 }
183
184 //*****************************************************************************
185 //
186 // Gets a data element from the SSI receive FIFO
187 //
188 //*****************************************************************************
189 int32_t
SSIDataGetNonBlocking(uint32_t ui32Base,uint32_t * pui32Data)190 SSIDataGetNonBlocking(uint32_t ui32Base, uint32_t *pui32Data)
191 {
192 // Check the arguments.
193 ASSERT(SSIBaseValid(ui32Base));
194
195 // Check for data to read.
196 if(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE)
197 {
198 *pui32Data = HWREG(ui32Base + SSI_O_DR);
199 return(1);
200 }
201 else
202 {
203 return(0);
204 }
205 }
206
207 //*****************************************************************************
208 //
209 // Registers an interrupt handler for the synchronous serial port
210 //
211 //*****************************************************************************
212 void
SSIIntRegister(uint32_t ui32Base,void (* pfnHandler)(void))213 SSIIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
214 {
215 uint32_t ui32Int;
216
217 // Check the arguments.
218 ASSERT(SSIBaseValid(ui32Base));
219
220 // Determine the interrupt number based on the SSI port.
221 ui32Int = (ui32Base == SSI0_BASE) ? INT_SSI0_COMB : INT_SSI1_COMB;
222
223 // Register the interrupt handler.
224 IntRegister(ui32Int, pfnHandler);
225
226 // Enable the synchronous serial port interrupt.
227 IntEnable(ui32Int);
228 }
229
230 //*****************************************************************************
231 //
232 // Unregisters an interrupt handler for the synchronous serial port
233 //
234 //*****************************************************************************
235 void
SSIIntUnregister(uint32_t ui32Base)236 SSIIntUnregister(uint32_t ui32Base)
237 {
238 uint32_t ui32Int;
239
240 // Check the arguments.
241 ASSERT(SSIBaseValid(ui32Base));
242
243 // Determine the interrupt number based on the SSI port.
244 ui32Int = (ui32Base == SSI0_BASE) ? INT_SSI0_COMB : INT_SSI1_COMB;
245
246 // Disable the interrupt.
247 IntDisable(ui32Int);
248
249 // Unregister the interrupt handler.
250 IntUnregister(ui32Int);
251 }
252