ARMEBS4  revision-26.06.2015
stm32_spi.c
Go to the documentation of this file.
1 /**
2  * \file heivs/stm32_spi.c
3  * \brief spi bus
4  * \author marc dot pignat at hevs dot ch
5  ***************************************************************************/
6 
7 #include "heivs/stm32_spi.h"
8 #include "heivs/time.h"
9 #include "heivs/bsp.h"
10 #include "stm32/stm32f4xx_spi.h"
11 #include "stm32/stm32f4xx_rcc.h"
12 
13 #define SPI_STD_TIMEOUT_MS 10
14 
15 static status_e init(const struct heivs_bus_t *bus)
16 {
17  status_e status;
18  const struct spi_bus_private_t *spi = bus->priv;
19  SPI_InitTypeDef SPI_InitStruct;
20 
21  /* FIXME handle those cases */
22  if (spi->options & SPI_OPTION_SLAVE)
23  {
24  return ERROR_NOT_YET_IMPLEMENTED;
25  }
26 
27  /* Setup gpios */
28  status = gpio_setup_list(spi->gpios, ARRAY_SIZE(spi->gpios));
29  if (status != NO_ERROR)
30  {
31  return status;
32  }
33 
34  /* Enable the spi controller */
35  switch ((uint32_t)spi->ctrl)
36  {
37  case (uint32_t)SPI1:
38  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
39  break;
40 
41  case (uint32_t)SPI2:
42  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
43  break;
44 
45  case (uint32_t)SPI3:
46  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
47  break;
48 
49  default:
50  case 0:
51  return ERROR_BAD_PARAM;
52  }
53 
54  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
55  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
56  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
57  switch (spi->options & SPI_OPTION_MODE_3)
58  {
59  case SPI_OPTION_MODE_0:
60  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
61  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
62  break;
63  case SPI_OPTION_MODE_1:
64  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
65  SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
66  break;
67  case SPI_OPTION_MODE_2:
68  SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
69  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
70  break;
71  case SPI_OPTION_MODE_3:
72  SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
73  SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
74  break;
75  }
76 
77  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
78  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
79  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
80  SPI_Init(spi->ctrl, &SPI_InitStruct);
81 
82  SPI_Cmd(spi->ctrl, ENABLE);
83 
84  return NO_ERROR;
85 }
86 
87 static status_e suspend(const struct heivs_bus_t *bus)
88 {
89  (void)bus;
90  return ERROR_NOT_YET_IMPLEMENTED;
91 }
92 
93 static status_e write_read_one(const struct spi_bus_private_t *spi, const uint8_t *src, uint8_t *dst)
94 {
95  timeout_t timeout = time_set_timeout_ms(SPI_STD_TIMEOUT_MS);
96 
97  /* Send one byte */
98  spi->ctrl->DR = *src;
99 
100  /* Wait for TX empty */
101  while (!(spi->ctrl->SR & SPI_I2S_FLAG_TXE))
102  {
103  if (time_elapsed(timeout))
104  {
105  return ERROR_TIMEOUT;
106  }
107  }
108 
109  /* Wait for RX finished */
110  while (!(spi->ctrl->SR & SPI_I2S_FLAG_RXNE))
111  {
112  if (time_elapsed(timeout))
113  {
114  return ERROR_TIMEOUT;
115  }
116  }
117 
118  /* Wait for not busy */
119  while (spi->ctrl->SR & SPI_I2S_FLAG_BSY)
120  {
121  if (time_elapsed(timeout))
122  {
123  return ERROR_TIMEOUT;
124  }
125  }
126 
127  /* Write back the received value */
128  *dst = spi->ctrl->DR;
129 
130  return NO_ERROR;
131 }
132 
133 static status_e writeread(const struct heivs_bus_t *bus, uint32_t address, const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, size_t *rlen)
134 {
135  const struct spi_bus_private_t *spi = bus->priv;
136  size_t i;
137  status_e status = NO_ERROR;
138 
139  (void)address;
140 
141  /* Chip select */
142  gpio_set(&spi->gpios[3], spi->options & SPI_OPTION_CS_HIGH);
143 
144  /**
145  * Do as many access as max(src_len, dst_len)
146  */
147  for (i = 0 ; i < max(src_len, dst_len) ; i++)
148  {
149  /* Write to/from this dummy byte when dst_len != src_len */
150  uint8_t dummy = 0xff;
151  const uint8_t *l_src = &dummy;
152  uint8_t *l_dst = &dummy;
153 
154  /* Limit src access to src_len*/
155  if (i < src_len)
156  {
157  l_src = &src[i];
158  }
159 
160  /* Limit dst access to dst_len */
161  if (i < dst_len)
162  {
163  l_dst = &dst[i];
164  }
165 
166  /* Do one access */
167  status = write_read_one(spi, l_src, l_dst);
168  if (status != NO_ERROR)
169  {
170  goto error;
171  }
172 
173  if (i < dst_len)
174  {
175  *rlen = *rlen+1;
176  }
177  }
178 
179 error:
180  /* Chip deselect */
181  gpio_set(&spi->gpios[3], !(spi->options & SPI_OPTION_CS_HIGH));
182 
183  return status;
184 }
185 
186 static status_e read(const struct heivs_bus_t *bus, uint32_t address, uint8_t *data, size_t len, size_t *rlen)
187 {
188  size_t dont_care;
189  (void)address;
190  (void)rlen;
191  return writeread(bus, 0, NULL, 0, data, len, &dont_care);
192 }
193 
194 static status_e write(const struct heivs_bus_t *bus, uint32_t address, const uint8_t *data, size_t len)
195 {
196  size_t dont_care;
197  (void)address;
198  return writeread(bus, 0, data, len, NULL, 0, &dont_care);
199 }
200 
201 static const struct spi_bus_private_t bus_priv[BSP_SPI_BUS_COUNT] =
202 {
203 #if BSP_SPI_BUS_COUNT > 0
204  {
207  .gpios =
208  {
213  },
214  },
215 #endif
216 #if BSP_SPI_BUS_COUNT > 1
217  {
218  .ctrl = BSP_SPI_BUS1_CTRL,
220  .gpios =
221  {
222  BSP_SPI_BUS1_GPIO_MISO,
223  BSP_SPI_BUS1_GPIO_MOSI,
224  BSP_SPI_BUS1_GPIO_SCK,
225  BSP_SPI_BUS1_GPIO_CS,
226  },
227  },
228 #endif
229 #if BSP_SPI_BUS_COUNT > 2
230  {
231  .ctrl = BSP_SPI_BUS2_CTRL,
233  .gpios =
234  {
235  BSP_SPI_BUS2_GPIO_MISO,
236  BSP_SPI_BUS2_GPIO_MOSI,
237  BSP_SPI_BUS2_GPIO_SCK,
238  BSP_SPI_BUS2_GPIO_CS,
239  },
240  },
241 #endif
242 };
243 
244 static struct heivs_bus_var_t bus_var[BSP_SPI_BUS_COUNT];
245 
247 {
248 #if BSP_SPI_BUS_COUNT > 0
249  #ifndef BSP_SPI_BUS0_NAME
250  #define BSP_SPI_BUS0_NAME "bus_spi[0]"
251  #endif
252  {
253  .name = BSP_SPI_BUS0_NAME,
254  .priv = &bus_priv[0],
255  .var = &bus_var[0],
256 
257  ._init = init,
258  ._read = read,
259  ._write = write,
260  ._suspend = suspend,
261  ._writeread = writeread,
262  },
263 #endif
264 #if BSP_SPI_BUS_COUNT > 1
265  #ifndef BSP_SPI_BUS1_NAME
266  #define BSP_SPI_BUS1_NAME "bus_spi[1]"
267  #endif
268  {
269  .name = BSP_SPI_BUS1_NAME,
270  .priv = &bus_priv[1],
271  .var = &bus_var[1],
272 
273  ._init = init,
274  ._read = read,
275  ._write = write,
276  ._suspend = suspend,
277  ._writeread = writeread,
278  },
279 #endif
280 #if BSP_SPI_BUS_COUNT > 2
281  #ifndef BSP_SPI_BUS2_NAME
282  #define BSP_SPI_BUS2_NAME "bus_spi[2]"
283  #endif
284  {
285  .name = BSP_SPI_BUS2_NAME,
286  .priv = &bus_priv[2],
287  .var = &bus_var[2],
288 
289  ._init = init,
290  ._read = read,
291  ._write = write,
292  ._suspend = suspend,
293  ._writeread = writeread,
294  },
295 #endif
296 #if BSP_I2C_BUS_COUNT > 3
297  #error this CPU has no 4 SPI buses
298 #endif
299 };
300 
This file contains all the functions prototypes for the RCC firmware library.
No comment.
Definition: error.h:64
SPI_TypeDef * ctrl
Controller.
Definition: stm32_spi.h:43
uint16_t SPI_DataSize
Definition: stm32f4xx_spi.h:56
Bus handler.
Definition: bus.h:92
const char * name
Definition: bus.h:102
SPI bus.
const void * priv
Definition: bus.h:107
BSP - Board Support Package.
uint16_t SPI_Mode
Definition: stm32f4xx_spi.h:53
const struct heivs_bus_t bus_spi[BSP_SPI_BUS_COUNT]
All SPI busses.
Definition: stm32_spi.c:246
#define BSP_SPI_BUS_COUNT
Number of SPI buses.
Definition: bsp_armebs4.h:38
ssize_t read(int fd, void *buf, size_t count)
simple time abstraction
uint16_t SPI_BaudRatePrescaler
Definition: stm32f4xx_spi.h:69
This file contains all the functions prototypes for the SPI firmware library.
uint16_t SPI_CPOL
Definition: stm32f4xx_spi.h:59
Variable part of the bus description.
Definition: bus.h:79
enum spi_option_e options
Options.
Definition: stm32_spi.h:45
uint16_t SPI_Direction
Definition: stm32f4xx_spi.h:50
Master mode.
Definition: stm32_spi.h:26
static uint32_t time_elapsed(timeout_t timeout)
Is this time passed?
Definition: time.h:71
#define BSP_SPI_BUS0_CTRL
On this controller.
Definition: bsp_armebs4.h:41
static void gpio_set(const struct gpio_t *gpio, uint32_t value)
Set a gpio.
Definition: stm32_gpio.h:260
Mode 3 : CPOL = 1, CPHA = 1.
Definition: stm32_spi.h:32
#define max(a, b)
Maximum between a and b.
Definition: utils.h:47
#define BSP_SPI_BUS0_GPIO_MOSI
MOSI on this pin.
Definition: bsp_armebs4.h:43
Parameter unsupported.
Definition: error.h:56
Mode 2 : CPOL = 1, CPHA = 0.
Definition: stm32_spi.h:31
SPI Init structure definition.
Definition: stm32f4xx_spi.h:48
uint16_t SPI_NSS
Definition: stm32f4xx_spi.h:65
#define BSP_SPI_BUS0_GPIO_MISO
MISO on this pin.
Definition: bsp_armebs4.h:42
const struct gpio_t gpios[4]
Gpios.
Definition: stm32_spi.h:44
Chip select active high.
Definition: stm32_spi.h:35
Mode 0 : CPOL = 0, CPHA = 0.
Definition: stm32_spi.h:29
__IO uint16_t SR
Definition: stm32f4xx.h:842
uint16_t SPI_FirstBit
Definition: stm32f4xx_spi.h:75
__IO uint16_t DR
Definition: stm32f4xx.h:844
uint16_t SPI_CPHA
Definition: stm32f4xx_spi.h:62
Timeout structure.
Definition: time.h:34
SPI specific data.
Definition: stm32_spi.h:41
ssize_t write(int fd, const void *buf, size_t count)
timeout_t time_set_timeout_ms(uint32_t ms)
Set an obscure time at least ms milliseconds in the future.
Definition: time.c:15
Slave mode.
Definition: stm32_spi.h:27
status_e gpio_setup_list(const struct gpio_t gpio[], size_t len)
Setup an array of gpio.
Definition: stm32_gpio.c:47
status_e
Known errors.
Definition: error.h:21
#define ARRAY_SIZE(x)
Number of elements in the array.
Definition: utils.h:19
No error.
Definition: error.h:28
#define BSP_SPI_BUS0_GPIO_CS
CS on this pin.
Definition: bsp_armebs4.h:45
#define BSP_SPI_BUS0_GPIO_SCK
SCK on this pin.
Definition: bsp_armebs4.h:44
Chip select active low.
Definition: stm32_spi.h:34
Mode 1 : CPOL = 0, CPHA = 1.
Definition: stm32_spi.h:30