0% found this document useful (0 votes)
34 views5 pages

XMC Spi C

spi

Uploaded by

Roberto Dias
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views5 pages

XMC Spi C

spi

Uploaded by

Roberto Dias
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

1 /**

2 * @file xmc_spi.c
3 * @date 2020-12-05
4 *
5 * @cond
6 *****************************************************************************
7 * XMClib v2.2.0 - XMC Peripheral Driver Library
8 *
9 * Copyright (c) 2015-2020, Infineon Technologies AG
10 * All rights reserved.
11 *
12 * Boost Software License - Version 1.0 - August 17th, 2003
13 *
14 * Permission is hereby granted, free of charge, to any person or organization
15 * obtaining a copy of the software and accompanying documentation covered by
16 * this license (the "Software") to use, reproduce, display, distribute,
17 * execute, and transmit the Software, and to prepare derivative works of the
18 * Software, and to permit third-parties to whom the Software is furnished to
19 * do so, all subject to the following:
20 *
21 * The copyright notices in the Software and this entire statement, including
22 * the above license grant, this restriction and the following disclaimer,
23 * must be included in all copies of the Software, in whole or in part, and
24 * all derivative works of the Software, unless such copies or derivative
25 * works are solely in the form of machine-executable object code generated by
26 * a source language processor.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
31 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
32 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
33 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34 * DEALINGS IN THE SOFTWARE.
35 *
36 * To improve the quality of the software, users are encouraged to share
37 * modifications, enhancements or bug fixes with Infineon Technologies AG
38 * at [email protected].
39 *****************************************************************************
40 *
41 * Change History
42 * --------------
43 *
44 * 2015-02-20:
45 * - Initial <br>
46 *
47 * 2015-05-20:
48 * - Modified XMC_SPI_CH_Stop() API for not setting to IDLE the channel if it is
busy
49 * - Modified XMC_SPI_CH_SetInterwordDelay() implementation in order to gain
accuracy <br>
50 *
51 * 2015-06-20:
52 * - Removed GetDriverVersion API <br>
53 *
54 * 2015-09-01:
55 * - Modified XMC_SPI_CH_EnableEvent() and XMC_SPI_CH_DisableEvent() for
supporting multiple events configuration <br>
56 *
57 * 2015-11-04:
58 * - Modified the check of XMC_USIC_CH_GetTransmitBufferStatus() in the
XMC_SPI_CH_Transmit() flag <br>
59 *
60 * 2019-05-07:
61 * - Added XMC_SPI_CH_SetBaudrateEx() which allows to select between baudrate
generator normal divider and fractional divider mode
62 *
63 * 2019-12-16:
64 * - Fix including files following the convention: angle brackets are used for
standard includes and double quotes for everything else.
65 *
66 * 2020-12-05:
67 * - Added XMC_SPI_CH_InitEx that allows user select if automatic baudrate
configuration should be done or not
68 *
69 * @endcond
70 *
71 */
72 /**
73 *
74 * @brief SPI driver for XMC microcontroller family
75 *
76 */
77 /*************************************************************************************
********************************
78 * HEADER FILES
79
*************************************************************************************
*******************************/
80
81 #include "xmc_scu.h"
82 #include "xmc_spi.h"
83
84 /*************************************************************************************
********************************
85 * MACROS
86
*************************************************************************************
*******************************/
87 #define XMC_SPI_CH_OVERSAMPLING (2UL)
88
89 /*************************************************************************************
********************************
90 * API IMPLEMENTATION
91
*************************************************************************************
*******************************/
92
93 /* Initializes the selected SPI channel with the config structure. */
94 void XMC_SPI_CH_InitEx(XMC_USIC_CH_t *const channel, const XMC_SPI_CH_CONFIG_t *const
config, bool init_brg)
95 {
96 XMC_USIC_CH_Enable(channel);
97
98 if ((config->bus_mode == XMC_SPI_CH_BUS_MODE_MASTER) && init_brg)
99 {
100 /* Configure baud rate */
101 if (config->normal_divider_mode)
102 {
103 /* Normal divider mode */
104 (void)XMC_USIC_CH_SetBaudrateEx(channel, config->baudrate,
XMC_SPI_CH_OVERSAMPLING);
105 }
106 else
107 {
108 /* Fractional divider mode */
109 (void)XMC_USIC_CH_SetBaudrate(channel, config->baudrate, XMC_SPI_CH_OVERSAMPLING
);
110 }
111 }
112
113 /* Configuration of USIC Shift Control */
114 /* Transmission Mode (TRM) = 1 */
115 /* Passive Data Level (PDL) = 1 */
116 channel->SCTR = USIC_CH_SCTR_PDL_Msk |
117 (0x1UL << USIC_CH_SCTR_TRM_Pos) |
118 (0x3fUL << USIC_CH_SCTR_FLE_Pos) |
119 (0x7UL << USIC_CH_SCTR_WLE_Pos);
120
121 /* Configuration of USIC Transmit Control/Status Register */
122 /* TBUF Data Enable (TDEN) = 1 */
123 /* TBUF Data Single Shot Mode (TDSSM) = 1 */
124 channel->TCSR = (uint32_t)(USIC_CH_TCSR_HPCMD_Msk |
125 (0x01UL << USIC_CH_TCSR_TDEN_Pos) |
126 USIC_CH_TCSR_TDSSM_Msk);
127
128 if (config->bus_mode == XMC_SPI_CH_BUS_MODE_MASTER)
129 {
130 /* Configuration of Protocol Control Register */
131 channel->PCR_SSCMode = (uint32_t)(USIC_CH_PCR_SSCMode_MSLSEN_Msk |
132 USIC_CH_PCR_SSCMode_SELCTR_Msk |
133 (uint32_t)config->selo_inversion |
134 USIC_CH_PCR_SSCMode_FEM_Msk);
135 }
136
137 /* Clear protocol status */
138 channel->PSCR = 0xFFFFFFFFUL;
139
140 /* Set parity settings */
141 channel->CCR = (uint32_t)config->parity_mode;
142 }
143
144 XMC_SPI_CH_STATUS_t XMC_SPI_CH_SetBaudrate(XMC_USIC_CH_t *const channel, const
uint32_t rate)
145 {
146 XMC_SPI_CH_STATUS_t status;
147
148 status = XMC_SPI_CH_STATUS_ERROR;
149
150 if (rate <= (XMC_SCU_CLOCK_GetPeripheralClockFrequency() >> 1U))
151 {
152 if (XMC_USIC_CH_SetBaudrate(channel, rate, XMC_SPI_CH_OVERSAMPLING) ==
XMC_USIC_CH_STATUS_OK)
153 {
154 status = XMC_SPI_CH_STATUS_OK;
155 }
156 }
157 return status;
158 }
159
160 XMC_SPI_CH_STATUS_t XMC_SPI_CH_SetBaudrateEx(XMC_USIC_CH_t *const channel, const
uint32_t rate, bool normal_divider_mode)
161 {
162 XMC_USIC_CH_STATUS_t status;
163
164 if (rate <= (XMC_SCU_CLOCK_GetPeripheralClockFrequency() >> 1U))
165 {
166 if (normal_divider_mode)
167 {
168 /* Normal divider mode */
169 status = XMC_USIC_CH_SetBaudrateEx(channel, rate, XMC_SPI_CH_OVERSAMPLING);
170 }
171 else
172 {
173 /* Fractional divider mode */
174 status = XMC_USIC_CH_SetBaudrate(channel, rate, XMC_SPI_CH_OVERSAMPLING);
175 }
176 }
177 else
178 {
179 status = XMC_USIC_CH_STATUS_ERROR;
180 }
181
182 return (XMC_SPI_CH_STATUS_t)status;
183 }
184
185 /* Enable the selected slave signal by setting (SELO) bits in PCR register. */
186 void XMC_SPI_CH_EnableSlaveSelect(XMC_USIC_CH_t *const channel, const
XMC_SPI_CH_SLAVE_SELECT_t slave)
187 {
188 /* Configuration of Protocol Control Register */
189 channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_SELO_Msk;
190 channel->PCR_SSCMode |= (uint32_t)slave;
191 }
192
193 /* Disable the slave signals by clearing (SELO) bits in PCR register. */
194 void XMC_SPI_CH_DisableSlaveSelect(XMC_USIC_CH_t *const channel)
195 {
196 XMC_SPI_CH_ClearStatusFlag(channel, (uint32_t)XMC_SPI_CH_STATUS_FLAG_MSLS);
197
198 /* Configuration of Protocol Control Register */
199 channel->PCR_SSCMode &= (uint32_t)~USIC_CH_PCR_SSCMode_SELO_Msk;
200 }
201
202 /* Puts the data into FIFO if FIFO mode is enabled or else into standard buffers, by
setting the proper mode. */
203 void XMC_SPI_CH_Transmit(XMC_USIC_CH_t *const channel, const uint16_t data, const
XMC_SPI_CH_MODE_t mode)
204 {
205
206 channel->CCR = (channel->CCR & (uint32_t)(~USIC_CH_CCR_HPCEN_Msk)) |
207 (((uint32_t) mode << USIC_CH_CCR_HPCEN_Pos) & (uint32_t)
USIC_CH_CCR_HPCEN_Msk);
208
209
210 /* Check FIFO size */
211 if ((channel->TBCTR & USIC_CH_TBCTR_SIZE_Msk) == 0U)
212 {
213 while (XMC_USIC_CH_GetTransmitBufferStatus(channel) ==
XMC_USIC_CH_TBUF_STATUS_BUSY)
214 {
215 }
216
217 XMC_SPI_CH_ClearStatusFlag(channel, (uint32_t)
XMC_SPI_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION);
218
219 channel->TBUF[mode] = data;
220 }
221 else
222 {
223 channel->IN[mode] = data;
224 }
225 }
226
227 /* Reads the data from the buffers based on the FIFO mode selection. */
228 uint16_t XMC_SPI_CH_GetReceivedData(XMC_USIC_CH_t *const channel)
229 {
230 uint16_t retval;
231
232 /* Check FIFO size */
233 if ((channel->RBCTR & USIC_CH_RBCTR_SIZE_Msk) == 0U)
234 {
235 retval = (uint16_t)channel->RBUF;
236 }
237 else
238 {
239 retval = (uint16_t)channel->OUTR;
240 }
241
242 return retval;
243 }
244
245 /* Configures the inter word delay by setting PCR.PCTQ1, PCR.DCTQ1 bit fields. */
246 void XMC_SPI_CH_SetInterwordDelay(XMC_USIC_CH_t *const channel, uint32_t
tinterword_delay_us)
247 {
248 uint32_t peripheral_clock;
249 uint32_t pdiv;
250 uint32_t step;
251 uint32_t fFD;
252 uint32_t fpdiv;
253 uint32_t divider_factor1 = 0U;
254 uint32_t divider_factor2 = 32U;
255 uint32_t divider_factor1_int = 0U;
256 uint32_t divider_factor1_int_min = 4U;
257 uint32_t divider_factor1_frac_min = 100U;
258 uint32_t divider_factor1_frac = 0U;
259 uint32_t divider_factor2_temp = 0U;
260 peripheral_clock = XMC_SCU_CLOCK_GetPeripheralClockFrequency();
261 pdiv = (uint32_t)(channel->BRG & USIC_CH_BRG_PDIV_Msk) >> USIC_CH_BRG_PDIV_Pos;
262 step = (uint32_t)(channel->FDR & USIC_CH_FDR_STEP_Msk) >> USIC_CH_FDR_STEP_Pos;
263 fFD = (uint32_t)((peripheral_clock >> 10U) * step);
264 fpdiv = fFD / (1U + pdiv);
265
266 if (tinterword_delay_us < (128000000 / fpdiv))
267 {
268 for (divider_factor2_temp = 32U; divider_factor2_temp > 0U; --divider_factor2_temp
)
269 {
270
271 divider_factor1 = (tinterword_delay_us * fpdiv) / (divider_factor2_temp * 10000
);
272 divider_factor1_frac = divider_factor1 % 100U;
273
274 if (divider_factor1_frac > 50)
275 {
276 divider_factor1_int = (divider_factor1 / 100U) + 1;
277 divider_factor1_frac = (divider_factor1_int * 100) - divider_factor1;
278 }
279 else
280 {
281 divider_factor1_int = (divider_factor1 / 100U);
282 }
283
284 if ((divider_factor1_int < 5U) && (divider_factor1_int > 0) && (
divider_factor1_frac < divider_factor1_frac_min))
285 {
286 divider_factor1_frac_min = divider_factor1_frac;
287 divider_factor1_int_min = divider_factor1_int;
288 divider_factor2 = divider_factor2_temp;
289 }
290 }
291 }
292
293 channel->PCR_SSCMode = (uint32_t)((channel->PCR_SSCMode) & (~(
USIC_CH_PCR_SSCMode_DCTQ1_Msk |
294 USIC_CH_PCR_SSCMode_PCTQ1_Msk |
295 USIC_CH_PCR_SSCMode_CTQSEL1_Msk))) |
296 (((divider_factor1_int_min - 1) <<
USIC_CH_PCR_SSCMode_PCTQ1_Pos) & (uint32_t)
USIC_CH_PCR_SSCMode_PCTQ1_Msk) |
297 (((divider_factor2 - 1 ) << USIC_CH_PCR_SSCMode_DCTQ1_Pos) &
(uint32_t)USIC_CH_PCR_SSCMode_DCTQ1_Msk);
298 }
299
300 XMC_SPI_CH_STATUS_t XMC_SPI_CH_Stop(XMC_USIC_CH_t *const channel)
301 {
302 XMC_SPI_CH_STATUS_t status = XMC_SPI_CH_STATUS_OK;
303
304 if (XMC_USIC_CH_GetTransmitBufferStatus(channel) == XMC_USIC_CH_TBUF_STATUS_BUSY)
305 {
306 status = XMC_SPI_CH_STATUS_BUSY;
307 }
308 else
309 {
310
311 /* USIC channel in IDLE mode */
312 XMC_USIC_CH_SetMode(channel, XMC_USIC_CH_OPERATING_MODE_IDLE);
313 }
314
315 return status;
316 }
317
318 void XMC_SPI_CH_EnableEvent(XMC_USIC_CH_t *const channel, const uint32_t event)
319 {
320 channel->CCR |= (event & 0x1fc00U);
321 channel->PCR_SSCMode |= ((event << 13U) & 0xe000U);
322 }
323
324 void XMC_SPI_CH_DisableEvent(XMC_USIC_CH_t *const channel, const uint32_t event)
325 {
326 channel->CCR &= (uint32_t)~(event & 0x1fc00U);
327 channel->PCR_SSCMode &= (uint32_t)~((event << 13U) & 0xe000U);
328 }
329

You might also like