Paparazzi UAS  v5.15_devel-230-gc96ce27
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
spi_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Felix Ruess <felix.ruess@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <fcntl.h>
30 #include <string.h>
31 
32 #include <sys/ioctl.h>
33 #include <linux/spi/spidev.h>
34 
35 #include "mcu_periph/spi.h"
36 #include BOARD_CONFIG
37 
38 
39 void spi_init_slaves(void)
40 {
41  /* for now we assume that each SPI device has it's SLAVE CS already set up
42  * e.g. in pin muxing of BBB
43  */
44 }
45 
46 #pragma GCC diagnostic push
47 #pragma GCC diagnostic ignored "-Wcast-qual"
48 bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
49 {
50  int fd = (int)p->reg_addr;
51 
52  struct spi_ioc_transfer xfer;
53  memset(&xfer, 0, sizeof xfer);
54 
55  /* length in bytes of transaction */
56  uint16_t buf_len = Max(t->input_length, t->output_length);
57 
58  // temp buffers, used if necessary
59  uint8_t tx_buf[buf_len], rx_buf[buf_len];
60  memset(tx_buf, 0, buf_len);
61  memset(rx_buf, 0, buf_len);
62 
63  /* handle transactions with different input/output length */
64  if (buf_len > t->output_length) {
65  /* copy bytes to transmit to larger buffer, rest filled with zero */
66  memcpy(tx_buf, (void *)t->output_buf, t->output_length);
67  xfer.tx_buf = (unsigned long)tx_buf;
68  } else {
69  xfer.tx_buf = (unsigned long)t->output_buf;
70  }
71 
72  if (buf_len > t->input_length) {
73  xfer.rx_buf = (unsigned long)rx_buf;
74  } else {
75  xfer.rx_buf = (unsigned long)t->input_buf;
76  }
77 
78  xfer.len = buf_len;
79  /* fixed speed of 1Mhz for now, use SPIClockDiv?? */
80  xfer.speed_hz = (uint32_t)p->init_struct;
81  xfer.delay_usecs = 0;
82  if (t->dss == SPIDss16bit) {
83  xfer.bits_per_word = 16;
84  } else {
85  xfer.bits_per_word = 8;
86  }
87  if (t->select == SPISelectUnselect || t->select == SPIUnselect) {
88  xfer.cs_change = 1;
89  }
90 
91  if (ioctl(fd, SPI_IOC_MESSAGE(1), &xfer) < 0) {
93  return false;
94  }
95 
96  /* copy received data if we had to use an extra rx_buffer */
97  if (buf_len > t->input_length) {
98  memcpy((void *)t->input_buf, rx_buf, t->input_length);
99  }
100 
101  t->status = SPITransSuccess;
102  return true;
103 }
104 #pragma GCC diagnostic pop
105 
106 bool spi_lock(struct spi_periph *p, uint8_t slave)
107 {
108  // not implemented
109  return false;
110 }
111 
112 bool spi_resume(struct spi_periph *p, uint8_t slave)
113 {
114  // not implemented
115  return false;
116 }
117 
118 
119 #if USE_SPI0
120 
121 #ifndef SPI0_MODE
122 #define SPI0_MODE (SPI_CPOL | SPI_CPHA)
123 #endif
124 
125 #ifndef SPI0_LSB_FIRST
126 #define SPI0_LSB_FIRST 0
127 #endif
128 
129 #ifndef SPI0_BITS_PER_WORD
130 #define SPI0_BITS_PER_WORD 8
131 #endif
132 
133 #ifndef SPI0_MAX_SPEED_HZ
134 #define SPI0_MAX_SPEED_HZ 1000000
135 #endif
136 
137 void spi0_arch_init(void)
138 {
139  int fd = open("/dev/spidev1.0", O_RDWR);
140 
141  if (fd < 0) {
142  perror("Could not open SPI device /dev/spidev1.0");
143  spi0.reg_addr = NULL;
144  return;
145  }
146  spi0.reg_addr = (void *)fd;
147 
148  /* spi mode */
149  unsigned char spi_mode = SPI0_MODE;
150  if (ioctl(fd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
151  perror("SPI0: can't set spi mode");
152  }
153 
154  /* set to MSB first */
155  unsigned char spi_order = SPI0_LSB_FIRST;
156  if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &spi_order) < 0) {
157  perror("SPI0: can't set spi bit justification");
158  }
159 
160  /* bits per word default to 8 */
161  unsigned char spi_bits_per_word = SPI0_BITS_PER_WORD;
162  if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word) < 0) {
163  perror("SPI0: can't set bits per word");
164  }
165 
166  /* max speed in hz, 1MHz for now */
167  unsigned int spi_speed = SPI0_MAX_SPEED_HZ;
168  if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0) {
169  perror("SPI0: can't set max speed hz");
170  }
172 }
173 #endif /* USE_SPI0 */
174 
175 #if USE_SPI1
176 
177 #ifndef SPI1_MODE
178 #define SPI1_MODE (SPI_CPOL | SPI_CPHA)
179 #endif
180 
181 #ifndef SPI1_LSB_FIRST
182 #define SPI1_LSB_FIRST 0
183 #endif
184 
185 #ifndef SPI1_BITS_PER_WORD
186 #define SPI1_BITS_PER_WORD 8
187 #endif
188 
189 #ifndef SPI1_MAX_SPEED_HZ
190 #define SPI1_MAX_SPEED_HZ 1000000
191 #endif
192 
193 void spi1_arch_init(void)
194 {
195  int fd = open("/dev/spidev1.1", O_RDWR);
196 
197  if (fd < 0) {
198  perror("Could not open SPI device /dev/spidev1.1");
199  spi1.reg_addr = NULL;
200  return;
201  }
202  spi1.reg_addr = (void *)fd;
203 
204  /* spi mode */
205  unsigned char spi_mode = SPI1_MODE;
206  if (ioctl(fd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
207  perror("SPI1: can't set spi mode");
208  }
209 
210  /* set to MSB first */
211  unsigned char spi_order = SPI1_LSB_FIRST;
212  if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &spi_order) < 0) {
213  perror("SPI1: can't set spi bit justification");
214  }
215 
216  /* bits per word default to 8 */
217  unsigned char spi_bits_per_word = SPI1_BITS_PER_WORD;
218  if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word) < 0) {r
219  perror("SPI1: can't set bits per word");
220  }
221 
222  /* max speed in hz, 1MHz for now */
223  unsigned int spi_speed = SPI1_MAX_SPEED_HZ;
224  if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0) {
225  perror("SPI1: can't set max speed hz");
226  }
227  spi1.init_struct = (void *)SPI1_MAX_SPEED_HZ;
228 }
229 #endif /* USE_SPI1 */
unsigned short uint16_t
Definition: types.h:16
#define SPI1_MODE
Definition: spi_arch.c:178
uint16_t output_length
number of data words to write
Definition: spi.h:152
void * reg_addr
Definition: spi.h:183
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
Definition: spi_arch.c:366
slave is not selected but unselected after transaction
Definition: spi.h:65
SPI transaction structure.
Definition: spi.h:148
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:511
#define SPI0_BITS_PER_WORD
Definition: spi_arch.c:130
void * init_struct
Definition: spi.h:184
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:150
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:154
Architecture independent SPI (Serial Peripheral Interface) API.
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
Definition: spi_arch.c:629
SPI peripheral structure.
Definition: spi.h:174
#define SPI1_MAX_SPEED_HZ
Definition: spi_arch.c:190
struct spi_periph spi0
Definition: spi.c:35
unsigned long uint32_t
Definition: types.h:18
#define SPI0_MAX_SPEED_HZ
Definition: spi_arch.c:134
#define Max(x, y)
Definition: main_fbw.c:53
uint16_t input_length
number of data words to read
Definition: spi.h:151
#define SPI0_MODE
Definition: spi_arch.c:122
#define SPI0_LSB_FIRST
Definition: spi_arch.c:126
unsigned char uint8_t
Definition: types.h:14
bool spi_resume(struct spi_periph *p, uint8_t slave)
spi_resume() function
Definition: spi_arch.c:643
#define SPI1_LSB_FIRST
Definition: spi_arch.c:182
int fd
Definition: serial.c:26
slave is selected before transaction and unselected after
Definition: spi.h:63
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:157
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:149
#define SPI1_BITS_PER_WORD
Definition: spi_arch.c:186
static float p[2][2]
void spi_init_slaves(void)
spi_init_slaves() function
Definition: spi_arch.c:657
void spi0_arch_init(void)
Architecture dependent SPI0 initialization.
Definition: spi_arch.c:137
process_rx_dma_interrupt & spi1
receive transferred over DMA
Definition: spi_arch.c:967
enum SPITransactionStatus status
Definition: spi.h:162