source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/SPI/spi.c @ 46

Last change on this file since 46 was 46, checked in by jrpelegrina, 4 years ago

First release to Xenial

File size: 10.4 KB
Line 
1/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3/*This file is prepared for Doxygen automatic documentation generation.*/
4/*! \file *********************************************************************
5 *
6 * \brief SPI driver for AVR32 UC3.
7 *
8 * This file defines a useful set of functions for the SPI interface on AVR32
9 * devices.
10 *
11 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
12 * - Supported devices:  All AVR32 devices with an SPI module can be used.
13 * - AppNote:
14 *
15 * \author               Atmel Corporation: http://www.atmel.com \n
16 *                       Support and FAQ: http://support.atmel.no/
17 *
18 ******************************************************************************/
19
20/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are met:
24 *
25 * 1. Redistributions of source code must retain the above copyright notice, this
26 * list of conditions and the following disclaimer.
27 *
28 * 2. Redistributions in binary form must reproduce the above copyright notice,
29 * this list of conditions and the following disclaimer in the documentation
30 * and/or other materials provided with the distribution.
31 *
32 * 3. The name of Atmel may not be used to endorse or promote products derived
33 * from this software without specific prior written permission.
34 *
35 * 4. This software may only be redistributed and used in connection with an Atmel
36 * AVR product.
37 *
38 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
39 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
41 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
42 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
48 *
49 */
50
51#include "spi.h"
52
53#ifdef FREERTOS_USED
54
55#include "FreeRTOS.h"
56#include "semphr.h"
57
58#endif
59
60
61/*! \name SPI Writable Bit-Field Registers
62 */
63//! @{
64
65typedef union
66{
67  unsigned long                 cr;
68  avr32_spi_cr_t                CR;
69} u_avr32_spi_cr_t;
70
71typedef union
72{
73  unsigned long                 mr;
74  avr32_spi_mr_t                MR;
75} u_avr32_spi_mr_t;
76
77typedef union
78{
79  unsigned long                 tdr;
80  avr32_spi_tdr_t               TDR;
81} u_avr32_spi_tdr_t;
82
83typedef union
84{
85  unsigned long                 ier;
86  avr32_spi_ier_t               IER;
87} u_avr32_spi_ier_t;
88
89typedef union
90{
91  unsigned long                 idr;
92  avr32_spi_idr_t               IDR;
93} u_avr32_spi_idr_t;
94
95typedef union
96{
97  unsigned long                 csr;
98  avr32_spi_csr0_t              CSR;
99} u_avr32_spi_csr_t;
100
101//! @}
102
103
104#ifdef FREERTOS_USED
105
106//! The SPI mutex.
107static xSemaphoreHandle xSPIMutex;
108
109#endif
110
111
112/*! \brief Calculates the baudrate divider.
113 *
114 * \param options Pointer to a structure containing initialization options for
115 *                an SPI channel.
116 * \param pba_hz  SPI module input clock frequency (PBA clock, Hz).
117 *
118 * \return Divider or error code.
119 *   \retval >=0  Success.
120 *   \retval  <0  Error.
121 */
122static int getBaudDiv(const spi_options_t *options, unsigned int pba_hz)
123{
124  int baudDiv = (pba_hz + options->baudrate / 2) / options->baudrate;
125
126  if (baudDiv <= 0 || baudDiv > 255) {
127    return -1;
128  }
129
130  return baudDiv;
131}
132
133
134void spi_reset(volatile avr32_spi_t *spi)
135{
136  spi->cr = AVR32_SPI_CR_SWRST_MASK;
137}
138
139
140spi_status_t spi_initSlave(volatile avr32_spi_t *spi,
141                           unsigned char bits,
142                           unsigned char spi_mode)
143{
144  if (spi_mode > 3 ||
145      bits < 8 || bits > 16) {
146    return SPI_ERROR_ARGUMENT;
147  }
148
149  // Reset.
150  spi->cr = AVR32_SPI_CR_SWRST_MASK;
151
152  // Will use CSR0 offsets; these are the same for CSR0 to CSR3.
153  spi->csr0 = ((spi_mode >> 1) << AVR32_SPI_CSR0_CPOL_OFFSET) |
154              (((spi_mode & 0x1) ^ 0x1) << AVR32_SPI_CSR0_NCPHA_OFFSET) |
155              ((bits - 8) << AVR32_SPI_CSR0_BITS_OFFSET);
156
157  return SPI_OK;
158}
159
160
161spi_status_t spi_initTest(volatile avr32_spi_t *spi)
162{
163  // Reset.
164  spi->cr = AVR32_SPI_CR_SWRST_MASK;
165  spi->mr |= AVR32_SPI_MR_MSTR_MASK | // Master Mode.
166             AVR32_SPI_MR_LLB_MASK;   // Local Loopback.
167
168  return SPI_OK;
169}
170
171
172spi_status_t spi_initMaster(volatile avr32_spi_t *spi, const spi_options_t *options)
173{
174  u_avr32_spi_mr_t u_avr32_spi_mr;
175
176  if (options->modfdis > 1) {
177    return SPI_ERROR_ARGUMENT;
178  }
179
180  // Reset.
181  spi->cr = AVR32_SPI_CR_SWRST_MASK;
182
183  // Master Mode.
184  u_avr32_spi_mr.mr = spi->mr;
185  u_avr32_spi_mr.MR.mstr = 1;
186  u_avr32_spi_mr.MR.modfdis = options->modfdis;
187  u_avr32_spi_mr.MR.llb = 0;
188  u_avr32_spi_mr.MR.pcs = (1 << AVR32_SPI_MR_PCS_SIZE) - 1;
189  spi->mr = u_avr32_spi_mr.mr;
190
191  return SPI_OK;
192}
193
194
195spi_status_t spi_selectionMode(volatile avr32_spi_t *spi,
196                               unsigned char variable_ps,
197                               unsigned char pcs_decode,
198                               unsigned char delay)
199{
200  u_avr32_spi_mr_t u_avr32_spi_mr;
201
202  if (variable_ps > 1 ||
203      pcs_decode > 1) {
204    return SPI_ERROR_ARGUMENT;
205  }
206
207  u_avr32_spi_mr.mr = spi->mr;
208  u_avr32_spi_mr.MR.ps = variable_ps;
209  u_avr32_spi_mr.MR.pcsdec = pcs_decode;
210  u_avr32_spi_mr.MR.dlybcs = delay;
211  spi->mr = u_avr32_spi_mr.mr;
212
213  return SPI_OK;
214}
215
216
217spi_status_t spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip)
218{
219#ifdef FREERTOS_USED
220  while (pdFALSE == xSemaphoreTake(xSPIMutex, 20));
221#endif
222
223  // Assert all lines; no peripheral is selected.
224  spi->mr |= AVR32_SPI_MR_PCS_MASK;
225
226  if (spi->mr & AVR32_SPI_MR_PCSDEC_MASK) {
227    // The signal is decoded; allow up to 15 chips.
228    if (chip > 14) {
229      return SPI_ERROR_ARGUMENT;
230    }
231
232    spi->mr &= ~AVR32_SPI_MR_PCS_MASK | (chip << AVR32_SPI_MR_PCS_OFFSET);
233  } else {
234    if (chip > 3) {
235      return SPI_ERROR_ARGUMENT;
236    }
237
238    spi->mr &= ~(1 << (AVR32_SPI_MR_PCS_OFFSET + chip));
239  }
240
241  return SPI_OK;
242}
243
244
245spi_status_t spi_unselectChip(volatile avr32_spi_t *spi, unsigned char chip)
246{
247  unsigned int timeout = SPI_TIMEOUT;
248
249  while (!(spi->sr & AVR32_SPI_SR_TXEMPTY_MASK)) {
250    if (!timeout--) {
251      return SPI_ERROR_TIMEOUT;
252    }
253  }
254
255  // Assert all lines; no peripheral is selected.
256  spi->mr |= AVR32_SPI_MR_PCS_MASK;
257
258  // Last transfer, so deassert the current NPCS if CSAAT is set.
259  spi->cr = AVR32_SPI_CR_LASTXFER_MASK;
260
261#ifdef FREERTOS_USED
262  xSemaphoreGive(xSPIMutex);
263#endif
264
265  return SPI_OK;
266}
267
268
269spi_status_t spi_setupChipReg(volatile avr32_spi_t *spi,
270                              const spi_options_t *options,
271                              unsigned int pba_hz)
272{
273  u_avr32_spi_csr_t u_avr32_spi_csr;
274
275  if (options->spi_mode > 3 ||
276      options->stay_act > 1 ||
277      options->bits < 8 || options->bits > 16) {
278    return SPI_ERROR_ARGUMENT;
279  }
280
281  int baudDiv = getBaudDiv(options, pba_hz);
282
283  if (baudDiv < 0) {
284    return SPI_ERROR_ARGUMENT;
285  }
286
287  // Will use CSR0 offsets; these are the same for CSR0 to CSR3.
288  u_avr32_spi_csr.csr = 0;
289  u_avr32_spi_csr.CSR.cpol = options->spi_mode >> 1;
290  u_avr32_spi_csr.CSR.ncpha = (options->spi_mode & 0x1) ^ 0x1;
291  u_avr32_spi_csr.CSR.csaat = options->stay_act;
292  u_avr32_spi_csr.CSR.bits = options->bits - 8;
293  u_avr32_spi_csr.CSR.scbr = baudDiv;
294  u_avr32_spi_csr.CSR.dlybs = options->spck_delay;
295  u_avr32_spi_csr.CSR.dlybct = options->trans_delay;
296
297  switch(options->reg) {
298    case 0:
299      spi->csr0 = u_avr32_spi_csr.csr;
300      break;
301    case 1:
302      spi->csr1 = u_avr32_spi_csr.csr;
303      break;
304    case 2:
305      spi->csr2 = u_avr32_spi_csr.csr;
306      break;
307    case 3:
308      spi->csr3 = u_avr32_spi_csr.csr;
309      break;
310    default:
311      return SPI_ERROR_ARGUMENT;
312  }
313
314#ifdef FREERTOS_USED
315  if (!xSPIMutex)
316  {
317    // Create the SPI mutex.
318    vSemaphoreCreateBinary(xSPIMutex);
319    if (!xSPIMutex)
320    {
321      while(1);
322    }
323  }
324#endif
325
326  return SPI_OK;
327}
328
329
330void spi_enable(volatile avr32_spi_t *spi)
331{
332  spi->cr = AVR32_SPI_CR_SPIEN_MASK;
333}
334
335
336void spi_disable(volatile avr32_spi_t *spi)
337{
338  spi->cr = AVR32_SPI_CR_SPIDIS_MASK;
339}
340
341
342int spi_is_enabled(volatile avr32_spi_t *spi)
343{
344  return (spi->sr & AVR32_SPI_SR_SPIENS_MASK) != 0;
345}
346
347
348inline unsigned char spi_writeRegisterEmptyCheck(volatile avr32_spi_t *spi)
349{
350  return ((spi->sr & AVR32_SPI_SR_TDRE_MASK) != 0);
351}
352
353
354inline spi_status_t spi_write(volatile avr32_spi_t *spi, unsigned short data)
355{
356  unsigned int timeout = SPI_TIMEOUT;
357
358  while (!(spi->sr & AVR32_SPI_SR_TDRE_MASK)) {
359    if (!timeout--) {
360      return SPI_ERROR_TIMEOUT;
361    }
362  }
363
364  spi->tdr = data << AVR32_SPI_TDR_TD_OFFSET;
365
366  return SPI_OK;
367}
368
369
370spi_status_t spi_variableSlaveWrite(volatile avr32_spi_t *spi, unsigned short data,
371                                    unsigned char pcs, unsigned char lastxfer)
372{
373  unsigned int timeout = SPI_TIMEOUT;
374
375  if (pcs > 14 || lastxfer > 1) {
376    return SPI_ERROR_ARGUMENT;
377  }
378
379  while (!(spi->sr & AVR32_SPI_SR_TDRE_MASK)) {
380    if (!timeout--) {
381      return SPI_ERROR_TIMEOUT;
382    }
383  }
384
385  spi->tdr = (data << AVR32_SPI_TDR_TD_OFFSET) |
386             (pcs << AVR32_SPI_TDR_PCS_OFFSET) |
387             (lastxfer << AVR32_SPI_TDR_LASTXFER_OFFSET);
388
389  return SPI_OK;
390}
391
392
393inline unsigned char spi_writeEndCheck(volatile avr32_spi_t *spi)
394{
395  return ((spi->sr & AVR32_SPI_SR_TXEMPTY_MASK) != 0);
396}
397
398
399unsigned char spi_readRegisterFullCheck(volatile avr32_spi_t *spi)
400{
401  return ((spi->sr & AVR32_SPI_SR_RDRF_MASK) != 0);
402}
403
404
405inline spi_status_t spi_read(volatile avr32_spi_t *spi, unsigned short *data)
406{
407  unsigned int timeout = SPI_TIMEOUT;
408
409  while ((spi->sr & (AVR32_SPI_SR_RDRF_MASK | AVR32_SPI_SR_TXEMPTY_MASK)) !=
410         (AVR32_SPI_SR_RDRF_MASK | AVR32_SPI_SR_TXEMPTY_MASK)) {
411    if (!timeout--) {
412      return SPI_ERROR_TIMEOUT;
413    }
414  }
415
416  *data = spi->rdr >> AVR32_SPI_RDR_RD_OFFSET;
417
418  return SPI_OK;
419}
420
421
422unsigned char spi_getStatus(volatile avr32_spi_t *spi)
423{
424  spi_status_t ret = SPI_OK;
425  unsigned long sr = spi->sr;
426
427  if (sr & AVR32_SPI_SR_OVRES_MASK) {
428    ret = SPI_ERROR_OVERRUN;
429  }
430
431  if (sr & AVR32_SPI_SR_MODF_MASK) {
432    ret += SPI_ERROR_MODE_FAULT;
433  }
434
435  if (ret == (SPI_ERROR_OVERRUN + SPI_ERROR_MODE_FAULT)) {
436    return SPI_ERROR_OVERRUN_AND_MODE_FAULT;
437  }
438  else if (ret > 0) {
439    return ret;
440  } else {
441    return SPI_OK;
442  }
443}
Note: See TracBrowser for help on using the repository browser.