spi.c
Go to the documentation of this file.
1 
33 /*
34  * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35  */
36 
37 #include "spi.h"
38 #include "sysclk.h"
39 
51 #ifndef SPI_WPMR_WPKEY_PASSWD
52 #define SPI_WPMR_WPKEY_PASSWD SPI_WPMR_WPKEY((uint32_t) 0x535049)
53 #endif
54 
60 void spi_enable_clock(Spi *p_spi)
61 {
62 #if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG51|| SAMG53|| SAMG54)
63  UNUSED(p_spi);
65 #elif (SAM3XA || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
66  if (p_spi == SPI0) {
68  }
69  #ifdef SPI1
70  else if (p_spi == SPI1) {
72  }
73  #endif
74 #elif (SAMG55)
75  if (p_spi == SPI0) {
76  sysclk_enable_peripheral_clock(ID_FLEXCOM0);
77  }
78  #ifdef SPI1
79  else if (p_spi == SPI1) {
80  sysclk_enable_peripheral_clock(ID_FLEXCOM1);
81  }
82  #endif
83  #ifdef SPI2
84  else if (p_spi == SPI2) {
85  sysclk_enable_peripheral_clock(ID_FLEXCOM2);
86  }
87  #endif
88  #ifdef SPI3
89  else if (p_spi == SPI3) {
90  sysclk_enable_peripheral_clock(ID_FLEXCOM3);
91  }
92  #endif
93  #ifdef SPI4
94  else if (p_spi == SPI4) {
95  sysclk_enable_peripheral_clock(ID_FLEXCOM4);
96  }
97  #endif
98  #ifdef SPI5
99  else if (p_spi == SPI5) {
100  sysclk_enable_peripheral_clock(ID_FLEXCOM5);
101  }
102  #endif
103  #ifdef SPI6
104  else if (p_spi == SPI6) {
105  sysclk_enable_peripheral_clock(ID_FLEXCOM6);
106  }
107  #endif
108  #ifdef SPI7
109  else if (p_spi == SPI7) {
110  sysclk_enable_peripheral_clock(ID_FLEXCOM7);
111  }
112  #endif
113 #elif SAM4L
115 #endif
116 }
117 
123 void spi_disable_clock(Spi *p_spi)
124 {
125 #if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG51|| SAMG53|| SAMG54)
126  UNUSED(p_spi);
128 #elif (SAM3XA || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
129  if (p_spi == SPI0) {
131  }
132  #ifdef SPI1
133  else if (p_spi == SPI1) {
135  }
136  #endif
137 #elif (SAMG55)
138  if (p_spi == SPI0) {
139  sysclk_disable_peripheral_clock(ID_FLEXCOM0);
140  }
141  #ifdef SPI1
142  else if (p_spi == SPI1) {
143  sysclk_disable_peripheral_clock(ID_FLEXCOM1);
144  }
145  #endif
146  #ifdef SPI2
147  else if (p_spi == SPI2) {
148  sysclk_disable_peripheral_clock(ID_FLEXCOM2);
149  }
150  #endif
151  #ifdef SPI3
152  else if (p_spi == SPI3) {
153  sysclk_disable_peripheral_clock(ID_FLEXCOM3);
154  }
155  #endif
156  #ifdef SPI4
157  else if (p_spi == SPI4) {
158  sysclk_disable_peripheral_clock(ID_FLEXCOM4);
159  }
160  #endif
161  #ifdef SPI5
162  else if (p_spi == SPI5) {
163  sysclk_disable_peripheral_clock(ID_FLEXCOM5);
164  }
165  #endif
166  #ifdef SPI6
167  else if (p_spi == SPI6) {
168  sysclk_disable_peripheral_clock(ID_FLEXCOM6);
169  }
170  #endif
171  #ifdef SPI7
172  else if (p_spi == SPI7) {
173  sysclk_disable_peripheral_clock(ID_FLEXCOM7);
174  }
175  #endif
176 #elif SAM4L
178 #endif
179 }
180 
193 void spi_set_peripheral_chip_select_value(Spi *p_spi, uint32_t ul_value)
194 {
195  p_spi->SPI_MR &= (~SPI_MR_PCS_Msk);
196  p_spi->SPI_MR |= SPI_MR_PCS(ul_value);
197 }
198 
206 void spi_set_delay_between_chip_select(Spi *p_spi, uint32_t ul_delay)
207 {
208  p_spi->SPI_MR &= (~SPI_MR_DLYBCS_Msk);
209  p_spi->SPI_MR |= SPI_MR_DLYBCS(ul_delay);
210 }
211 
224 spi_status_t spi_read(Spi *p_spi, uint16_t *us_data, uint8_t *p_pcs)
225 {
226  uint32_t timeout = SPI_TIMEOUT;
227  static uint32_t reg_value;
228 
229  while (!(p_spi->SPI_SR & SPI_SR_RDRF)) {
230  if (!timeout--) {
231  return SPI_ERROR_TIMEOUT;
232  }
233  }
234 
235  reg_value = p_spi->SPI_RDR;
236  if (spi_get_peripheral_select_mode(p_spi)) {
237  *p_pcs = (uint8_t) ((reg_value & SPI_RDR_PCS_Msk) >> SPI_RDR_PCS_Pos);
238  }
239  *us_data = (uint16_t) (reg_value & SPI_RDR_RD_Msk);
240 
241  return SPI_OK;
242 }
243 
257 spi_status_t spi_write(Spi *p_spi, uint16_t us_data,
258  uint8_t uc_pcs, uint8_t uc_last)
259 {
260  uint32_t timeout = SPI_TIMEOUT;
261  uint32_t value;
262 
263  while (!(p_spi->SPI_SR & SPI_SR_TDRE)) {
264  if (!timeout--) {
265  return SPI_ERROR_TIMEOUT;
266  }
267  }
268 
269  if (spi_get_peripheral_select_mode(p_spi)) {
270  value = SPI_TDR_TD(us_data) | SPI_TDR_PCS(uc_pcs);
271  if (uc_last) {
272  value |= SPI_TDR_LASTXFER;
273  }
274  } else {
275  value = SPI_TDR_TD(us_data);
276  }
277 
278  p_spi->SPI_TDR = value;
279 
280  return SPI_OK;
281 }
282 
290 void spi_set_clock_polarity(Spi *p_spi, uint32_t ul_pcs_ch,
291  uint32_t ul_polarity)
292 {
293  if (ul_polarity) {
294  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CPOL;
295  } else {
296  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CPOL);
297  }
298 }
299 
307 void spi_set_clock_phase(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase)
308 {
309  if (ul_phase) {
310  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_NCPHA;
311  } else {
312  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_NCPHA);
313  }
314 }
315 
323 void spi_configure_cs_behavior(Spi *p_spi, uint32_t ul_pcs_ch,
324  uint32_t ul_cs_behavior)
325 {
326  if (ul_cs_behavior == SPI_CS_RISE_FORCED) {
327  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSAAT);
328  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CSNAAT;
329  } else if (ul_cs_behavior == SPI_CS_RISE_NO_TX) {
330  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSAAT);
331  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_CSNAAT);
332  } else if (ul_cs_behavior == SPI_CS_KEEP_LOW) {
333  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_CSAAT;
334  }
335 }
336 
345 void spi_set_bits_per_transfer(Spi *p_spi, uint32_t ul_pcs_ch,
346  uint32_t ul_bits)
347 {
348  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_BITS_Msk);
349  p_spi->SPI_CSR[ul_pcs_ch] |= ul_bits;
350 }
351 
362 int16_t spi_calc_baudrate_div(const uint32_t baudrate, uint32_t mck)
363 {
364  int baud_div = div_ceil(mck, baudrate);
365 
366  /* The value of baud_div is from 1 to 255 in the SCBR field. */
367  if (baud_div <= 0 || baud_div > 255) {
368  return -1;
369  }
370 
371  return baud_div;
372 }
373 
385 int16_t spi_set_baudrate_div(Spi *p_spi, uint32_t ul_pcs_ch,
386  uint8_t uc_baudrate_divider)
387 {
388  /* Programming the SCBR field to 0 is forbidden */
389  if (!uc_baudrate_divider){
390  return -1;
391  }
392  p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_SCBR_Msk);
393  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_SCBR(uc_baudrate_divider);
394  return 0;
395 }
396 
405 void spi_set_transfer_delay(Spi *p_spi, uint32_t ul_pcs_ch,
406  uint8_t uc_dlybs, uint8_t uc_dlybct)
407 {
408  p_spi->SPI_CSR[ul_pcs_ch] &= ~(SPI_CSR_DLYBS_Msk | SPI_CSR_DLYBCT_Msk);
409  p_spi->SPI_CSR[ul_pcs_ch] |= SPI_CSR_DLYBS(uc_dlybs)
410  | SPI_CSR_DLYBCT(uc_dlybct);
411 }
412 
413 
420 void spi_set_writeprotect(Spi *p_spi, uint32_t ul_enable)
421 {
422 #if SAM4L
423  if (ul_enable) {
424  p_spi->SPI_WPCR = SPI_WPCR_SPIWPKEY_VALUE | SPI_WPCR_SPIWPEN;
425  } else {
426  p_spi->SPI_WPCR = SPI_WPCR_SPIWPKEY_VALUE;
427  }
428 #else
429  if (ul_enable) {
431  } else {
433  }
434 #endif
435 }
436 
445 {
446  return p_spi->SPI_WPSR;
447 }
448 
#define SPI_WPMR_WPEN
(SPI_WPMR) Write Protection Enable
__I uint32_t SPI_SR
(Spi Offset: 0x10) Status Register
#define div_ceil(a, b)
Calculate using integer arithmetic.
Definition: compiler.h:1038
void spi_set_clock_phase(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase)
Set Data Capture Phase.
Definition: spi.c:307
void spi_configure_cs_behavior(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_cs_behavior)
Configure CS behavior for SPI transfer (spi_cs_behavior_t).
Definition: spi.c:323
#define SPI_CSR_SCBR_Msk
(SPI_CSR[4]) Serial Clock Bit Rate
#define SPI_CSR_SCBR(value)
#define SPI1
(SPI1 ) Base Address
Definition: same70q19.h:607
__IO uint32_t SPI_CSR[4]
(Spi Offset: 0x30) Chip Select Register (CS_number = 0)
#define UNUSED(v)
Marking v as a unused parameter or value.
Definition: compiler.h:86
__I uint32_t SPI_RDR
(Spi Offset: 0x08) Receive Data Register
#define ID_SPI1
Serial Peripheral Interface 1 (SPI1)
Definition: same70q19.h:500
spi_status_t spi_read(Spi *p_spi, uint16_t *us_data, uint8_t *p_pcs)
Read the received data and it&#39;s peripheral chip select value. While SPI works in fixed peripheral sel...
Definition: spi.c:224
int16_t spi_set_baudrate_div(Spi *p_spi, uint32_t ul_pcs_ch, uint8_t uc_baudrate_divider)
Set Serial Clock Baud Rate divider value (SCBR).
Definition: spi.c:385
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:3589
#define SPI_MR_DLYBCS(value)
Spi hardware registers.
void spi_set_bits_per_transfer(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_bits)
Set number of bits per transfer.
Definition: spi.c:345
#define SPI_CSR_CSNAAT
(SPI_CSR[4]) Chip Select Not Active After Transfer (Ignored if CSAAT = 1)
void spi_set_clock_polarity(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_polarity)
Set clock default state.
Definition: spi.c:290
#define SPI_CSR_DLYBS_Msk
(SPI_CSR[4]) Delay Before SPCK
#define SPI_TDR_TD(value)
#define ID_SPI0
Serial Peripheral Interface 0 (SPI0)
Definition: same70n19.h:450
#define SPI_MR_PCS(value)
void spi_enable_clock(Spi *p_spi)
Enable SPI clock.
Definition: spi.c:60
__IO uint32_t SPI_WPMR
(Spi Offset: 0xE4) Write Protection Mode Register
#define SPI_CSR_BITS_Msk
(SPI_CSR[4]) Bits Per Transfer
#define SPI_RDR_PCS_Msk
(SPI_RDR) Peripheral Chip Select
__O uint32_t SPI_TDR
(Spi Offset: 0x0C) Transmit Data Register
spi_status_t spi_write(Spi *p_spi, uint16_t us_data, uint8_t uc_pcs, uint8_t uc_last)
Write the transmitted data with specified peripheral chip select value.
Definition: spi.c:257
#define SPI_CSR_DLYBCT(value)
static void sysclk_disable_peripheral_clock(uint32_t ul_id)
Disable a peripheral&#39;s clock.
#define SPI_SR_TDRE
(SPI_SR) Transmit Data Register Empty (cleared by writing SPI_TDR)
spi_status_t
void spi_disable_clock(Spi *p_spi)
Disable SPI clock.
Definition: spi.c:123
void spi_set_peripheral_chip_select_value(Spi *p_spi, uint32_t ul_value)
Set Peripheral Chip Select (PCS) value.
Definition: spi.c:193
#define SPI0
(SPI0 ) Base Address
Definition: same70n19.h:541
#define SPI_TDR_PCS(value)
#define SPI_WPMR_WPKEY_PASSWD
Definition: spi.c:52
#define SPI_CSR_CPOL
(SPI_CSR[4]) Clock Polarity
#define SPI_MR_PCS_Msk
(SPI_MR) Peripheral Chip Select
int16_t spi_calc_baudrate_div(const uint32_t baudrate, uint32_t mck)
Calculate the baudrate divider.
Definition: spi.c:362
void spi_set_transfer_delay(Spi *p_spi, uint32_t ul_pcs_ch, uint8_t uc_dlybs, uint8_t uc_dlybct)
Configure timing for SPI transfer.
Definition: spi.c:405
Serial Peripheral Interface (SPI) driver for SAM.
__I uint32_t SPI_WPSR
(Spi Offset: 0xE8) Write Protection Status Register
void spi_set_delay_between_chip_select(Spi *p_spi, uint32_t ul_delay)
Set delay between chip selects (in number of MCK clocks). If DLYBCS <= 6, 6 MCK clocks will be insert...
Definition: spi.c:206
#define SPI_CSR_NCPHA
(SPI_CSR[4]) Clock Phase
void spi_set_writeprotect(Spi *p_spi, uint32_t ul_enable)
Enable or disable write protection of SPI registers.
Definition: spi.c:420
#define SPI_SR_RDRF
(SPI_SR) Receive Data Register Full (cleared by reading SPI_RDR)
#define SPI_TDR_LASTXFER
(SPI_TDR) Last Transfer
static void sysclk_enable_peripheral_clock(uint32_t ul_id)
Enable a peripheral&#39;s clock.
static uint32_t spi_get_peripheral_select_mode(Spi *p_spi)
Get Peripheral Select mode.
#define SPI_RDR_RD_Msk
(SPI_RDR) Receive Data
#define SPI_CSR_DLYBCT_Msk
(SPI_CSR[4]) Delay Between Consecutive Transfers
#define SPI_TIMEOUT
__IO uint32_t SPI_MR
(Spi Offset: 0x04) Mode Register
#define SPI_CSR_DLYBS(value)
#define SPI_MR_DLYBCS_Msk
(SPI_MR) Delay Between Chip Selects
uint32_t spi_get_writeprotect_status(Spi *p_spi)
Indicate write protect status.
Definition: spi.c:444
#define SPI_CSR_CSAAT
(SPI_CSR[4]) Chip Select Active After Transfer


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58