Paparazzi UAS  v5.12_stable-4-g9b43e9b
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  /* handle transactions with different input/output length */
59  if (buf_len > t->output_length) {
60  uint8_t tx_buf[buf_len];
61  memset(tx_buf, 0, sizeof tx_buf);
62  /* copy bytes to transmit to larger buffer, rest filled with zero */
63  memcpy(tx_buf, (void *)t->output_buf, t->output_length);
64  xfer.tx_buf = (unsigned long)tx_buf;
65  } else {
66  xfer.tx_buf = (unsigned long)t->output_buf;
67  }
68 
69  if (buf_len > t->input_length) {
70  uint8_t rx_buf[buf_len];
71  memset(rx_buf, 0, sizeof rx_buf);
72  xfer.rx_buf = (unsigned long)rx_buf;
73  } else {
74  xfer.rx_buf = (unsigned long)t->input_buf;
75  }
76 
77  xfer.len = buf_len;
78  /* fixed speed of 1Mhz for now, use SPIClockDiv?? */
79  xfer.speed_hz = (uint32_t)p->init_struct;
80  xfer.delay_usecs = 0;
81  if (t->dss == SPIDss16bit) {
82  xfer.bits_per_word = 16;
83  } else {
84  xfer.bits_per_word = 8;
85  }
86  if (t->select == SPISelectUnselect || t->select == SPIUnselect) {
87  xfer.cs_change = 1;
88  }
89 
90  if (ioctl(fd, SPI_IOC_MESSAGE(1), &xfer) < 0) {
92  return false;
93  }
94 
95  /* copy recieved data if we had to use an extra rx_buffer */
96  if (buf_len > t->input_length) {
97  memcpy((void *)t->input_buf, (void *)((uint32_t)xfer.rx_buf), t->input_length);
98  }
99 
100  t->status = SPITransSuccess;
101  return true;
102 }
103 #pragma GCC diagnostic pop
104 
105 bool spi_lock(struct spi_periph *p, uint8_t slave)
106 {
107  // not implemented
108  return false;
109 }
110 
111 bool spi_resume(struct spi_periph *p, uint8_t slave)
112 {
113  // not implemented
114  return false;
115 }
116 
117 
118 #if USE_SPI0
119 
120 #ifndef SPI0_MODE
121 #define SPI0_MODE (SPI_CPOL | SPI_CPHA)
122 #endif
123 
124 #ifndef SPI0_LSB_FIRST
125 #define SPI0_LSB_FIRST 0
126 #endif
127 
128 #ifndef SPI0_BITS_PER_WORD
129 #define SPI0_BITS_PER_WORD 8
130 #endif
131 
132 #ifndef SPI0_MAX_SPEED_HZ
133 #define SPI0_MAX_SPEED_HZ 1000000
134 #endif
135 
136 void spi0_arch_init(void)
137 {
138  int fd = open("/dev/spidev1.0", O_RDWR);
139 
140  if (fd < 0) {
141  perror("Could not open SPI device /dev/spidev1.0");
142  spi0.reg_addr = NULL;
143  return;
144  }
145  spi0.reg_addr = (void *)fd;
146 
147  /* spi mode */
148  unsigned char spi_mode = SPI0_MODE;
149  if (ioctl(fd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
150  perror("SPI0: can't set spi mode");
151  }
152 
153  /* set to MSB first */
154  unsigned char spi_order = SPI0_LSB_FIRST;
155  if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &spi_order) < 0) {
156  perror("SPI0: can't set spi bit justification");
157  }
158 
159  /* bits per word default to 8 */
160  unsigned char spi_bits_per_word = SPI0_BITS_PER_WORD;
161  if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word) < 0) {
162  perror("SPI0: can't set bits per word");
163  }
164 
165  /* max speed in hz, 1MHz for now */
166  unsigned int spi_speed = SPI0_MAX_SPEED_HZ;
167  if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0) {
168  perror("SPI0: can't set max speed hz");
169  }
171 }
172 #endif /* USE_SPI0 */
173 
174 #if USE_SPI1
175 
176 #ifndef SPI1_MODE
177 #define SPI1_MODE (SPI_CPOL | SPI_CPHA)
178 #endif
179 
180 #ifndef SPI1_LSB_FIRST
181 #define SPI1_LSB_FIRST 0
182 #endif
183 
184 #ifndef SPI1_BITS_PER_WORD
185 #define SPI1_BITS_PER_WORD 8
186 #endif
187 
188 #ifndef SPI1_MAX_SPEED_HZ
189 #define SPI1_MAX_SPEED_HZ 1000000
190 #endif
191 
192 void spi1_arch_init(void)
193 {
194  int fd = open("/dev/spidev1.1", O_RDWR);
195 
196  if (fd < 0) {
197  perror("Could not open SPI device /dev/spidev1.1");
198  spi1.reg_addr = NULL;
199  return;
200  }
201  spi1.reg_addr = (void *)fd;
202 
203  /* spi mode */
204  unsigned char spi_mode = SPI1_MODE;
205  if (ioctl(fd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
206  perror("SPI1: can't set spi mode");
207  }
208 
209  /* set to MSB first */
210  unsigned char spi_order = SPI1_LSB_FIRST;
211  if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &spi_order) < 0) {
212  perror("SPI1: can't set spi bit justification");
213  }
214 
215  /* bits per word default to 8 */
216  unsigned char spi_bits_per_word = SPI1_BITS_PER_WORD;
217  if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word) < 0) {r
218  perror("SPI1: can't set bits per word");
219  }
220 
221  /* max speed in hz, 1MHz for now */
222  unsigned int spi_speed = SPI1_MAX_SPEED_HZ;
223  if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0) {
224  perror("SPI1: can't set max speed hz");
225  }
226  spi1.init_struct = (void *)SPI1_MAX_SPEED_HZ;
227 }
228 #endif /* USE_SPI1 */
unsigned short uint16_t
Definition: types.h:16
#define SPI1_MODE
Definition: spi_arch.c:177
uint16_t output_length
number of data words to write
Definition: spi.h:146
void * reg_addr
Definition: spi.h:177
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
Definition: spi_arch.c:352
slave is not selected but unselected after transaction
Definition: spi.h:59
SPI transaction structure.
Definition: spi.h:142
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:458
#define SPI0_BITS_PER_WORD
Definition: spi_arch.c:129
void * init_struct
Definition: spi.h:178
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
Architecture independent SPI (Serial Peripheral Interface) API.
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
Definition: spi_arch.c:576
SPI peripheral structure.
Definition: spi.h:168
#define SPI1_MAX_SPEED_HZ
Definition: spi_arch.c:189
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:133
#define Max(x, y)
Definition: main_fbw.c:53
uint16_t input_length
number of data words to read
Definition: spi.h:145
#define SPI0_MODE
Definition: spi_arch.c:121
#define SPI0_LSB_FIRST
Definition: spi_arch.c:125
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:590
#define SPI1_LSB_FIRST
Definition: spi_arch.c:181
int fd
Definition: serial.c:26
slave is selected before transaction and unselected after
Definition: spi.h:57
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
#define SPI1_BITS_PER_WORD
Definition: spi_arch.c:185
static float p[2][2]
void spi_init_slaves(void)
spi_init_slaves() function
Definition: spi_arch.c:604
void spi0_arch_init(void)
Architecture dependent SPI0 initialization.
Definition: spi_arch.c:136
process_rx_dma_interrupt & spi1
receive transferred over DMA
Definition: spi_arch.c:967
enum SPITransactionStatus status
Definition: spi.h:156
if(PrimarySpektrumState.SpektrumTimer)