SAM4SD32 (SAM4S-EK2)
Loading...
Searching...
No Matches
Serial Peripheral Interface (SPI)

See Quickstart guide for SAM SPI driver. More...

Topics

 Legacy SPI group alias

Macros

#define SPI_WPMR_WPKEY_PASSWD   SPI_WPMR_WPKEY((uint32_t) 0x535049)

Functions

int16_t spi_calc_baudrate_div (const uint32_t baudrate, uint32_t mck)
 Calculate the baudrate divider.
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).
void spi_disable_clock (Spi *p_spi)
 Disable SPI clock.
void spi_enable_clock (Spi *p_spi)
 Enable SPI clock.
uint32_t spi_get_writeprotect_status (Spi *p_spi)
 Indicate write protect status.
spi_status_t spi_read (Spi *p_spi, uint16_t *us_data, uint8_t *p_pcs)
 Read the received data and it's peripheral chip select value.
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).
void spi_set_bits_per_transfer (Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_bits)
 Set number of bits per transfer.
void spi_set_clock_phase (Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase)
 Set Data Capture Phase.
void spi_set_clock_polarity (Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_polarity)
 Set clock default state.
void spi_set_delay_between_chip_select (Spi *p_spi, uint32_t ul_delay)
 Set delay between chip selects (in number of MCK clocks).
void spi_set_peripheral_chip_select_value (Spi *p_spi, uint32_t ul_value)
 Set Peripheral Chip Select (PCS) value.
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.
void spi_set_writeprotect (Spi *p_spi, uint32_t ul_enable)
 Enable or disable write protection of SPI registers.
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.

Detailed Description

See Quickstart guide for SAM SPI driver.

The SPI circuit is a synchronous serial data link that provides communication with external devices in Master or Slave mode. Connection to Peripheral DMA Controller channel capabilities optimizes data transfers.

Macro Definition Documentation

◆ SPI_WPMR_WPKEY_PASSWD

#define SPI_WPMR_WPKEY_PASSWD   SPI_WPMR_WPKEY((uint32_t) 0x535049)

Definition at line 52 of file spi.c.

Referenced by spi_set_writeprotect().

Function Documentation

◆ spi_calc_baudrate_div()

int16_t spi_calc_baudrate_div ( const uint32_t baudrate,
uint32_t mck )

Calculate the baudrate divider.

Parameters
baudrateBaudrate value.
mckSPI module input clock frequency (MCK clock, Hz).
Returns
Divider or error code.
Return values
>0 Success.
<0 Error.

Definition at line 362 of file spi.c.

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}

◆ spi_configure_cs_behavior()

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).

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
ul_cs_behaviorBehavior of the Chip Select after transfer.

Definition at line 323 of file spi.c.

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}
#define SPI_CSR_CSAAT
(SPI_CSR[4]) Chip Select Active After Transfer
#define SPI_CSR_CSNAAT
(SPI_CSR[4]) Chip Select Not Active After Transfer (Ignored if CSAAT = 1)
@ SPI_CS_KEEP_LOW
CS does not rise until a new transfer is requested on different chip select.
Definition spi.h:68
@ SPI_CS_RISE_FORCED
CS is de-asserted systematically during a time DLYBCS.
Definition spi.h:72
@ SPI_CS_RISE_NO_TX
CS rises if there is no more data to transfer.
Definition spi.h:70
__IO uint32_t SPI_CSR[4]
(Spi Offset: 0x30) Chip Select Register

References SPI_CS_KEEP_LOW, SPI_CS_RISE_FORCED, SPI_CS_RISE_NO_TX, Spi::SPI_CSR, SPI_CSR_CSAAT, and SPI_CSR_CSNAAT.

◆ spi_disable_clock()

void spi_disable_clock ( Spi * p_spi)

Disable SPI clock.

Parameters
p_spiPointer to an SPI instance.

Definition at line 123 of file spi.c.

124{
125#if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG51|| SAMG53|| SAMG54)
126 UNUSED(p_spi);
127 sysclk_disable_peripheral_clock(ID_SPI);
128#elif (SAM3XA || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
129 if (p_spi == SPI0) {
130 sysclk_disable_peripheral_clock(ID_SPI0);
131 }
132 #ifdef SPI1
133 else if (p_spi == SPI1) {
134 sysclk_disable_peripheral_clock(ID_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
177 sysclk_disable_peripheral_clock(p_spi);
178#endif
179}
#define ID_SPI
Serial Peripheral Interface (SPI).
Definition sam4sd32c.h:339

References ID_SPI.

◆ spi_enable_clock()

void spi_enable_clock ( Spi * p_spi)

Enable SPI clock.

Parameters
p_spiPointer to an SPI instance.

Definition at line 60 of file spi.c.

61{
62#if (SAM4S || SAM3S || SAM3N || SAM3U || SAM4E || SAM4N || SAMG51|| SAMG53|| SAMG54)
63 UNUSED(p_spi);
64 sysclk_enable_peripheral_clock(ID_SPI);
65#elif (SAM3XA || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70)
66 if (p_spi == SPI0) {
67 sysclk_enable_peripheral_clock(ID_SPI0);
68 }
69 #ifdef SPI1
70 else if (p_spi == SPI1) {
71 sysclk_enable_peripheral_clock(ID_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
114 sysclk_enable_peripheral_clock(p_spi);
115#endif
116}

References ID_SPI.

◆ spi_get_writeprotect_status()

uint32_t spi_get_writeprotect_status ( Spi * p_spi)

Indicate write protect status.

Parameters
p_spiPointer to an SPI instance.
Returns
SPI_WPSR value.

Definition at line 444 of file spi.c.

445{
446 return p_spi->SPI_WPSR;
447}
__I uint32_t SPI_WPSR
(Spi Offset: 0xE8) Write Protection Status Register

References Spi::SPI_WPSR.

◆ spi_read()

spi_status_t spi_read ( Spi * p_spi,
uint16_t * us_data,
uint8_t * p_pcs )

Read the received data and it's peripheral chip select value.

While SPI works in fixed peripheral select mode, the peripheral chip select value is meaningless.

Parameters
p_spiPointer to an SPI instance.
us_dataPointer to the location where to store the received data word.
p_pcsPointer to fill Peripheral Chip Select Value.
Return values
SPI_OKon Success.
SPI_ERROR_TIMEOUTon Time-out.

Definition at line 224 of file spi.c.

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;
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}
#define SPI_RDR_RD_Msk
(SPI_RDR) Receive Data
#define SPI_RDR_PCS_Msk
(SPI_RDR) Peripheral Chip Select
#define SPI_RDR_PCS_Pos
#define SPI_SR_RDRF
(SPI_SR) Receive Data Register Full
#define SPI_TIMEOUT
Time-out value (number of attempts).
Definition spi.h:51
static uint32_t spi_get_peripheral_select_mode(Spi *p_spi)
Get Peripheral Select mode.
Definition spi.h:192
@ SPI_OK
Definition spi.h:57
@ SPI_ERROR_TIMEOUT
Definition spi.h:58
__I uint32_t SPI_SR
(Spi Offset: 0x10) Status Register
__I uint32_t SPI_RDR
(Spi Offset: 0x08) Receive Data Register

References SPI_ERROR_TIMEOUT, spi_get_peripheral_select_mode(), SPI_OK, Spi::SPI_RDR, SPI_RDR_PCS_Msk, SPI_RDR_PCS_Pos, SPI_RDR_RD_Msk, Spi::SPI_SR, SPI_SR_RDRF, and SPI_TIMEOUT.

◆ spi_set_baudrate_div()

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).

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
uc_baudrate_dividerBaudrate divider from MCK.
Returns
Return values
0Success.
-1Error.

Definition at line 385 of file spi.c.

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}
#define SPI_CSR_SCBR_Msk
(SPI_CSR[4]) Serial Clock Baud Rate
#define SPI_CSR_SCBR(value)

References Spi::SPI_CSR, SPI_CSR_SCBR, and SPI_CSR_SCBR_Msk.

◆ spi_set_bits_per_transfer()

void spi_set_bits_per_transfer ( Spi * p_spi,
uint32_t ul_pcs_ch,
uint32_t ul_bits )

Set number of bits per transfer.

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
ul_bitsNumber of bits (8~16), use the pattern defined in the device header file.

Definition at line 345 of file spi.c.

347{
348 p_spi->SPI_CSR[ul_pcs_ch] &= (~SPI_CSR_BITS_Msk);
349 p_spi->SPI_CSR[ul_pcs_ch] |= ul_bits;
350}
#define SPI_CSR_BITS_Msk
(SPI_CSR[4]) Bits Per Transfer

References Spi::SPI_CSR, and SPI_CSR_BITS_Msk.

◆ spi_set_clock_phase()

void spi_set_clock_phase ( Spi * p_spi,
uint32_t ul_pcs_ch,
uint32_t ul_phase )

Set Data Capture Phase.

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
ul_phaseData capture on the rising/falling edge of clock.

Definition at line 307 of file spi.c.

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}
#define SPI_CSR_NCPHA
(SPI_CSR[4]) Clock Phase

References Spi::SPI_CSR, and SPI_CSR_NCPHA.

◆ spi_set_clock_polarity()

void spi_set_clock_polarity ( Spi * p_spi,
uint32_t ul_pcs_ch,
uint32_t ul_polarity )

Set clock default state.

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
ul_polarityDefault clock state is logical one(high)/zero(low).

Definition at line 290 of file spi.c.

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}
#define SPI_CSR_CPOL
(SPI_CSR[4]) Clock Polarity

References Spi::SPI_CSR, and SPI_CSR_CPOL.

◆ spi_set_delay_between_chip_select()

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 inserted by default.

Parameters
p_spiPointer to an SPI instance.
ul_delayDelay between chip selects (in number of MCK clocks).

Definition at line 206 of file spi.c.

207{
208 p_spi->SPI_MR &= (~SPI_MR_DLYBCS_Msk);
209 p_spi->SPI_MR |= SPI_MR_DLYBCS(ul_delay);
210}
#define SPI_MR_DLYBCS(value)
#define SPI_MR_DLYBCS_Msk
(SPI_MR) Delay Between Chip Selects
__IO uint32_t SPI_MR
(Spi Offset: 0x04) Mode Register

References Spi::SPI_MR, SPI_MR_DLYBCS, and SPI_MR_DLYBCS_Msk.

◆ spi_set_peripheral_chip_select_value()

void spi_set_peripheral_chip_select_value ( Spi * p_spi,
uint32_t ul_value )

Set Peripheral Chip Select (PCS) value.

Parameters
p_spiPointer to an SPI instance.
ul_valuePeripheral Chip Select value. If PCS decode mode is not used, use spi_get_pcs to build the value to use. On reset the decode mode is not enabled. The decode mode can be enabled/disabled by follow functions: spi_enable_peripheral_select_decode, spi_disable_peripheral_select_decode.

Definition at line 193 of file spi.c.

194{
195 p_spi->SPI_MR &= (~SPI_MR_PCS_Msk);
196 p_spi->SPI_MR |= SPI_MR_PCS(ul_value);
197}
#define SPI_MR_PCS_Msk
(SPI_MR) Peripheral Chip Select
#define SPI_MR_PCS(value)

References Spi::SPI_MR, SPI_MR_PCS, and SPI_MR_PCS_Msk.

◆ spi_set_transfer_delay()

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.

Parameters
p_spiPointer to an SPI instance.
ul_pcs_chPeripheral Chip Select channel (0~3).
uc_dlybsDelay before SPCK (in number of MCK clocks).
uc_dlybctDelay between consecutive transfers (in number of MCK clocks).

Definition at line 405 of file spi.c.

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}
#define SPI_CSR_DLYBS(value)
#define SPI_CSR_DLYBCT(value)
#define SPI_CSR_DLYBS_Msk
(SPI_CSR[4]) Delay Before SPCK
#define SPI_CSR_DLYBCT_Msk
(SPI_CSR[4]) Delay Between Consecutive Transfers

References Spi::SPI_CSR, SPI_CSR_DLYBCT, SPI_CSR_DLYBCT_Msk, SPI_CSR_DLYBS, and SPI_CSR_DLYBS_Msk.

◆ spi_set_writeprotect()

void spi_set_writeprotect ( Spi * p_spi,
uint32_t ul_enable )

Enable or disable write protection of SPI registers.

Parameters
p_spiPointer to an SPI instance.
ul_enable1 to enable, 0 to disable.

Definition at line 420 of file spi.c.

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}
#define SPI_WPMR_WPEN
(SPI_WPMR) Write Protect Enable
#define SPI_WPMR_WPKEY_PASSWD
Definition spi.c:52
__IO uint32_t SPI_WPMR
(Spi Offset: 0xE4) Write Protection Control Register

References Spi::SPI_WPMR, SPI_WPMR_WPEN, and SPI_WPMR_WPKEY_PASSWD.

◆ spi_write()

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.

Parameters
p_spiPointer to an SPI instance.
us_dataThe data to transmit.
uc_pcsPeripheral Chip Select Value while SPI works in peripheral select mode, otherwise it's meaningless.
uc_lastIndicate whether this data is the last one while SPI is working in variable peripheral select mode.
Return values
SPI_OKon Success.
SPI_ERROR_TIMEOUTon Time-out.

Definition at line 257 of file spi.c.

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
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}
#define SPI_TDR_LASTXFER
(SPI_TDR) Last Transfer
#define SPI_TDR_TD(value)
#define SPI_SR_TDRE
(SPI_SR) Transmit Data Register Empty
#define SPI_TDR_PCS(value)
__O uint32_t SPI_TDR
(Spi Offset: 0x0C) Transmit Data Register

References SPI_ERROR_TIMEOUT, spi_get_peripheral_select_mode(), SPI_OK, Spi::SPI_SR, SPI_SR_TDRE, Spi::SPI_TDR, SPI_TDR_LASTXFER, SPI_TDR_PCS, SPI_TDR_TD, and SPI_TIMEOUT.