Skip to content

Commit

Permalink
STM32 SPI: Update and improvment
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromecoutant committed Aug 27, 2021
1 parent d2a88f4 commit df41a15
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 23 deletions.
2 changes: 2 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H7/spi_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "stm32h7xx_ll_rcc.h"
#include "stm32h7xx_ll_spi.h"

#define SPI_IP_VERSION_V2

// Defines the word legnth capability of the device where Nth bit allows for N window size
#define STM32_SPI_CAPABILITY_WORD_LENGTH (0xFFFFFFF8)

Expand Down
148 changes: 125 additions & 23 deletions targets/TARGET_STM/stm_spi_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,58 +181,135 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
spiobj->spi = (SPIName)pinmap->peripheral;
MBED_ASSERT(spiobj->spi != (SPIName)NC);

#if defined(SPI_IP_VERSION_V2)
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
#endif

#if defined SPI1_BASE
// Enable SPI clock
if (spiobj->spi == SPI_1) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#else
PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_SYSCLK;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
__HAL_RCC_SPI1_CLK_ENABLE();
spiobj->spiIRQ = SPI1_IRQn;
}
#endif

#if defined SPI2_BASE
if (spiobj->spi == SPI_2) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#else
PeriphClkInit.Spi2ClockSelection = RCC_SPI2CLKSOURCE_SYSCLK;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI2_FORCE_RESET();
__HAL_RCC_SPI2_RELEASE_RESET();
__HAL_RCC_SPI2_CLK_ENABLE();
spiobj->spiIRQ = SPI2_IRQn;
}
#endif

#if defined SPI3_BASE
if (spiobj->spi == SPI_3) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#else
PeriphClkInit.Spi3ClockSelection = RCC_SPI3CLKSOURCE_SYSCLK;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI3_FORCE_RESET();
__HAL_RCC_SPI3_RELEASE_RESET();
__HAL_RCC_SPI3_CLK_ENABLE();
spiobj->spiIRQ = SPI3_IRQn;
}
#endif

#if defined SPI4_BASE
if (spiobj->spi == SPI_4) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI4;
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI4_FORCE_RESET();
__HAL_RCC_SPI4_RELEASE_RESET();
__HAL_RCC_SPI4_CLK_ENABLE();
spiobj->spiIRQ = SPI4_IRQn;
}
#endif

#if defined SPI5_BASE
if (spiobj->spi == SPI_5) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI5;
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI5_FORCE_RESET();
__HAL_RCC_SPI5_RELEASE_RESET();
__HAL_RCC_SPI5_CLK_ENABLE();
spiobj->spiIRQ = SPI5_IRQn;
}
#endif

#if defined SPI6_BASE
if (spiobj->spi == SPI_6) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
PeriphClkInit.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PCLK4;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
#endif

__HAL_RCC_SPI6_FORCE_RESET();
__HAL_RCC_SPI6_RELEASE_RESET();
__HAL_RCC_SPI6_CLK_ENABLE();
spiobj->spiIRQ = SPI6_IRQn;
}
#endif

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

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

pin_function(pinmap->sclk_pin, pinmap->sclk_function);
pin_mode(pinmap->sclk_pin, PullNone);

spiobj->pin_miso = pinmap->miso_pin;
spiobj->pin_mosi = pinmap->mosi_pin;
spiobj->pin_sclk = pinmap->sclk_pin;
Expand Down Expand Up @@ -273,9 +350,21 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
handle->Init.TIMode = SPI_TIMODE_DISABLE;

#if TARGET_STM32H7
handle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
#if defined (SPI_IP_VERSION_V2)
handle->Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
handle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
handle->Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
handle->Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
handle->Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
handle->Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
handle->Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
handle->Init.IOSwap = SPI_IO_SWAP_DISABLE;
#endif

#if defined(SPI_RDY_MASTER_MANAGEMENT_INTERNALLY)
handle->Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
handle->Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
#endif

/*
Expand Down Expand Up @@ -564,16 +653,21 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
}

handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
if (slave) {
handle->Init.Mode = SPI_MODE_SLAVE;

if (handle->Init.Direction == SPI_DIRECTION_1LINE) {
/* SPI slave implemtation in MBED does not support the 3 wires SPI.
* (e.g. when MISO is not connected). So we're forcing slave in
* 2LINES mode. As MISO is not connected, slave will only read
* from master, and cannot write to it. Inform user.
*/
debug("3 wires SPI slave not supported - slave will only read\r\n");
handle->Init.Direction = SPI_DIRECTION_2LINES;
}

if (slave && (handle->Init.Direction == SPI_DIRECTION_1LINE)) {
/* SPI slave implemtation in MBED does not support the 3 wires SPI.
* (e.g. when MISO is not connected). So we're forcing slave in
* 2LINES mode. As MISO is not connected, slave will only read
* from master, and cannot write to it. Inform user.
*/
debug("3 wires SPI slave not supported - slave will only read\r\n");
handle->Init.Direction = SPI_DIRECTION_2LINES;
pin_mode(pinmap->mosi_pin, PullNone);
pin_mode(pinmap->miso_pin, PullDown); // Pull Down is set for output line
}

/*
Expand Down Expand Up @@ -639,7 +733,11 @@ static inline int ssp_readable(spi_t *obj)
SPI_HandleTypeDef *handle = &(spiobj->handle);

// Check if data is received
#if defined(SPI_IP_VERSION_V2)
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXP) != RESET) ? 1 : 0);
#else
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
#endif
return status;
}

Expand All @@ -650,7 +748,12 @@ static inline int ssp_writeable(spi_t *obj)
SPI_HandleTypeDef *handle = &(spiobj->handle);

// Check if data is transmitted
#if defined(SPI_IP_VERSION_V2)
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXP) != RESET) ? 1 : 0);
#else
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0);
#endif

return status;
}

Expand All @@ -659,11 +762,11 @@ static inline int ssp_busy(spi_t *obj)
int status;
struct spi_s *spiobj = SPI_S(obj);
SPI_HandleTypeDef *handle = &(spiobj->handle);
#if TARGET_STM32H7
#if defined(SPI_IP_VERSION_V2)
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXWNE) != RESET) ? 1 : 0);
#else /* TARGET_STM32H7 */
#else
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0);
#endif /* TARGET_STM32H7 */
#endif
return status;
}

Expand Down Expand Up @@ -803,7 +906,7 @@ int spi_master_write(spi_t *obj, int value)
* but this will increase performances significantly
*/

#if TARGET_STM32H7
#if defined(SPI_IP_VERSION_V2)
/* Master transfer start */
LL_SPI_StartMasterTransfer(SPI_INST(obj));

Expand All @@ -813,7 +916,7 @@ int spi_master_write(spi_t *obj, int value)
/* Wait TXE flag to transmit data */
while (!LL_SPI_IsActiveFlag_TXE(SPI_INST(obj)));

#endif /* TARGET_STM32H7 */
#endif

/* Transmit data */
if (bitshift == 1) {
Expand All @@ -826,13 +929,13 @@ int spi_master_write(spi_t *obj, int value)
LL_SPI_TransmitData8(SPI_INST(obj), (uint8_t)value);
}

#if TARGET_STM32H7
#if defined(SPI_IP_VERSION_V2)
/* Wait for RXP or end of Transfer */
while (!LL_SPI_IsActiveFlag_RXP(SPI_INST(obj)));
#else /* TARGET_STM32H7 */
#else
/* Wait for RXNE flag before reading */
while (!LL_SPI_IsActiveFlag_RXNE(SPI_INST(obj)));
#endif /* TARGET_STM32H7 */
#endif

/* Read received data */
if (bitshift == 1) {
Expand Down Expand Up @@ -1003,7 +1106,7 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer
NVIC_EnableIRQ(irq_n);

// flush FIFO
#if defined(SPI_FLAG_FRLVL) // STM32F0 STM32F3 STM32F7 STM32L4
#if defined(SPI_FLAG_FRLVL)
HAL_SPIEx_FlushRxFifo(handle);
#endif

Expand Down Expand Up @@ -1068,11 +1171,10 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx,

obj->spi.event = event;

DEBUG_PRINTF("SPI: Transfer: %u, %u\n", tx_length, rx_length);

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

// enable the right hal transfer
if (use_tx && use_rx) {
Expand Down

0 comments on commit df41a15

Please sign in to comment.