rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Functions | Variables
SPI

Functions

static int32_t spi_detectPCS (bool isMaster, ioportid_t ssport, uint16_t sspad, int *alt)
 
static int32_t spi_detectBaudRate (SPIDriver *spip)
 
void spi_lld_master_callback (LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData)
 
void spi_lld_slave_callback (LPSPI_Type *base, lpspi_slave_handle_t *handle, status_t status, void *userData)
 

Variables

SPIDriver SPID1
 SPI0 driver identifier.
 
SPIDriver SPID2
 SPI1 driver identifier.
 

Configuration options

typedef void(* spicallback_t) (SPIDriver *spip)
 SPI notification callback type.
 
SPIDriver SPID1
 SPI0 driver identifier.
 
SPIDriver SPID2
 SPI1 driver identifier.
 
void spi_lld_init (void)
 Low level SPI driver initialization.
 
void spi_lld_start (SPIDriver *spip)
 Configures and activates the SPI peripheral.
 
void spi_lld_stop (SPIDriver *spip)
 Deactivates the SPI peripheral.
 
void spi_lld_select (SPIDriver *spip)
 Asserts the slave select signal and prepares for transfers.
 
void spi_lld_unselect (SPIDriver *spip)
 Deasserts the slave select signal.
 
void spi_lld_ignore (SPIDriver *spip, size_t n)
 Ignores data on the SPI bus.
 
void spi_lld_exchange (SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf)
 Exchanges data on the SPI bus.
 
void spi_lld_send (SPIDriver *spip, size_t n, const void *txbuf)
 Sends data over the SPI bus.
 
void spi_lld_receive (SPIDriver *spip, size_t n, void *rxbuf)
 Receives data from the SPI bus.
 
void spi_lld_abort (SPIDriver *spip)
 Aborts the ongoing SPI operation, if any.
 
uint16_t spi_lld_polled_exchange (SPIDriver *spip, uint16_t frame)
 Exchanges one frame using a polled wait.
 

Detailed Description

Typedef Documentation

◆ spicallback_t

typedef void(* spicallback_t) (SPIDriver *spip)

SPI notification callback type.

Parameters
[in]spippointer to the SPIDriver object triggering the callback

Definition at line 123 of file hal_spi_lld.h.

Function Documentation

◆ spi_detectBaudRate()

static int32_t spi_detectBaudRate ( SPIDriver *  spip)
static

Definition at line 90 of file hal_spi_lld.c.

90 {
91 static const int baudRates[] = { 21000000, 10500000, 5250000, 2626000, 1312500, 656250, 328125, 164060 };
92 int flags = 0;
93 if (spip->config->cr1 & SPI_CR1_BR_0)
94 flags |= 1;
95 if (spip->config->cr1 & SPI_CR1_BR_1)
96 flags |= 2;
97 if (spip->config->cr1 & SPI_CR1_BR_2)
98 flags |= 4;
99 int br = baudRates[flags];
100 // SPI1 is faster on STM32 (42 MHz max) so we imitate this behavior
101 if (spip == &SPID1)
102 br *= 2;
103 return br;
104}
static const struct @5 baudRates[]
SPIDriver SPID1
SPI0 driver identifier.
Definition hal_spi_lld.c:42

Referenced by spi_lld_start().

Here is the caller graph for this function:

◆ spi_detectPCS()

static int32_t spi_detectPCS ( bool  isMaster,
ioportid_t  ssport,
uint16_t  sspad,
int *  alt 
)
static

Definition at line 58 of file hal_spi_lld.c.

58 {
59 // todo: check if PCS corresponds to SPI number
60 *alt = 3;
61 if (ssport == GPIOA) {
62 switch (sspad) {
63 case 6:
64 return isMaster ? kLPSPI_MasterPcs1 : kLPSPI_SlavePcs1;
65 case 15:
66 return isMaster ? kLPSPI_MasterPcs3 : kLPSPI_SlavePcs3;
67 case 16:
68 return isMaster ? kLPSPI_MasterPcs2 : kLPSPI_SlavePcs2;
69 }
70 } else if (ssport == GPIOB) {
71 switch (sspad) {
72 case 0:
73 return isMaster ? kLPSPI_MasterPcs0 : kLPSPI_SlavePcs0;
74 case 5:
75 return isMaster ? kLPSPI_MasterPcs1 : kLPSPI_SlavePcs1;
76 case 17:
77 return isMaster ? kLPSPI_MasterPcs3 : kLPSPI_SlavePcs3;
78 }
79 } else if (ssport == GPIOD && sspad == 3) {
80 return isMaster ? kLPSPI_MasterPcs0 : kLPSPI_SlavePcs0;
81 } else if (ssport == GPIOE && sspad == 6) {
82 *alt = 2;
83 return isMaster ? kLPSPI_MasterPcs2 : kLPSPI_SlavePcs2;
84 }
85 // wrong/unrecognized PCS!
86 *alt = 0;
87 return -1;
88}
@ kLPSPI_MasterPcs1
Definition fsl_lpspi.h:199
@ kLPSPI_MasterPcs3
Definition fsl_lpspi.h:201
@ kLPSPI_MasterPcs2
Definition fsl_lpspi.h:200
@ kLPSPI_MasterPcs0
Definition fsl_lpspi.h:198
@ kLPSPI_SlavePcs1
Definition fsl_lpspi.h:227
@ kLPSPI_SlavePcs3
Definition fsl_lpspi.h:229
@ kLPSPI_SlavePcs0
Definition fsl_lpspi.h:226
@ kLPSPI_SlavePcs2
Definition fsl_lpspi.h:228

Referenced by spi_lld_start().

Here is the caller graph for this function:

◆ spi_lld_abort()

void spi_lld_abort ( SPIDriver *  spip)

Aborts the ongoing SPI operation, if any.

Parameters
[in]spippointer to the SPIDriver object

@notapi

Definition at line 390 of file hal_spi_lld.c.

390 {
391#if 0
392 //SPI_DisableDMA(base, kLPSPI_TxDmaEnable | kLPSPI_RxDmaEnable);
393 /* Stopping DMAs.*/
394 dmaStreamDisable(spip->dmatx);
395 dmaStreamDisable(spip->dmarx);
396#endif
397}

◆ spi_lld_exchange()

void spi_lld_exchange ( SPIDriver *  spip,
size_t  n,
const void *  txbuf,
void *  rxbuf 
)

Exchanges data on the SPI bus.

This asynchronous function starts a simultaneous transmit/receive operation.

Postcondition
At the end of the operation the configured callback is invoked.
Note
The buffers are organized as uint8_t arrays for data sizes below or equal to 8 bits else it is organized as uint16_t arrays.
Parameters
[in]spippointer to the SPIDriver object
[in]nnumber of words to be exchanged
[in]txbufthe pointer to the transmit buffer
[out]rxbufthe pointer to the receive buffer

@notapi

Definition at line 314 of file hal_spi_lld.c.

315 {
316 spip->handleXfer.txData = (uint8_t *)txbuf;
317 spip->handleXfer.rxData = rxbuf;
318 spip->handleXfer.dataSize = n;
319 spip->handleXfer.configFlags = spip->flags;
320
321 if (spip->isMaster) {
322 LPSPI_MasterTransferNonBlocking(spip->spi, &spip->masterHandle, &spip->handleXfer);
323 } else {
324 LPSPI_SlaveTransferNonBlocking(spip->spi, &spip->slaveHandle, &spip->handleXfer);
325 }
326}
status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer)
LPSPI slave transfer data using an interrupt method.
Definition fsl_lpspi.c:1403
status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer)
LPSPI master transfer data using an interrupt method.
Definition fsl_lpspi.c:961
Here is the call graph for this function:

◆ spi_lld_ignore()

void spi_lld_ignore ( SPIDriver *  spip,
size_t  n 
)

Ignores data on the SPI bus.

This asynchronous function starts the transmission of a series of idle words on the SPI bus and ignores the received data.

Postcondition
At the end of the operation the configured callback is invoked.
Parameters
[in]spippointer to the SPIDriver object
[in]nnumber of words to be ignored

@notapi

Definition at line 289 of file hal_spi_lld.c.

289 {
290/*
291 spip->count = n;
292 spip->rxbuf = NULL;
293 spip->txbuf = NULL;
294
295 spi_start_xfer(spip, false);
296*/
297}

◆ spi_lld_init()

void spi_lld_init ( void  )

Low level SPI driver initialization.

@notapi

Definition at line 135 of file hal_spi_lld.c.

135 {
136#if KINETIS_SPI_USE_SPI0
137 spiObjectInit(&SPID1);
138#endif
139#if KINETIS_SPI_USE_SPI1
140 spiObjectInit(&SPID2);
141#endif
142}
SPIDriver SPID2
SPI1 driver identifier.
Definition hal_spi_lld.c:47

◆ spi_lld_master_callback()

void spi_lld_master_callback ( LPSPI_Type *  base,
lpspi_master_handle_t handle,
status_t  status,
void *  userData 
)

Definition at line 110 of file hal_spi_lld.c.

111 {
112 SPIDriver *spi = (SPIDriver *)userData;
113
114 // todo: check status?
115 _spi_isr_code(spi);
116}

Referenced by spi_lld_start().

Here is the caller graph for this function:

◆ spi_lld_polled_exchange()

uint16_t spi_lld_polled_exchange ( SPIDriver *  spip,
uint16_t  frame 
)

Exchanges one frame using a polled wait.

This synchronous function exchanges one frame using a polled synchronization method. This function is useful when exchanging small amount of data on high speed channels, usually in this situation is much more efficient just wait for completion using polling than suspending the thread waiting for an interrupt.

Parameters
[in]spippointer to the SPIDriver object
[in]framethe data frame to send over the SPI bus
Returns
The received data frame from the SPI bus.

Definition at line 412 of file hal_spi_lld.c.

412 {
413 // todo: use faster LPSPI_WriteData()
414 uint16_t rxFrame = 0;
415 spip->handleXfer.txData = (uint8_t *)&frame;
416 spip->handleXfer.rxData = (uint8_t *)&rxFrame;
417 spip->handleXfer.dataSize = sizeof(frame);
418 spip->handleXfer.configFlags = spip->flags;
419
420 if (spip->isMaster) {
421 LPSPI_MasterTransferBlocking(spip->spi, &spip->handleXfer);
422 } else {
423 // todo: slave support?
424 }
425 // todo: check status?
426 return rxFrame;
427}
status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer)
LPSPI master transfer data using a polling method.
Definition fsl_lpspi.c:779
Here is the call graph for this function:

◆ spi_lld_receive()

void spi_lld_receive ( SPIDriver *  spip,
size_t  n,
void *  rxbuf 
)

Receives data from the SPI bus.

This asynchronous function starts a receive operation.

Postcondition
At the end of the operation the configured callback is invoked.
Note
The buffers are organized as uint8_t arrays for data sizes below or equal to 8 bits else it is organized as uint16_t arrays.
Parameters
[in]spippointer to the SPIDriver object
[in]nnumber of words to receive
[out]rxbufthe pointer to the receive buffer

@notapi

Definition at line 368 of file hal_spi_lld.c.

368 {
369
370 spip->handleXfer.txData = NULL;
371 spip->handleXfer.rxData = (uint8_t *)rxbuf;
372 spip->handleXfer.dataSize = n;
373 spip->handleXfer.configFlags = spip->flags;
374
375 if (spip->isMaster) {
376 LPSPI_MasterTransferNonBlocking(spip->spi, &spip->masterHandle, &spip->handleXfer);
377 } else {
378 LPSPI_SlaveTransferNonBlocking(spip->spi, &spip->slaveHandle, &spip->handleXfer);
379 }
380}
Here is the call graph for this function:

◆ spi_lld_select()

void spi_lld_select ( SPIDriver *  spip)

Asserts the slave select signal and prepares for transfers.

Parameters
[in]spippointer to the SPIDriver object

@notapi

Definition at line 258 of file hal_spi_lld.c.

258 {
259 // software PCS control for non-standard pins
260 if (!(spip->flags & LPSPI_MASTER_PCS_MASK))
261 palClearPad(spip->config->ssport, spip->config->sspad);
262}

◆ spi_lld_send()

void spi_lld_send ( SPIDriver *  spip,
size_t  n,
const void *  txbuf 
)

Sends data over the SPI bus.

This asynchronous function starts a transmit operation.

Postcondition
At the end of the operation the configured callback is invoked.
Note
The buffers are organized as uint8_t arrays for data sizes below or equal to 8 bits else it is organized as uint16_t arrays.
Parameters
[in]spippointer to the SPIDriver object
[in]nnumber of words to send
[in]txbufthe pointer to the transmit buffer

@notapi

Definition at line 341 of file hal_spi_lld.c.

341 {
342
343 spip->handleXfer.txData = (uint8_t *)txbuf;
344 spip->handleXfer.rxData = NULL;
345 spip->handleXfer.dataSize = n;
346 spip->handleXfer.configFlags = spip->flags;
347
348 if (spip->isMaster) {
349 LPSPI_MasterTransferNonBlocking(spip->spi, &spip->masterHandle, &spip->handleXfer);
350 } else {
351 LPSPI_SlaveTransferNonBlocking(spip->spi, &spip->slaveHandle, &spip->handleXfer);
352 }
353}
Here is the call graph for this function:

◆ spi_lld_slave_callback()

void spi_lld_slave_callback ( LPSPI_Type *  base,
lpspi_slave_handle_t handle,
status_t  status,
void *  userData 
)

Definition at line 118 of file hal_spi_lld.c.

119 {
120 SPIDriver *spi = (SPIDriver *)userData;
121
122 // todo: check status?
123 _spi_isr_code(spi);
124}

Referenced by spi_lld_start().

Here is the caller graph for this function:

◆ spi_lld_start()

void spi_lld_start ( SPIDriver *  spip)

Configures and activates the SPI peripheral.

Parameters
[in]spippointer to the SPIDriver object

@notapi

Definition at line 151 of file hal_spi_lld.c.

151 {
152
153 /* If in stopped state then enables the SPI and DMA clocks.*/
154 if (spip->state == SPI_STOP) {
155 clock_ip_name_t clockName;
156#if KINETIS_SPI_USE_SPI0
157 if (&SPID1 == spip) {
158 spip->spi = LPSPI0;
159 clockName = kCLOCK_Lpspi0;
160 }
161#endif
162
163#if KINETIS_SPI_USE_SPI1
164 if (&SPID2 == spip) {
165 spip->spi = LPSPI1;
166 clockName = kCLOCK_Lpspi1;
167 }
168#endif
169
170 spip->isMaster = (spip->config->cr1 & SPI_CR1_MSTR) != 0;
171 spip->flags = 0; // kLPSPI_MasterByteSwap;
172 int pcsAlt;
173 int pcsIdx = spi_detectPCS(spip->isMaster, spip->config->ssport, spip->config->sspad, &pcsAlt);
174 if (pcsIdx >= 0) {
175 spip->flags |= pcsIdx;
176 // enable corresponding alt.mode for hardware PCS control
177 palSetPadMode(spip->config->ssport, spip->config->sspad, PAL_MODE_ALTERNATE(pcsAlt));
178 } else {
179 // software PCS control for non-standard pins
180 palSetPadMode(spip->config->ssport, spip->config->sspad, PAL_MODE_OUTPUT_OPENDRAIN);
181 }
182
183 //CLOCK_SetIpSrc(clockName, kCLOCK_IpSrcSysPllAsync);
184
185 if (spip->isMaster) {
186 // Master mode
187 lpspi_master_config_t masterConfig;
188 LPSPI_MasterGetDefaultConfig(&masterConfig);
189
190 masterConfig.baudRate = spi_detectBaudRate(spip);
191 masterConfig.bitsPerFrame = (spip->config->cr1 & SPI_CR1_DFF) ? 16 : 8;
192 masterConfig.cpol = (spip->config->cr1 & SPI_CR1_CPOL) ? kLPSPI_ClockPolarityActiveLow : kLPSPI_ClockPolarityActiveHigh;
193 masterConfig.cpha = (spip->config->cr1 & SPI_CR1_CPHA) ? kLPSPI_ClockPhaseSecondEdge : kLPSPI_ClockPhaseFirstEdge;
194 masterConfig.direction = (spip->config->cr1 & SPI_CR1_LSBFIRST) ? kLPSPI_LsbFirst : kLPSPI_MsbFirst;
195
196 masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate * 2;
197 masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate * 2;
198 masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate * 2;
199
200 masterConfig.whichPcs = pcsIdx;
201
202 if (spip->config->circular)
203 spip->flags |= kLPSPI_MasterPcsContinuous;
204
205 uint32_t srcClock_Hz = CLOCK_GetIpFreq(clockName);
206 LPSPI_MasterInit(spip->spi, &masterConfig, srcClock_Hz);
207
208 LPSPI_MasterTransferCreateHandle(spip->spi, &spip->masterHandle, spi_lld_master_callback, spip);
209 } else {
210 // todo: add slave support
211 lpspi_slave_config_t slaveConfig;
212 LPSPI_SlaveGetDefaultConfig(&slaveConfig);
213 LPSPI_SlaveInit(spip->spi, &slaveConfig);
214
215 LPSPI_SlaveTransferCreateHandle(spip->spi, &spip->slaveHandle, spi_lld_slave_callback, spip);
216 }
217
218 // todo: add DMA support?
219 //nvicEnableVector(DMA0_IRQn, KINETIS_SPI0_RX_DMA_IRQ_PRIORITY);
220 }
221}
static int32_t spi_detectBaudRate(SPIDriver *spip)
Definition hal_spi_lld.c:90
void spi_lld_slave_callback(LPSPI_Type *base, lpspi_slave_handle_t *handle, status_t status, void *userData)
void spi_lld_master_callback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData)
static int32_t spi_detectPCS(bool isMaster, ioportid_t ssport, uint16_t sspad, int *alt)
Definition hal_spi_lld.c:58
enum _clock_ip_name clock_ip_name_t
Peripheral clock name difinition used for clock gate, clock source and clock divider setting....
uint32_t CLOCK_GetIpFreq(clock_ip_name_t name)
Gets the clock frequency for a specific IP module.
Definition fsl_clock.c:250
@ kCLOCK_Lpspi1
Definition fsl_clock.h:280
@ kCLOCK_Lpspi0
Definition fsl_clock.h:279
void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
Initializes the LPSPI master.
Definition fsl_lpspi.c:187
void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig)
LPSPI slave configuration.
Definition fsl_lpspi.c:279
void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig)
Sets the lpspi_slave_config_t structure to default values.
Definition fsl_lpspi.c:326
void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_slave_transfer_callback_t callback, void *userData)
Initializes the LPSPI slave handle.
Definition fsl_lpspi.c:1366
void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_master_transfer_callback_t callback, void *userData)
Initializes the LPSPI master handle.
Definition fsl_lpspi.c:686
void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig)
Sets the lpspi_master_config_t structure to default values.
Definition fsl_lpspi.c:249
@ kLPSPI_MasterPcsContinuous
Definition fsl_lpspi.h:203
@ kLPSPI_MsbFirst
Definition fsl_lpspi.h:137
@ kLPSPI_LsbFirst
Definition fsl_lpspi.h:138
@ kLPSPI_ClockPolarityActiveHigh
Definition fsl_lpspi.h:121
@ kLPSPI_ClockPolarityActiveLow
Definition fsl_lpspi.h:122
@ kLPSPI_ClockPhaseFirstEdge
Definition fsl_lpspi.h:128
@ kLPSPI_ClockPhaseSecondEdge
Definition fsl_lpspi.h:130
LPSPI master configuration structure.
Definition fsl_lpspi.h:256
lpspi_shift_direction_t direction
Definition fsl_lpspi.h:261
lpspi_clock_phase_t cpha
Definition fsl_lpspi.h:260
uint32_t betweenTransferDelayInNanoSec
Definition fsl_lpspi.h:268
uint32_t lastSckToPcsDelayInNanoSec
Definition fsl_lpspi.h:265
lpspi_which_pcs_t whichPcs
Definition fsl_lpspi.h:271
uint32_t pcsToSckDelayInNanoSec
Definition fsl_lpspi.h:263
lpspi_clock_polarity_t cpol
Definition fsl_lpspi.h:259
LPSPI slave configuration structure.
Definition fsl_lpspi.h:283
Here is the call graph for this function:

◆ spi_lld_stop()

void spi_lld_stop ( SPIDriver *  spip)

Deactivates the SPI peripheral.

Parameters
[in]spippointer to the SPIDriver object

@notapi

Definition at line 230 of file hal_spi_lld.c.

230 {
231
232 /* If in ready state then disables the SPI clock.*/
233 if (spip->state == SPI_READY) {
234
235 //nvicDisableVector(DMA0_IRQn);
236
237#if KINETIS_SPI_USE_SPI0
238 if (&SPID1 == spip) {
239 LPSPI_Deinit(LPSPI0);
240 }
241#endif
242
243#if KINETIS_SPI_USE_SPI1
244 if (&SPID2 == spip) {
245 LPSPI_Deinit(LPSPI1);
246 }
247#endif
248 }
249}
void LPSPI_Deinit(LPSPI_Type *base)
De-initializes the LPSPI peripheral. Call this API to disable the LPSPI clock.
Definition fsl_lpspi.c:367
Here is the call graph for this function:

◆ spi_lld_unselect()

void spi_lld_unselect ( SPIDriver *  spip)

Deasserts the slave select signal.

The previously selected peripheral is unselected.

Parameters
[in]spippointer to the SPIDriver object

@notapi

Definition at line 272 of file hal_spi_lld.c.

272 {
273 // software PCS control for non-standard pins
274 if (!(spip->flags & LPSPI_MASTER_PCS_MASK))
275 palSetPad(spip->config->ssport, spip->config->sspad);
276}

Variable Documentation

◆ SPID1 [1/2]

SPIDriver SPID1

◆ SPID1 [2/2]

SPIDriver SPID1
extern

◆ SPID2 [1/2]

SPIDriver SPID2

◆ SPID2 [2/2]

SPIDriver SPID2
extern