UoS³ Flight Computer Firmware
 All Data Structures Files Functions Groups Pages
spi.c
Go to the documentation of this file.
1 
11 #include "board.h"
12 #include "../spi.h"
13 #include "../gpio.h"
14 
15 #include "inc/tm4c123gh6pm.h"
16 #include "inc/hw_memmap.h"
17 #include "inc/hw_gpio.h"
18 #include "inc/hw_types.h"
19 
20 #include "driverlib/gpio.h"
21 #include "driverlib/ssi.h"
22 #include "driverlib/sysctl.h"
23 #include "driverlib/pin_map.h"
24 
25 /* Note that this module currently has no locking of the underlying physical port */
26 
27 /* SPI physical port description struct */
28 typedef struct SPI_port {
29  uint32_t peripheral_gpio; // TI Driver GPIO Peripheral Reference
30  uint32_t peripheral_spi; // TI Driver SPI Peripheral Reference
31  uint32_t base_gpio; // TI Driver GPIO Base Reference
32  uint32_t base_spi; // TI Driver SPI Base Reference
33  uint32_t pin_clk_function; // TI Driver SPI CLK Pin Reference
34  uint32_t pin_miso_function; // TI Driver SPI RX Pin Reference
35  uint32_t pin_mosi_function; // TI Driver SPI TX Pin Reference
36  uint8_t pin_clk; // TI Driver CLK Pin Reference
37  uint8_t pin_miso; // TI Driver RX Pin Reference
38  uint8_t pin_mosi; // TI Driver TX Pin Reference
39  uint32_t clockrate; // Clockrate in bps
40  bool initialised;
41 } SPI_port;
42 
43 static SPI_port SPI_ports[1] =
44  {
45  {
46  SYSCTL_PERIPH_GPIOF,
47  SYSCTL_PERIPH_SSI1,
48  GPIO_PORTF_BASE,
49  SSI1_BASE,
50  GPIO_PF2_SSI1CLK,
51  GPIO_PF0_SSI1RX,
52  GPIO_PF1_SSI1TX,
53  GPIO_PIN_2,
54  GPIO_PIN_0,
55  GPIO_PIN_1,
56  5000000,
57  false
58  }
59  };
60 
61 /* SPI virtual port description struct */
62 typedef struct SPI_t {
63  SPI_port *port;
64  uint8_t gpio_cs; // CS GPIO Reference
65  bool wait_miso; // Whether the SPI peripheral waits for SO low (required for cc1120)
66 } SPI_t;
67 
68 /* Array of enabled SPIs */
69 static SPI_t SPI_spis[3] =
70  {
71  {
72  &SPI_ports[0],
73  GPIO_PA3,
74  true
75  },
76  {
77  &SPI_ports[0],
78  GPIO_PF3,
79  true
80  },
81  {
82  &SPI_ports[0],
83  GPIO_PC5,
84  false
85  }
86  };
87 
88 #define NUMBER_OF_SPIS ( sizeof(SPI_spis) / sizeof(SPI_t) )
89 
90 #define check_spi_num(x, y) if(x >= NUMBER_OF_SPIS) { return y; }
91 
92 static void SPI_init(SPI_t* spi)
93 {
94  /* Check Physical SPI is initialised */
95  if(!spi->port->initialised)
96  {
97  /* Set CS[bar] high for all virtual ports */
98  for(uint8_t i=0; i<NUMBER_OF_SPIS; i++)
99  {
100  GPIO_write(SPI_spis[i].gpio_cs, true);
101  }
102 
103  /* Initialise SPI Peripheral if not already initialised */
104  if(!SysCtlPeripheralReady(spi->port->peripheral_spi))
105  {
106  SysCtlPeripheralEnable(spi->port->peripheral_spi);
107  while(!SysCtlPeripheralReady(spi->port->peripheral_spi)) { };
108  }
109 
110  /* Initialise GPIO Peripheral if not already initialised */
111  if(!SysCtlPeripheralReady(spi->port->peripheral_gpio))
112  {
113  SysCtlPeripheralEnable(spi->port->peripheral_gpio);
114  while(!SysCtlPeripheralReady(spi->port->peripheral_gpio)) { };
115  }
116 
117  if(spi->port->base_gpio == GPIO_PORTF_BASE)
118  {
119  // sort out PF0...
120  HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; //Unlock
121  HWREG(GPIO_PORTF_BASE+GPIO_O_CR) |= 0x01; // Enable PF0 AFS
122  HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = 0; // Relock
123  }
124 
125  /* Configure Pins for SPI function */
126  GPIOPinConfigure(spi->port->pin_clk_function);
127  GPIOPinConfigure(spi->port->pin_miso_function);
128  GPIOPinConfigure(spi->port->pin_mosi_function);
129 
130  /* Assign pins to SPI peripheral */
131  GPIOPinTypeSSI(spi->port->base_gpio, spi->port->pin_clk | spi->port->pin_miso | spi->port->pin_mosi);
132  SSIClockSourceSet(spi->port->base_spi, SSI_CLOCK_SYSTEM);
133 
134  /* Set peripheral clockrate */
135  SSIConfigSetExpClk(spi->port->base_spi, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
136  SSI_MODE_MASTER, spi->port->clockrate, 8);
137 
138  SSIEnable(spi->port->base_spi);
139 
140  /* Clear current pending data */
141  uint32_t d;
142  while(SSIDataGetNonBlocking(spi->port->base_spi, &d));
143 
144  spi->port->initialised = true;
145  }
146 }
147 
150 uint8_t SPI_cmd(uint8_t spi_num, uint8_t cmd)
151 {
152  check_spi_num(spi_num, 0);
153  SPI_t *spi = &SPI_spis[spi_num];
154 
155  SPI_init(spi);
156 
157  uint32_t r, d;
158 
159  /* Pull CS_N low and wait for SO to go low before communication starts */
160  GPIO_write(spi->gpio_cs, false);
161 
162  /* Flush Input FIFO */
163  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
164 
165  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
166  if(spi->wait_miso)
167  {
168  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
169  }
170 
171  /* Send Command */
172  SSIDataPut(spi->port->base_spi, (uint32_t)cmd);
173  SSIDataGet(spi->port->base_spi, &r);
174 
175  /* Wait for TX FIFO to be exhausted */
176  while(SSIBusy(spi->port->base_spi)) {};
177 
178  /* De-assert CS (high) */
179  GPIO_write(spi->gpio_cs, true);
180 
181  /* return the status byte value */
182  return (uint8_t)r;
183 }
184 
185 uint8_t SPI_read8(uint8_t spi_num, uint8_t addr, uint8_t *data)
186 {
187  check_spi_num(spi_num, 0);
188  SPI_t *spi = &SPI_spis[spi_num];
189 
190  SPI_init(spi);
191 
192  uint32_t r, d;
193 
194  /* Pull CS_N low */
195  GPIO_write(spi->gpio_cs, false);
196 
197  /* Flush Input FIFO */
198  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
199 
200  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
201  if(spi->wait_miso)
202  {
203  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
204  }
205 
206  /* Write address, read status byte */
207  SSIDataPut(spi->port->base_spi, (uint32_t)(addr));
208  SSIDataGet(spi->port->base_spi, &r);
209 
210  /* Read Data */
211  SSIDataPut(spi->port->base_spi, 0);
212  SSIDataGet(spi->port->base_spi, &d);
213  *data = (uint8_t)d;
214 
215  /* Wait for TX FIFO to be exhausted */
216  while(SSIBusy(spi->port->base_spi)) {};
217 
218  /* De-assert CS (high) */
219  GPIO_write(spi->gpio_cs, true);
220 
221  /* return the status byte value */
222  return (uint8_t)r;
223 }
224 
225 uint8_t SPI_burstread8(uint8_t spi_num, uint8_t addr, uint8_t *data, uint32_t len)
226 {
227  check_spi_num(spi_num, 0);
228  SPI_t *spi = &SPI_spis[spi_num];
229 
230  SPI_init(spi);
231 
232  uint32_t r, d;
233 
234  /* Pull CS_N low */
235  GPIO_write(spi->gpio_cs, false);
236 
237  /* Flush Input FIFO */
238  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
239 
240  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
241  if(spi->wait_miso)
242  {
243  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
244  }
245 
246  /* Transmit address with Read Bit Set */
247  SSIDataPut(spi->port->base_spi, (uint32_t)(addr));
248  SSIDataGet(spi->port->base_spi, &r);
249 
250  while(len--)
251  {
252  SSIDataPut(spi->port->base_spi, 0);
253  SSIDataGet(spi->port->base_spi, &d);
254  *data++ = (uint8_t)d;
255  }
256 
257  /* Wait for TX FIFO to be exhausted */
258  while(SSIBusy(spi->port->base_spi)) {};
259 
260  /* De-assert CS (high) */
261  GPIO_write(spi->gpio_cs, true);
262 
263  /* return the status byte value */
264  return (uint8_t)r;
265 }
266 
267 uint8_t SPI_write8(uint8_t spi_num, uint8_t addr, uint8_t *data)
268 {
269  check_spi_num(spi_num, 0);
270  SPI_t *spi = &SPI_spis[spi_num];
271 
272  SPI_init(spi);
273 
274  uint32_t r, d, w;
275 
276  /* Pull CS_N low */
277  GPIO_write(spi->gpio_cs, false);
278 
279  /* Flush Input FIFO */
280  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
281 
282  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
283  if(spi->wait_miso)
284  {
285  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
286  }
287 
288  /* Write Address, read status byte */
289  SSIDataPut(spi->port->base_spi, (uint32_t)addr);
290  SSIDataGet(spi->port->base_spi, &r);
291 
292  if(data!=NULL)
293  {
294  /* Write Data */
295  w = *data;
296  SSIDataPut(spi->port->base_spi, w);
297  SSIDataGet(spi->port->base_spi, &d);
298  }
299 
300  /* Wait for TX FIFO to be exhausted */
301  while(SSIBusy(spi->port->base_spi)) {};
302 
303  /* De-assert CS (high) */
304  GPIO_write(spi->gpio_cs, true);
305 
306  /* return the status byte value */
307  return (uint8_t)r;
308 }
309 
310 uint8_t SPI_burstwrite8(uint8_t spi_num, uint8_t addr, uint8_t *data, uint32_t len)
311 {
312  check_spi_num(spi_num, 0);
313  SPI_t *spi = &SPI_spis[spi_num];
314 
315  SPI_init(spi);
316 
317  uint32_t r, d, w;
318 
319  /* Pull CS_N low */
320  GPIO_write(spi->gpio_cs, false);
321 
322  /* Flush Input FIFO */
323  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
324 
325  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
326  if(spi->wait_miso)
327  {
328  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
329  }
330 
331  /* Write Address, read status byte */
332  SSIDataPut(spi->port->base_spi, (uint32_t)addr);
333  SSIDataGet(spi->port->base_spi, &r);
334 
335  /* Write data */
336  while(len--)
337  {
338  w = *data;
339  SSIDataPut(spi->port->base_spi, w);
340  SSIDataGet(spi->port->base_spi, &d);
341  data++;
342  }
343 
344  /* Wait for TX FIFO to be exhausted */
345  while(SSIBusy(spi->port->base_spi)) {};
346 
347  /* De-assert CS (high) */
348  GPIO_write(spi->gpio_cs, true);
349 
350  /* return the status byte value */
351  return (uint8_t)r;
352 }
353 
354 uint8_t SPI_read16(uint8_t spi_num, uint16_t addr, uint8_t *data)
355 {
356  check_spi_num(spi_num, 0);
357  SPI_t *spi = &SPI_spis[spi_num];
358 
359  SPI_init(spi);
360 
361  uint32_t r, d;
362 
363  uint8_t addr_msb = (uint8_t)(addr >> 8);
364  uint8_t addr_lsb = (uint8_t)(addr & 0x00FF);
365 
366  /* Pull CS_N low */
367  GPIO_write(spi->gpio_cs, false);
368 
369  /* Flush Input FIFO */
370  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
371 
372  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
373  if(spi->wait_miso)
374  {
375  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
376  }
377 
378  /* Transmit MSB address */
379  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
380  SSIDataGet(spi->port->base_spi, &r);
381 
382  /* Transmit LSB address */
383  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
384  SSIDataGet(spi->port->base_spi, &d);
385 
386  /* Read Result */
387  SSIDataPut(spi->port->base_spi, 0);
388  SSIDataGet(spi->port->base_spi, &d);
389  *data = (uint8_t)d;
390 
391  /* Wait for TX FIFO to be exhausted */
392  while(SSIBusy(spi->port->base_spi)) {};
393 
394  /* De-assert CS (high) */
395  GPIO_write(spi->gpio_cs, true);
396 
397  /* return the status byte value */
398  return (uint8_t)r;
399 }
400 
401 uint8_t SPI_burstread16(uint8_t spi_num, uint16_t addr, uint8_t *data, uint32_t len)
402 {
403  check_spi_num(spi_num, 0);
404  SPI_t *spi = &SPI_spis[spi_num];
405 
406  SPI_init(spi);
407 
408  uint32_t r, d;
409 
410  uint8_t addr_msb = (uint8_t)(addr >> 8);
411  uint8_t addr_lsb = (uint8_t)(addr & 0x00FF);
412 
413  /* Pull CS_N low */
414  GPIO_write(spi->gpio_cs, false);
415 
416  /* Flush Input FIFO */
417  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
418 
419  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
420  if(spi->wait_miso)
421  {
422  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
423  }
424 
425  /* Transmit MSB address */
426  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
427  SSIDataGet(spi->port->base_spi, &r);
428 
429  /* Transmit LSB address */
430  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
431  SSIDataGet(spi->port->base_spi, &d);
432 
433  while(len--)
434  {
435  SSIDataPut(spi->port->base_spi, 0);
436  SSIDataGet(spi->port->base_spi, &d);
437  *data++ = (uint8_t)d;
438  }
439 
440  /* Wait for TX FIFO to be exhausted */
441  while(SSIBusy(spi->port->base_spi)) {};
442 
443  /* De-assert CS (high) */
444  GPIO_write(spi->gpio_cs, true);
445 
446  /* return the status byte value */
447  return (uint8_t)r;
448 }
449 
450 uint8_t SPI_write16(uint8_t spi_num, uint16_t addr, uint8_t *data)
451 {
452  check_spi_num(spi_num, 0);
453  SPI_t *spi = &SPI_spis[spi_num];
454 
455  SPI_init(spi);
456 
457  uint32_t r, d, w;
458 
459  uint8_t addr_msb = (uint8_t)(addr >> 8);
460  uint8_t addr_lsb = (uint8_t)(addr & 0x00FF);
461 
462  /* Pull CS_N low */
463  GPIO_write(spi->gpio_cs, false);
464 
465  /* Flush Input FIFO */
466  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
467 
468  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
469  if(spi->wait_miso)
470  {
471  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
472  }
473 
474  /* Transmit MSB address */
475  SSIDataPut(spi->port->base_spi, (uint32_t)(0x7F & addr_msb));
476  SSIDataGet(spi->port->base_spi, &r);
477 
478  /* Transmit LSB address */
479  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
480  SSIDataGet(spi->port->base_spi, &d);
481 
482  w = *data;
483  SSIDataPut(spi->port->base_spi, w);
484  SSIDataGet(spi->port->base_spi, &d);
485 
486  /* Wait for TX FIFO to be exhausted */
487  while(SSIBusy(spi->port->base_spi)) {};
488 
489  /* De-assert CS (high) */
490  GPIO_write(spi->gpio_cs, true);
491 
492  /* return the status byte value */
493  return (uint8_t)r;
494 }
495 
496 uint8_t SPI_burstwrite16(uint8_t spi_num, uint16_t addr, uint8_t *data, uint32_t len)
497 {
498  check_spi_num(spi_num, 0);
499  SPI_t *spi = &SPI_spis[spi_num];
500 
501  SPI_init(spi);
502 
503  uint32_t r, d, w;
504 
505  uint8_t addr_msb = (uint8_t)(addr >> 8);
506  uint8_t addr_lsb = (uint8_t)(addr & 0x00FF);
507 
508  /* Pull CS_N low */
509  GPIO_write(spi->gpio_cs, false);
510 
511  /* Flush Input FIFO */
512  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
513 
514  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
515  if(spi->wait_miso)
516  {
517  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
518  }
519 
520  /* Transmit MSB address */
521  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
522  SSIDataGet(spi->port->base_spi, &r);
523 
524  /* Transmit LSB address */
525  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
526  SSIDataGet(spi->port->base_spi, &d);
527 
528  while(len--)
529  {
530  w = *(data++);
531  SSIDataPut(spi->port->base_spi, w);
532  SSIDataGet(spi->port->base_spi, &d);
533  }
534 
535  /* Wait for TX FIFO to be exhausted */
536  while(SSIBusy(spi->port->base_spi)) {};
537 
538  /* De-assert CS (high) */
539  GPIO_write(spi->gpio_cs, true);
540 
541  /* return the status byte value */
542  return (uint8_t)r;
543 }
544 
545 uint8_t SPI_read32(uint8_t spi_num, uint32_t addr, uint8_t *data)
546 {
547  check_spi_num(spi_num, 0);
548  SPI_t *spi = &SPI_spis[spi_num];
549 
550  SPI_init(spi);
551 
552  uint32_t r, d;
553 
554  uint8_t addr_mmsb = (uint8_t)(addr >> 24);
555  uint8_t addr_msb = (uint8_t)(addr >> 16);
556  uint8_t addr_lsb = (uint8_t)(addr >> 8);
557  uint8_t addr_llsb = (uint8_t)(addr & 0xFF);
558 
559  /* Pull CS_N low */
560  GPIO_write(spi->gpio_cs, false);
561 
562  /* Flush Input FIFO */
563  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
564 
565  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
566  if(spi->wait_miso)
567  {
568  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
569  }
570 
571  /* Transmit MSB address, reading back status byte */
572  SSIDataPut(spi->port->base_spi, (uint32_t)addr_mmsb);
573  SSIDataGet(spi->port->base_spi, &r);
574 
575  /* Send less significant address bytes */
576  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
577  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
578  SSIDataPut(spi->port->base_spi, (uint32_t)addr_llsb);
579 
580  /* Wait for TX FIFO to be exhausted */
581  while(SSIBusy(spi->port->base_spi)) {};
582 
583  /* Flush RX FIFO */
584  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
585 
586  /* Read Data */
587  SSIDataPut(spi->port->base_spi, 0);
588  SSIDataGet(spi->port->base_spi, &d);
589  *data = (uint8_t)d;
590 
591  /* Wait for TX FIFO to be exhausted */
592  while(SSIBusy(spi->port->base_spi)) {};
593 
594  /* De-assert CS (high) */
595  GPIO_write(spi->gpio_cs, true);
596 
597  /* return the status byte value */
598  return (uint8_t)r;
599 }
600 
601 uint8_t SPI_burstread32(uint8_t spi_num, uint32_t addr, uint8_t *data, uint32_t len)
602 {
603  check_spi_num(spi_num, 0);
604  SPI_t *spi = &SPI_spis[spi_num];
605 
606  SPI_init(spi);
607 
608  uint32_t r, d;
609 
610  uint8_t addr_mmsb = (uint8_t)(addr >> 24);
611  uint8_t addr_msb = (uint8_t)(addr >> 16);
612  uint8_t addr_lsb = (uint8_t)(addr >> 8);
613  uint8_t addr_llsb = (uint8_t)(addr & 0xFF);
614 
615  /* Pull CS_N low */
616  GPIO_write(spi->gpio_cs, false);
617 
618  /* Flush Input FIFO */
619  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
620 
621  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
622  if(spi->wait_miso)
623  {
624  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
625  }
626 
627  /* Transmit MSB address, reading back status byte */
628  SSIDataPut(spi->port->base_spi, (uint32_t)addr_mmsb);
629  SSIDataGet(spi->port->base_spi, &r);
630 
631  /* Send less significant address bytes */
632  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
633  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
634  SSIDataPut(spi->port->base_spi, (uint32_t)addr_llsb);
635 
636  /* Wait for TX FIFO to be exhausted */
637  while(SSIBusy(spi->port->base_spi)) {};
638 
639  /* Flush RX FIFO */
640  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
641 
642  while(len--)
643  {
644  SSIDataPut(spi->port->base_spi, 0);
645  SSIDataGet(spi->port->base_spi, &d);
646  *data++ = (uint8_t)d;
647  }
648 
649  /* Wait for TX FIFO to be exhausted */
650  while(SSIBusy(spi->port->base_spi)) {};
651 
652  /* De-assert CS (high) */
653  GPIO_write(spi->gpio_cs, true);
654 
655  /* return the status byte value */
656  return (uint8_t)r;
657 }
658 
659 uint8_t SPI_write32(uint8_t spi_num, uint32_t addr, uint8_t *data)
660 {
661  check_spi_num(spi_num, 0);
662  SPI_t *spi = &SPI_spis[spi_num];
663 
664  SPI_init(spi);
665 
666  uint32_t r, d, w;
667 
668  uint8_t addr_mmsb = (uint8_t)(addr >> 24);
669  uint8_t addr_msb = (uint8_t)(addr >> 16);
670  uint8_t addr_lsb = (uint8_t)(addr >> 8);
671  uint8_t addr_llsb = (uint8_t)(addr & 0xFF);
672 
673  /* Pull CS_N low */
674  GPIO_write(spi->gpio_cs, false);
675 
676  /* Flush Input FIFO */
677  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
678 
679  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
680  if(spi->wait_miso)
681  {
682  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
683  }
684 
685  /* Transmit MSB address, reading back status byte */
686  SSIDataPut(spi->port->base_spi, (uint32_t)addr_mmsb);
687  SSIDataGet(spi->port->base_spi, &r);
688 
689  /* Send less significant address bytes */
690  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
691  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
692  SSIDataPut(spi->port->base_spi, (uint32_t)addr_llsb);
693 
694  w = *data;
695  SSIDataPut(spi->port->base_spi, w);
696 
697  /* Wait for TX FIFO to be exhausted */
698  while(SSIBusy(spi->port->base_spi)) {};
699 
700  /* De-assert CS (high) */
701  GPIO_write(spi->gpio_cs, true);
702 
703  /* return the status byte value */
704  return (uint8_t)r;
705 }
706 
707 uint8_t SPI_burstwrite32(uint8_t spi_num, uint32_t addr, uint8_t *data, uint32_t len)
708 {
709  check_spi_num(spi_num, 0);
710  SPI_t *spi = &SPI_spis[spi_num];
711 
712  SPI_init(spi);
713 
714  uint32_t r, d, w;
715 
716  uint8_t addr_mmsb = (uint8_t)(addr >> 24);
717  uint8_t addr_msb = (uint8_t)(addr >> 16);
718  uint8_t addr_lsb = (uint8_t)(addr >> 8);
719  uint8_t addr_llsb = (uint8_t)(addr & 0xFF);
720 
721  /* Pull CS_N low */
722  GPIO_write(spi->gpio_cs, false);
723 
724  /* Flush Input FIFO */
725  while(SSIDataGetNonBlocking(spi->port->base_spi, &d)) {};
726 
727  /* If configured, wait for MISO to go low (indicates clock stability for cc1120) */
728  if(spi->wait_miso)
729  {
730  while(GPIOPinRead(spi->port->base_gpio, spi->port->pin_miso) & spi->port->pin_miso) {};
731  }
732 
733  /* Transmit MSB address, reading back status byte */
734  SSIDataPut(spi->port->base_spi, (uint32_t)addr_mmsb);
735  SSIDataGet(spi->port->base_spi, &r);
736 
737  /* Send less significant address bytes */
738  SSIDataPut(spi->port->base_spi, (uint32_t)addr_msb);
739  SSIDataPut(spi->port->base_spi, (uint32_t)addr_lsb);
740  SSIDataPut(spi->port->base_spi, (uint32_t)addr_llsb);
741 
742  /* Put bytes into TX FIFO */
743  while(len--)
744  {
745  w = *(data++);
746  SSIDataPut(spi->port->base_spi, w);
747  }
748 
749  /* Wait for TX FIFO to be exhausted */
750  while(SSIBusy(spi->port->base_spi)) {};
751 
752  /* De-assert CS (high) */
753  GPIO_write(spi->gpio_cs, true);
754 
755  /* return the status byte value */
756  return (uint8_t)r;
757 }
758 
uint8_t SPI_write32(uint8_t spi_num, uint32_t addr, uint8_t *data)
Definition: spi.c:118
uint8_t SPI_burstread8(uint8_t spi_num, uint8_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:32
uint8_t SPI_burstread32(uint8_t spi_num, uint32_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:108
Definition: spi.c:62
uint8_t SPI_burstwrite8(uint8_t spi_num, uint8_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:51
uint8_t SPI_read32(uint8_t spi_num, uint32_t addr, uint8_t *data)
Definition: spi.c:99
uint8_t SPI_burstread16(uint8_t spi_num, uint16_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:70
Definition: spi.c:28
uint8_t SPI_cmd(uint8_t spi_num, uint8_t cmd)
Definition: spi.c:15
uint8_t SPI_write8(uint8_t spi_num, uint8_t addr, uint8_t *data)
Definition: spi.c:42
uint8_t SPI_burstwrite16(uint8_t spi_num, uint16_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:89
uint8_t SPI_write16(uint8_t spi_num, uint16_t addr, uint8_t *data)
Definition: spi.c:80
uint8_t SPI_read8(uint8_t spi_num, uint8_t addr, uint8_t *data)
Definition: spi.c:23
uint8_t SPI_read16(uint8_t spi_num, uint16_t addr, uint8_t *data)
Definition: spi.c:61
void GPIO_write(uint8_t gpio_num, bool state)
Definition: gpio.c:23
uint8_t SPI_burstwrite32(uint8_t spi_num, uint32_t addr, uint8_t *data, uint32_t len)
Definition: spi.c:127