Skip to content

Commit 3eae29b

Browse files
authored
Merge pull request #15028 from jeromecoutant/PR_SPI_V2
STM32 SPI: Update and improvement
2 parents d1f02f3 + 066c07b commit 3eae29b

File tree

2 files changed

+143
-40
lines changed

2 files changed

+143
-40
lines changed

targets/TARGET_STM/TARGET_STM32H7/spi_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "stm32h7xx_ll_rcc.h"
2020
#include "stm32h7xx_ll_spi.h"
2121

22+
#define SPI_IP_VERSION_V2
23+
2224
// Defines the word legnth capability of the device where Nth bit allows for N window size
2325
#define STM32_SPI_CAPABILITY_WORD_LENGTH (0xFFFFFFF8)
2426

targets/TARGET_STM/stm_spi_api.c

Lines changed: 141 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -197,58 +197,135 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
197197
spiobj->spi = (SPIName)pinmap->peripheral;
198198
MBED_ASSERT(spiobj->spi != (SPIName)NC);
199199

200+
#if defined(SPI_IP_VERSION_V2)
201+
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
202+
#endif /* SPI_IP_VERSION_V2 */
203+
200204
#if defined SPI1_BASE
201205
// Enable SPI clock
202206
if (spiobj->spi == SPI_1) {
207+
#if defined(SPI_IP_VERSION_V2)
208+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
209+
#if defined (RCC_SPI123CLKSOURCE_PLL)
210+
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
211+
#else
212+
PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_SYSCLK;
213+
#endif
214+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
215+
error("HAL_RCCEx_PeriphCLKConfig\n");
216+
}
217+
#endif /* SPI_IP_VERSION_V2 */
218+
219+
__HAL_RCC_SPI1_FORCE_RESET();
220+
__HAL_RCC_SPI1_RELEASE_RESET();
203221
__HAL_RCC_SPI1_CLK_ENABLE();
204222
spiobj->spiIRQ = SPI1_IRQn;
205223
}
206224
#endif
207225

208226
#if defined SPI2_BASE
209227
if (spiobj->spi == SPI_2) {
228+
#if defined(SPI_IP_VERSION_V2)
229+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
230+
#if defined (RCC_SPI123CLKSOURCE_PLL)
231+
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
232+
#else
233+
PeriphClkInit.Spi2ClockSelection = RCC_SPI2CLKSOURCE_SYSCLK;
234+
#endif
235+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
236+
error("HAL_RCCEx_PeriphCLKConfig\n");
237+
}
238+
#endif /* SPI_IP_VERSION_V2 */
239+
240+
__HAL_RCC_SPI2_FORCE_RESET();
241+
__HAL_RCC_SPI2_RELEASE_RESET();
210242
__HAL_RCC_SPI2_CLK_ENABLE();
211243
spiobj->spiIRQ = SPI2_IRQn;
212244
}
213245
#endif
214246

215247
#if defined SPI3_BASE
216248
if (spiobj->spi == SPI_3) {
249+
#if defined(SPI_IP_VERSION_V2)
250+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
251+
#if defined (RCC_SPI123CLKSOURCE_PLL)
252+
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
253+
#else
254+
PeriphClkInit.Spi3ClockSelection = RCC_SPI3CLKSOURCE_SYSCLK;
255+
#endif
256+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
257+
error("HAL_RCCEx_PeriphCLKConfig\n");
258+
}
259+
#endif /* SPI_IP_VERSION_V2 */
260+
261+
__HAL_RCC_SPI3_FORCE_RESET();
262+
__HAL_RCC_SPI3_RELEASE_RESET();
217263
__HAL_RCC_SPI3_CLK_ENABLE();
218264
spiobj->spiIRQ = SPI3_IRQn;
219265
}
220266
#endif
221267

222268
#if defined SPI4_BASE
223269
if (spiobj->spi == SPI_4) {
270+
#if defined(SPI_IP_VERSION_V2)
271+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI4;
272+
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
273+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
274+
error("HAL_RCCEx_PeriphCLKConfig\n");
275+
}
276+
#endif /* SPI_IP_VERSION_V2 */
277+
278+
__HAL_RCC_SPI4_FORCE_RESET();
279+
__HAL_RCC_SPI4_RELEASE_RESET();
224280
__HAL_RCC_SPI4_CLK_ENABLE();
225281
spiobj->spiIRQ = SPI4_IRQn;
226282
}
227283
#endif
228284

229285
#if defined SPI5_BASE
230286
if (spiobj->spi == SPI_5) {
287+
#if defined(SPI_IP_VERSION_V2)
288+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI5;
289+
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
290+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
291+
error("HAL_RCCEx_PeriphCLKConfig\n");
292+
}
293+
#endif /* SPI_IP_VERSION_V2 */
294+
295+
__HAL_RCC_SPI5_FORCE_RESET();
296+
__HAL_RCC_SPI5_RELEASE_RESET();
231297
__HAL_RCC_SPI5_CLK_ENABLE();
232298
spiobj->spiIRQ = SPI5_IRQn;
233299
}
234300
#endif
235301

236302
#if defined SPI6_BASE
237303
if (spiobj->spi == SPI_6) {
304+
#if defined(SPI_IP_VERSION_V2)
305+
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
306+
PeriphClkInit.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PCLK4;
307+
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
308+
error("HAL_RCCEx_PeriphCLKConfig\n");
309+
}
310+
#endif /* SPI_IP_VERSION_V2 */
311+
312+
__HAL_RCC_SPI6_FORCE_RESET();
313+
__HAL_RCC_SPI6_RELEASE_RESET();
238314
__HAL_RCC_SPI6_CLK_ENABLE();
239315
spiobj->spiIRQ = SPI6_IRQn;
240316
}
241317
#endif
242318

243319
// Configure the SPI pins
244320
pin_function(pinmap->mosi_pin, pinmap->mosi_function);
245-
pin_mode(pinmap->mosi_pin, PullNone);
321+
pin_mode(pinmap->mosi_pin, PullDown); // Pull Down is set for output line
246322

247323
pin_function(pinmap->miso_pin, pinmap->miso_function);
248324
pin_mode(pinmap->miso_pin, PullNone);
249325

250326
pin_function(pinmap->sclk_pin, pinmap->sclk_function);
251327
pin_mode(pinmap->sclk_pin, PullNone);
328+
252329
spiobj->pin_miso = pinmap->miso_pin;
253330
spiobj->pin_mosi = pinmap->mosi_pin;
254331
spiobj->pin_sclk = pinmap->sclk_pin;
@@ -289,10 +366,21 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
289366
handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
290367
handle->Init.TIMode = SPI_TIMODE_DISABLE;
291368

292-
#if TARGET_STM32H7
369+
#if defined (SPI_IP_VERSION_V2)
370+
handle->Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
293371
handle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
294372
handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
295-
#endif
373+
handle->Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
374+
handle->Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
375+
handle->Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
376+
handle->Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
377+
handle->Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
378+
handle->Init.IOSwap = SPI_IO_SWAP_DISABLE;
379+
#if defined(SPI_RDY_MASTER_MANAGEMENT_INTERNALLY)
380+
handle->Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
381+
handle->Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
382+
#endif
383+
#endif /* SPI_IP_VERSION_V2 */
296384

297385
/*
298386
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
@@ -580,16 +668,21 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
580668
handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
581669
}
582670

583-
handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
671+
if (slave) {
672+
handle->Init.Mode = SPI_MODE_SLAVE;
584673

585-
if (slave && (handle->Init.Direction == SPI_DIRECTION_1LINE)) {
586-
/* SPI slave implemtation in MBED does not support the 3 wires SPI.
587-
* (e.g. when MISO is not connected). So we're forcing slave in
588-
* 2LINES mode. As MISO is not connected, slave will only read
589-
* from master, and cannot write to it. Inform user.
590-
*/
591-
debug("3 wires SPI slave not supported - slave will only read\r\n");
592-
handle->Init.Direction = SPI_DIRECTION_2LINES;
674+
if (handle->Init.Direction == SPI_DIRECTION_1LINE) {
675+
/* SPI slave implemtation in MBED does not support the 3 wires SPI.
676+
* (e.g. when MISO is not connected). So we're forcing slave in
677+
* 2LINES mode. As MISO is not connected, slave will only read
678+
* from master, and cannot write to it. Inform user.
679+
*/
680+
debug("3 wires SPI slave not supported - slave will only read\r\n");
681+
handle->Init.Direction = SPI_DIRECTION_2LINES;
682+
}
683+
684+
pin_mode(spiobj->pin_mosi, PullNone);
685+
pin_mode(spiobj->pin_miso, PullDown); // Pull Down is set for output line
593686
}
594687

595688
/*
@@ -699,7 +792,11 @@ static inline int ssp_readable(spi_t *obj)
699792
SPI_HandleTypeDef *handle = &(spiobj->handle);
700793

701794
// Check if data is received
795+
#if defined(SPI_IP_VERSION_V2)
796+
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXP) != RESET) ? 1 : 0);
797+
#else /* SPI_IP_VERSION_V2 */
702798
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
799+
#endif /* SPI_IP_VERSION_V2 */
703800
return status;
704801
}
705802

@@ -710,7 +807,12 @@ static inline int ssp_writeable(spi_t *obj)
710807
SPI_HandleTypeDef *handle = &(spiobj->handle);
711808

712809
// Check if data is transmitted
810+
#if defined(SPI_IP_VERSION_V2)
811+
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXP) != RESET) ? 1 : 0);
812+
#else /* SPI_IP_VERSION_V2 */
713813
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0);
814+
#endif /* SPI_IP_VERSION_V2 */
815+
714816
return status;
715817
}
716818

@@ -719,11 +821,11 @@ static inline int ssp_busy(spi_t *obj)
719821
int status;
720822
struct spi_s *spiobj = SPI_S(obj);
721823
SPI_HandleTypeDef *handle = &(spiobj->handle);
722-
#if TARGET_STM32H7
824+
#if defined(SPI_IP_VERSION_V2)
723825
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXWNE) != RESET) ? 1 : 0);
724-
#else /* TARGET_STM32H7 */
826+
#else /* SPI_IP_VERSION_V2 */
725827
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0);
726-
#endif /* TARGET_STM32H7 */
828+
#endif /* SPI_IP_VERSION_V2 */
727829
return status;
728830
}
729831

@@ -845,11 +947,11 @@ static inline int datasize_to_transfer_bitshift(uint32_t DataSize)
845947
*/
846948
static inline int msp_writable(spi_t *obj)
847949
{
848-
#if TARGET_STM32H7
950+
#if defined(SPI_IP_VERSION_V2)
849951
return (int)LL_SPI_IsActiveFlag_TXP(SPI_INST(obj));
850-
#else /* TARGET_STM32H7 */
952+
#else /* SPI_IP_VERSION_V2 */
851953
return (int)LL_SPI_IsActiveFlag_TXE(SPI_INST(obj));
852-
#endif /* TARGET_STM32H7 */
954+
#endif /* SPI_IP_VERSION_V2 */
853955
}
854956

855957
/**
@@ -860,11 +962,11 @@ static inline int msp_writable(spi_t *obj)
860962
*/
861963
static inline int msp_readable(spi_t *obj)
862964
{
863-
#if TARGET_STM32H7
965+
#if defined(SPI_IP_VERSION_V2)
864966
return (int)LL_SPI_IsActiveFlag_RXP(SPI_INST(obj));
865-
#else /* TARGET_STM32H7 */
967+
#else /* SPI_IP_VERSION_V2 */
866968
return (int)LL_SPI_IsActiveFlag_RXNE(SPI_INST(obj));
867-
#endif /* TARGET_STM32H7 */
969+
#endif /* SPI_IP_VERSION_V2 */
868970
}
869971

870972
/**
@@ -891,11 +993,11 @@ static inline void msp_wait_readable(spi_t *obj)
891993
*/
892994
static inline int msp_busy(spi_t *obj)
893995
{
894-
#if TARGET_STM32H7
996+
#if defined(SPI_IP_VERSION_V2)
895997
return !(int)LL_SPI_IsActiveFlag_TXC(SPI_INST(obj));
896-
#else /* TARGET_STM32H7 */
998+
#else /* SPI_IP_VERSION_V2 */
897999
return (int)LL_SPI_IsActiveFlag_BSY(SPI_INST(obj));
898-
#endif /* TARGET_STM32H7 */
1000+
#endif /* SPI_IP_VERSION_V2 */
8991001
}
9001002

9011003
/**
@@ -962,15 +1064,15 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
9621064
/* Transmit data */
9631065
if (tx_length) {
9641066
LL_SPI_SetTransferDirection(SPI_INST(obj), LL_SPI_HALF_DUPLEX_TX);
965-
#if TARGET_STM32H7
1067+
#if defined(SPI_IP_VERSION_V2)
9661068
/* Set transaction size */
9671069
LL_SPI_SetTransferSize(SPI_INST(obj), tx_length);
968-
#endif /* TARGET_STM32H7 */
1070+
#endif /* SPI_IP_VERSION_V2 */
9691071
LL_SPI_Enable(SPI_INST(obj));
970-
#if TARGET_STM32H7
1072+
#if defined(SPI_IP_VERSION_V2)
9711073
/* Master transfer start */
9721074
LL_SPI_StartMasterTransfer(SPI_INST(obj));
973-
#endif /* TARGET_STM32H7 */
1075+
#endif /* SPI_IP_VERSION_V2 */
9741076

9751077
for (int i = 0; i < tx_length; i++) {
9761078
msp_wait_writable(obj);
@@ -982,19 +1084,19 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
9821084

9831085
LL_SPI_Disable(SPI_INST(obj));
9841086

985-
#if TARGET_STM32H7
1087+
#if defined(SPI_IP_VERSION_V2)
9861088
/* Clear transaction flags */
9871089
LL_SPI_ClearFlag_EOT(SPI_INST(obj));
9881090
LL_SPI_ClearFlag_TXTF(SPI_INST(obj));
9891091
/* Reset transaction size */
9901092
LL_SPI_SetTransferSize(SPI_INST(obj), 0);
991-
#endif /* TARGET_STM32H7 */
1093+
#endif /* SPI_IP_VERSION_V2 */
9921094
}
9931095

9941096
/* Receive data */
9951097
if (rx_length) {
9961098
LL_SPI_SetTransferDirection(SPI_INST(obj), LL_SPI_HALF_DUPLEX_RX);
997-
#if TARGET_STM32H7
1099+
#if defined(SPI_IP_VERSION_V2)
9981100
/* Set transaction size and run SPI */
9991101
LL_SPI_SetTransferSize(SPI_INST(obj), rx_length);
10001102
LL_SPI_Enable(SPI_INST(obj));
@@ -1014,7 +1116,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10141116
/* Reset transaction size */
10151117
LL_SPI_SetTransferSize(SPI_INST(obj), 0);
10161118

1017-
#else /* TARGET_STM32H7 */
1119+
#else /* SPI_IP_VERSION_V2 */
10181120
/* Unlike STM32H7 other STM32 families generates SPI Clock signal continuously in half-duplex receive mode
10191121
* till SPI is enabled. To stop clock generation a SPI should be disabled during last frame receiving,
10201122
* after generation at least one SPI clock cycle. It causes necessity of critical section usage.
@@ -1044,7 +1146,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10441146
rx_buffer[i] = msp_read_data(obj, bitshift);
10451147
}
10461148

1047-
#endif /* TARGET_STM32H7 */
1149+
#endif /* SPI_IP_VERSION_V2 */
10481150
}
10491151

10501152
return rx_length + tx_length;
@@ -1077,10 +1179,10 @@ int spi_master_write(spi_t *obj, int value)
10771179
* but this will increase performances significantly
10781180
*/
10791181

1080-
#if TARGET_STM32H7
1182+
#if defined(SPI_IP_VERSION_V2)
10811183
/* Master transfer start */
10821184
LL_SPI_StartMasterTransfer(SPI_INST(obj));
1083-
#endif
1185+
#endif /* SPI_IP_VERSION_V2 */
10841186

10851187
/* Transmit data */
10861188
msp_wait_writable(obj);
@@ -1241,7 +1343,7 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer
12411343
NVIC_EnableIRQ(irq_n);
12421344

12431345
// flush FIFO
1244-
#if defined(SPI_FLAG_FRLVL) // STM32F0 STM32F3 STM32F7 STM32L4
1346+
#if defined(SPI_FLAG_FRLVL)
12451347
HAL_SPIEx_FlushRxFifo(handle);
12461348
#endif
12471349

@@ -1306,11 +1408,10 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,
13061408

13071409
obj->spi.event = event;
13081410

1309-
DEBUG_PRINTF("SPI: Transfer: %u, %u\n", tx_length, rx_length);
1310-
13111411
// register the thunking handler
13121412
IRQn_Type irq_n = spiobj->spiIRQ;
13131413
NVIC_SetVector(irq_n, (uint32_t)handler);
1414+
DEBUG_PRINTF("SPI: Transfer: tx %u (%u), rx %u (%u), IRQ %u\n", use_tx, tx_length, use_rx, rx_length, irq_n);
13141415

13151416
// enable the right hal transfer
13161417
if (use_tx && use_rx) {
@@ -1355,7 +1456,7 @@ inline uint32_t spi_irq_handler_asynch(spi_t *obj)
13551456
// disable the interrupt
13561457
NVIC_DisableIRQ(obj->spi.spiIRQ);
13571458
NVIC_ClearPendingIRQ(obj->spi.spiIRQ);
1358-
#ifndef TARGET_STM32H7
1459+
#if !defined(SPI_IP_VERSION_V2)
13591460
if (handle->Init.Direction == SPI_DIRECTION_1LINE && obj->rx_buff.buffer != NULL) {
13601461
/**
13611462
* In case of 3-wire SPI data receiving we usually get dummy reads.
@@ -1365,7 +1466,7 @@ inline uint32_t spi_irq_handler_asynch(spi_t *obj)
13651466
*/
13661467
spi_flush_rx(obj);
13671468
}
1368-
#endif
1469+
#endif /* SPI_IP_VERSION_V2 */
13691470
}
13701471

13711472
return (event & (obj->spi.event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE));

0 commit comments

Comments
 (0)