From 5fdce5fbf7ecea263be90b18bcce4418ff8cf2ce Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Wed, 24 Aug 2016 14:52:45 +0200 Subject: [PATCH 1/8] [STM32F4] move spi_s to common file --- .../TARGET_STM32F4/TARGET_ARCH_MAX/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_B96B_F446VE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_DISCO_F401VC/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_DISCO_F407VG/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_DISCO_F429ZI/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_DISCO_F469NI/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_ELMO_F411RE/objects.h | 14 -------------- .../TARGET_MTS_DRAGONFLY_F411RE/objects.h | 14 -------------- .../TARGET_MTS_MDOT_F405RG/objects.h | 14 -------------- .../TARGET_MTS_MDOT_F411RE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F401RE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F410RB/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F411RE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F429ZI/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F446RE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_NUCLEO_F446ZE/objects.h | 14 -------------- .../TARGET_STM32F4/TARGET_UBLOX_C029/objects.h | 14 -------------- .../hal/TARGET_STM/TARGET_STM32F4/common_objects.h | 14 ++++++++++++++ 18 files changed, 14 insertions(+), 238 deletions(-) diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/objects.h index af634eaaa22..c02fc3174f1 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_B96B_F446VE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_B96B_F446VE/objects.h index 93063f6f6f8..4480dedf259 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_B96B_F446VE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_B96B_F446VE/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F401VC/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F401VC/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F401VC/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F401VC/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F407VG/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F407VG/objects.h index af634eaaa22..c02fc3174f1 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F407VG/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F407VG/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F429ZI/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F429ZI/objects.h index 373fc34516c..a6770342160 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F429ZI/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F429ZI/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F469NI/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F469NI/objects.h index 0d002e0104c..3b0932fb179 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F469NI/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_DISCO_F469NI/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ELMO_F411RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ELMO_F411RE/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ELMO_F411RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_ELMO_F411RE/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_DRAGONFLY_F411RE/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F405RG/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F405RG/objects.h index 36967625791..da53d4c55d9 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F405RG/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F405RG/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_MTS_MDOT_F411RE/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F401RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F401RE/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F401RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F401RE/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F410RB/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F410RB/objects.h index 36967625791..da53d4c55d9 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F410RB/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F410RB/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F411RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F411RE/objects.h index c252efd1d37..7500a61db5d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F411RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F411RE/objects.h @@ -60,20 +60,6 @@ struct analogin_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/objects.h index ecd684f90f2..a45edbcc1aa 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/objects.h index 0d002e0104c..3b0932fb179 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446ZE/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446ZE/objects.h index 0d002e0104c..3b0932fb179 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446ZE/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446ZE/objects.h @@ -65,20 +65,6 @@ struct dac_s { uint8_t channel; }; -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_C029/objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_C029/objects.h index 081916e91a1..1e054c9ff52 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_C029/objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_C029/objects.h @@ -62,20 +62,6 @@ struct analogin_s { -struct spi_s { - SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; - PinName pin_miso; - PinName pin_mosi; - PinName pin_sclk; - PinName pin_ssel; -}; - struct i2c_s { I2CName i2c; uint32_t slave; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h index 204dc13e587..68cdb7ce89b 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h @@ -68,6 +68,20 @@ struct serial_s { #endif }; +struct spi_s { + SPIName spi; + uint32_t bits; + uint32_t cpol; + uint32_t cpha; + uint32_t mode; + uint32_t nss; + uint32_t br_presc; + PinName pin_miso; + PinName pin_mosi; + PinName pin_sclk; + PinName pin_ssel; +}; + #include "gpio_object.h" #ifdef __cplusplus From 478168c71205862452ea410e88a902958b52baeb Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Wed, 24 Aug 2016 15:34:01 +0200 Subject: [PATCH 2/8] [STM32F4] SPI ASYNCH support This commit is highly derived from an existing work from salkinium. It adds SPI ASYNC support to STM32 F4 devices. This required a small rework of the structure to have SYNCH and ASYNCH co-exist. --- .../TARGET_STM32F4/common_objects.h | 7 + .../hal/TARGET_STM/TARGET_STM32F4/spi_api.c | 425 ++++++++++++++---- 2 files changed, 355 insertions(+), 77 deletions(-) diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h index 68cdb7ce89b..2c31a3f197f 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h @@ -69,6 +69,8 @@ struct serial_s { }; struct spi_s { + SPI_HandleTypeDef handle; + IRQn_Type spiIRQ; SPIName spi; uint32_t bits; uint32_t cpol; @@ -80,6 +82,11 @@ struct spi_s { PinName pin_mosi; PinName pin_sclk; PinName pin_ssel; +#ifdef DEVICE_SPI_ASYNCH + uint32_t event; + uint8_t module; + uint8_t transfer_type; +#endif }; #include "gpio_object.h" diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c index f2fae81534f..7500b50276d 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c @@ -32,42 +32,69 @@ #include "spi_api.h" #if DEVICE_SPI - +#include #include +#include #include "cmsis.h" #include "pinmap.h" #include "PeripheralPins.h" -#include "mbed_error.h" -static SPI_HandleTypeDef SpiHandle; +#if DEVICE_SPI_ASYNCH + #define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi.spi)) +#else + #define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi)) +#endif + +#if DEVICE_SPI_ASYNCH + #define SPI_S(obj) (( struct spi_s *)(&(obj->spi))) +#else + #define SPI_S(obj) (( struct spi_s *)(obj)) +#endif + +#ifndef DEBUG_STDIO +# define DEBUG_STDIO 0 +#endif + +#if DEBUG_STDIO +# include +# define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0) +#else +# define DEBUG_PRINTF(...) {} +#endif static void init_spi(spi_t *obj) { - SpiHandle.Instance = (SPI_TypeDef *)(obj->spi); - - __HAL_SPI_DISABLE(&SpiHandle); - - SpiHandle.Init.Mode = obj->mode; - SpiHandle.Init.BaudRatePrescaler = obj->br_presc; - SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; - SpiHandle.Init.CLKPhase = obj->cpha; - SpiHandle.Init.CLKPolarity = obj->cpol; - SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; - SpiHandle.Init.CRCPolynomial = 7; - SpiHandle.Init.DataSize = obj->bits; - SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; - SpiHandle.Init.NSS = obj->nss; - SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; - - if (HAL_SPI_Init(&SpiHandle) != HAL_OK) { + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + + handle->Instance = SPI_INST(obj); + __HAL_SPI_DISABLE(handle); + + DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance); + + handle->Init.Mode = spiobj->mode; + handle->Init.BaudRatePrescaler = spiobj->br_presc; + handle->Init.Direction = SPI_DIRECTION_2LINES; + handle->Init.CLKPhase = spiobj->cpha; + handle->Init.CLKPolarity = spiobj->cpol; + handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; + handle->Init.CRCPolynomial = 7; + handle->Init.DataSize = (spiobj->bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; + handle->Init.FirstBit = SPI_FIRSTBIT_MSB; + handle->Init.NSS = spiobj->nss; + handle->Init.TIMode = SPI_TIMODE_DISABLED; + + if (HAL_SPI_Init(handle) != HAL_OK) { error("Cannot initialize SPI"); } - __HAL_SPI_ENABLE(&SpiHandle); + __HAL_SPI_ENABLE(handle); } void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { + struct spi_s *spiobj = SPI_S(obj); + // Determine the SPI to use SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); @@ -77,39 +104,45 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - obj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl); - MBED_ASSERT(obj->spi != (SPIName)NC); + spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl); + MBED_ASSERT(spiobj->spi != (SPIName)NC); // Enable SPI clock - if (obj->spi == SPI_1) { + if (spiobj->spi == SPI_1) { __HAL_RCC_SPI1_CLK_ENABLE(); + spiobj->spiIRQ = SPI1_IRQn; } - if (obj->spi == SPI_2) { + if (spiobj->spi == SPI_2) { __HAL_RCC_SPI2_CLK_ENABLE(); + spiobj->spiIRQ = SPI2_IRQn; } #if defined SPI3_BASE - if (obj->spi == SPI_3) { + if (spiobj->spi == SPI_3) { __HAL_RCC_SPI3_CLK_ENABLE(); + spiobj->spiIRQ = SPI3_IRQn; } #endif #if defined SPI4_BASE - if (obj->spi == SPI_4) { + if (spiobj->spi == SPI_4) { __HAL_RCC_SPI4_CLK_ENABLE(); + spiobj->spiIRQ = SPI4_IRQn; } #endif #if defined SPI5_BASE - if (obj->spi == SPI_5) { + if (spiobj->spi == SPI_5) { __HAL_RCC_SPI5_CLK_ENABLE(); + spiobj->spiIRQ = SPI5_IRQn; } #endif #if defined SPI6_BASE - if (obj->spi == SPI_6) { + if (spiobj->spi == SPI_6) { __HAL_RCC_SPI6_CLK_ENABLE(); + spiobj->spiIRQ = SPI6_IRQn; } #endif @@ -118,21 +151,23 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); - // Save new values - obj->bits = SPI_DATASIZE_8BIT; - obj->cpol = SPI_POLARITY_LOW; - obj->cpha = SPI_PHASE_1EDGE; - obj->br_presc = SPI_BAUDRATEPRESCALER_256; + // Save default values + spiobj->bits = 8; + spiobj->mode = SPI_MODE_MASTER; - obj->pin_miso = miso; - obj->pin_mosi = mosi; - obj->pin_sclk = sclk; - obj->pin_ssel = ssel; + spiobj->cpol = SPI_POLARITY_LOW; + spiobj->cpha = SPI_PHASE_1EDGE; + spiobj->br_presc = SPI_BAUDRATEPRESCALER_256; + + spiobj->pin_miso = miso; + spiobj->pin_mosi = mosi; + spiobj->pin_sclk = sclk; + spiobj->pin_ssel = ssel; if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); } else { - obj->nss = SPI_NSS_SOFT; + spiobj->nss = SPI_NSS_SOFT; } init_spi(obj); @@ -140,20 +175,28 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel void spi_free(spi_t *obj) { + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + + DEBUG_PRINTF("spi_free\r\n"); + + __HAL_SPI_DISABLE(handle); + HAL_SPI_DeInit(handle); + // Reset SPI and disable clock - if (obj->spi == SPI_1) { + if (spiobj->spi == SPI_1) { __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); __HAL_RCC_SPI1_CLK_DISABLE(); } - if (obj->spi == SPI_2) { + if (spiobj->spi == SPI_2) { __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); } #if defined SPI3_BASE - if (obj->spi == SPI_3) { + if (spiobj->spi == SPI_3) { __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); @@ -161,7 +204,7 @@ void spi_free(spi_t *obj) #endif #if defined SPI4_BASE - if (obj->spi == SPI_4) { + if (spiobj->spi == SPI_4) { __HAL_RCC_SPI4_FORCE_RESET(); __HAL_RCC_SPI4_RELEASE_RESET(); __HAL_RCC_SPI4_CLK_DISABLE(); @@ -169,7 +212,7 @@ void spi_free(spi_t *obj) #endif #if defined SPI5_BASE - if (obj->spi == SPI_5) { + if (spiobj->spi == SPI_5) { __HAL_RCC_SPI5_FORCE_RESET(); __HAL_RCC_SPI5_RELEASE_RESET(); __HAL_RCC_SPI5_CLK_DISABLE(); @@ -177,7 +220,7 @@ void spi_free(spi_t *obj) #endif #if defined SPI6_BASE - if (obj->spi == SPI_6) { + if (spiobj->spi == SPI_6) { __HAL_RCC_SPI6_FORCE_RESET(); __HAL_RCC_SPI6_RELEASE_RESET(); __HAL_RCC_SPI6_CLK_DISABLE(); @@ -185,45 +228,47 @@ void spi_free(spi_t *obj) #endif // Configure GPIOs - pin_function(obj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - pin_function(obj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - pin_function(obj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - pin_function(obj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + pin_function(spiobj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + if (spiobj->nss != SPI_NSS_SOFT) { + pin_function(spiobj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + } } void spi_format(spi_t *obj, int bits, int mode, int slave) { + struct spi_s *spiobj = SPI_S(obj); + + DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave); + // Save new values - if (bits == 16) { - obj->bits = SPI_DATASIZE_16BIT; - } else { - obj->bits = SPI_DATASIZE_8BIT; - } + spiobj->bits = bits; switch (mode) { case 0: - obj->cpol = SPI_POLARITY_LOW; - obj->cpha = SPI_PHASE_1EDGE; + spiobj->cpol = SPI_POLARITY_LOW; + spiobj->cpha = SPI_PHASE_1EDGE; break; case 1: - obj->cpol = SPI_POLARITY_LOW; - obj->cpha = SPI_PHASE_2EDGE; + spiobj->cpol = SPI_POLARITY_LOW; + spiobj->cpha = SPI_PHASE_2EDGE; break; case 2: - obj->cpol = SPI_POLARITY_HIGH; - obj->cpha = SPI_PHASE_1EDGE; + spiobj->cpol = SPI_POLARITY_HIGH; + spiobj->cpha = SPI_PHASE_1EDGE; break; default: - obj->cpol = SPI_POLARITY_HIGH; - obj->cpha = SPI_PHASE_2EDGE; + spiobj->cpol = SPI_POLARITY_HIGH; + spiobj->cpha = SPI_PHASE_2EDGE; break; } - if (obj->nss != SPI_NSS_SOFT) { - obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; + if (spiobj->nss != SPI_NSS_SOFT) { + spiobj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; } - obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; + spiobj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; init_spi(obj); } @@ -239,11 +284,14 @@ static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2, void spi_frequency(spi_t *obj, int hz) { + struct spi_s *spiobj = SPI_S(obj); int spi_hz = 0; uint8_t prescaler_rank = 0; + DEBUG_PRINTF("spi_frequency:%d\r\n", hz); + /* Get source clock depending on SPI instance */ - switch ((int)obj->spi) { + switch ((int)spiobj->spi) { case SPI_1: #if defined SPI4_BASE case SPI_4: @@ -275,7 +323,7 @@ void spi_frequency(spi_t *obj, int hz) } if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) { - obj->br_presc = baudrate_prescaler_table[prescaler_rank-1]; + spiobj->br_presc = baudrate_prescaler_table[prescaler_rank-1]; } else { error("Couldn't setup requested SPI frequency"); } @@ -286,31 +334,35 @@ void spi_frequency(spi_t *obj, int hz) static inline int ssp_readable(spi_t *obj) { int status; - SpiHandle.Instance = (SPI_TypeDef *)(obj->spi); + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + // Check if data is received - status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0); + status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0); return status; } static inline int ssp_writeable(spi_t *obj) { int status; - SpiHandle.Instance = (SPI_TypeDef *)(obj->spi); + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + // Check if data is transmitted - status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_TXE) != RESET) ? 1 : 0); + status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0); return status; } static inline void ssp_write(spi_t *obj, int value) { - SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi); + SPI_TypeDef *spi = SPI_INST(obj); while (!ssp_writeable(obj)); spi->DR = (uint16_t)value; } static inline int ssp_read(spi_t *obj) { - SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi); + SPI_TypeDef *spi = SPI_INST(obj); while (!ssp_readable(obj)); return (int)spi->DR; } @@ -318,8 +370,10 @@ static inline int ssp_read(spi_t *obj) static inline int ssp_busy(spi_t *obj) { int status; - SpiHandle.Instance = (SPI_TypeDef *)(obj->spi); - status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_BSY) != RESET) ? 1 : 0); + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + + status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0); return status; } @@ -336,14 +390,14 @@ int spi_slave_receive(spi_t *obj) int spi_slave_read(spi_t *obj) { - SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi); + SPI_TypeDef *spi = SPI_INST(obj); while (!ssp_readable(obj)); return (int)spi->DR; } void spi_slave_write(spi_t *obj, int value) { - SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi); + SPI_TypeDef *spi = SPI_INST(obj); while (!ssp_writeable(obj)); spi->DR = (uint16_t)value; } @@ -353,4 +407,221 @@ int spi_busy(spi_t *obj) return ssp_busy(obj); } +#ifdef DEVICE_SPI_ASYNCH +typedef enum { + SPI_TRANSFER_TYPE_NONE = 0, + SPI_TRANSFER_TYPE_TX = 1, + SPI_TRANSFER_TYPE_RX = 2, + SPI_TRANSFER_TYPE_TXRX = 3, +} transfer_type_t; + + +/// @returns the number of bytes transferred, or `0` if nothing transferred +static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length) +{ + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); + // the HAL expects number of transfers instead of number of bytes + // so for 16 bit transfer width the count needs to be halved + size_t words; + + DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\r\n", (int)handle->Instance, transfer_type, length); + + obj->spi.transfer_type = transfer_type; + + if (is16bit) words = length / 2; + else words = length; + + // enable the interrupt + IRQn_Type irq_n = spiobj->spiIRQ; + NVIC_ClearPendingIRQ(irq_n); + NVIC_DisableIRQ(irq_n); + NVIC_SetPriority(irq_n, 1); + NVIC_EnableIRQ(irq_n); + + // enable the right hal transfer + static uint16_t sink; + int rc = 0; + switch(transfer_type) { + case SPI_TRANSFER_TYPE_TXRX: + rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)rx, words); + break; + case SPI_TRANSFER_TYPE_TX: + // TODO: we do not use `HAL_SPI_Transmit_IT`, since it has some unknown bug + // and makes the HAL keep some state and then that fails successive transfers + // rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words); + rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)&sink, 1); + length = is16bit ? 2 : 1; + break; + case SPI_TRANSFER_TYPE_RX: + // the receive function also "transmits" the receive buffer so in order + // to guarantee that 0xff is on the line, we explicitly memset it here + memset(rx, SPI_FILL_WORD, length); + rc = HAL_SPI_Receive_IT(handle, (uint8_t*)rx, words); + break; + default: + length = 0; + } + + if (rc) { + DEBUG_PRINTF("SPI: RC=%u\n", rc); + length = 0; + } + + return length; +} + +// asynchronous API +void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) +{ + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + + // TODO: DMA usage is currently ignored + (void) hint; + + // check which use-case we have + bool use_tx = (tx != NULL && tx_length > 0); + bool use_rx = (rx != NULL && rx_length > 0); + bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); + + // don't do anything, if the buffers aren't valid + if (!use_tx && !use_rx) + return; + + // copy the buffers to the SPI object + obj->tx_buff.buffer = (void *) tx; + obj->tx_buff.length = tx_length; + obj->tx_buff.pos = 0; + obj->tx_buff.width = is16bit ? 16 : 8; + + obj->rx_buff.buffer = rx; + obj->rx_buff.length = rx_length; + obj->rx_buff.pos = 0; + obj->rx_buff.width = obj->tx_buff.width; + + 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); + + // enable the right hal transfer + if (use_tx && use_rx) { + // transfer with the min(tx, rx), then later either transmit _or_ receive the remainder + size_t size = (tx_length < rx_length)? tx_length : rx_length; + spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size); + } else if (use_tx) { + spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length); + } else if (use_rx) { + spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_length); + } +} + +uint32_t spi_irq_handler_asynch(spi_t *obj) +{ + // use the right instance + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &spiobj->handle; + int event = 0; + + // call the CubeF4 handler, this will update the handle + HAL_SPI_IRQHandler(handle); + + if (HAL_SPI_GetState(handle) == HAL_SPI_STATE_READY) { + // adjust buffer positions + size_t tx_size = (handle->TxXferSize - handle->TxXferCount); + size_t rx_size = (handle->RxXferSize - handle->RxXferCount); + // 16 bit transfers need to be doubled to get bytes + if (handle->Init.DataSize == SPI_DATASIZE_16BIT) { + tx_size *= 2; + rx_size *= 2; + } + // adjust buffer positions + if (obj->spi.transfer_type != SPI_TRANSFER_TYPE_RX) { + obj->tx_buff.pos += tx_size; + } + if (obj->spi.transfer_type != SPI_TRANSFER_TYPE_TX) { + obj->rx_buff.pos += rx_size; + } + + if (handle->TxXferCount > 0) {DEBUG_PRINTF("SPI: TxXferCount: %u\n", handle->TxXferCount);} + if (handle->RxXferCount > 0) {DEBUG_PRINTF("SPI: RxXferCount: %u\n", handle->RxXferCount);} + + int error = HAL_SPI_GetError(handle); + if(error != HAL_SPI_ERROR_NONE) { + // something went wrong and the transfer has definitely completed + event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + + if (error & HAL_SPI_ERROR_OVR) { + // buffer overrun + event |= SPI_EVENT_RX_OVERFLOW; + } + } else { + // figure out if we need to transfer more data: + if (obj->tx_buff.pos < obj->tx_buff.length) { + //DEBUG_PRINTF("t%u ", obj->tx_buff.pos); + // we need to transfer more data + spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, + obj->tx_buff.buffer + obj->tx_buff.pos, // offset the initial buffer by the position + NULL, // there is no receive buffer + obj->tx_buff.length - obj->tx_buff.pos); // transfer the remaining bytes only + } else if (obj->rx_buff.pos < obj->rx_buff.length) { + //DEBUG_PRINTF("r%u ", obj->rx_buff.pos); + // we need to receive more data + spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, + NULL, // there is no transmit buffer + obj->rx_buff.buffer + obj->rx_buff.pos, // offset the initial buffer by the position + obj->rx_buff.length - obj->rx_buff.pos); // transfer one byte at a time, until we received everything + } else { + // everything is ok, nothing else needs to be transferred + event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + DEBUG_PRINTF("SPI: Done: %u, %u\n", obj->tx_buff.pos, obj->rx_buff.pos); + } + } + } + + if (event) DEBUG_PRINTF("SPI: Event: 0x%x\n", event); + + return (event & (obj->spi.event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)); +} + +uint8_t spi_active(spi_t *obj) +{ + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + HAL_SPI_StateTypeDef state = HAL_SPI_GetState(handle); + + switch(state) { + case HAL_SPI_STATE_RESET: + case HAL_SPI_STATE_READY: + case HAL_SPI_STATE_ERROR: + return 0; + default: + return 1; + } +} + +void spi_abort_asynch(spi_t *obj) +{ + struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); + + // disable interrupt + IRQn_Type irq_n = spiobj->spiIRQ; + NVIC_ClearPendingIRQ(irq_n); + NVIC_DisableIRQ(irq_n); + + // clean-up + __HAL_SPI_DISABLE(handle); + HAL_SPI_DeInit(handle); + HAL_SPI_Init(handle); + __HAL_SPI_ENABLE(handle); +} + +#endif //DEVICE_SPI_ASYNCH + #endif From c5323c13a81279690e065c8b3aef952b08222728 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Tue, 16 Aug 2016 16:39:27 +0200 Subject: [PATCH 3/8] [STM32F4] SPI: avoid duplicate information accross layers Same information was stored in spi_api.c and STM32 HAL layers. Modify code to avoid this duplicate information. --- .../TARGET_STM32F4/common_objects.h | 6 -- .../hal/TARGET_STM/TARGET_STM32F4/spi_api.c | 70 ++++++++----------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h index 2c31a3f197f..2f0df22f398 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/common_objects.h @@ -72,12 +72,6 @@ struct spi_s { SPI_HandleTypeDef handle; IRQn_Type spiIRQ; SPIName spi; - uint32_t bits; - uint32_t cpol; - uint32_t cpha; - uint32_t mode; - uint32_t nss; - uint32_t br_presc; PinName pin_miso; PinName pin_mosi; PinName pin_sclk; diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c index 7500b50276d..267bac40b74 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c @@ -67,23 +67,9 @@ static void init_spi(spi_t *obj) struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); - handle->Instance = SPI_INST(obj); __HAL_SPI_DISABLE(handle); DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance); - - handle->Init.Mode = spiobj->mode; - handle->Init.BaudRatePrescaler = spiobj->br_presc; - handle->Init.Direction = SPI_DIRECTION_2LINES; - handle->Init.CLKPhase = spiobj->cpha; - handle->Init.CLKPolarity = spiobj->cpol; - handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; - handle->Init.CRCPolynomial = 7; - handle->Init.DataSize = (spiobj->bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; - handle->Init.FirstBit = SPI_FIRSTBIT_MSB; - handle->Init.NSS = spiobj->nss; - handle->Init.TIMode = SPI_TIMODE_DISABLED; - if (HAL_SPI_Init(handle) != HAL_OK) { error("Cannot initialize SPI"); } @@ -94,6 +80,7 @@ static void init_spi(spi_t *obj) void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); // Determine the SPI to use SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); @@ -150,26 +137,29 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); - - // Save default values - spiobj->bits = 8; - spiobj->mode = SPI_MODE_MASTER; - - spiobj->cpol = SPI_POLARITY_LOW; - spiobj->cpha = SPI_PHASE_1EDGE; - spiobj->br_presc = SPI_BAUDRATEPRESCALER_256; - spiobj->pin_miso = miso; spiobj->pin_mosi = mosi; spiobj->pin_sclk = sclk; spiobj->pin_ssel = ssel; - if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); } else { - spiobj->nss = SPI_NSS_SOFT; + handle->Init.NSS = SPI_NSS_SOFT; } + /* Fill default value */ + handle->Instance = SPI_INST(obj); + handle->Init.Mode = SPI_MODE_MASTER; + handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; + handle->Init.Direction = SPI_DIRECTION_2LINES; + handle->Init.CLKPhase = SPI_PHASE_1EDGE; + handle->Init.CLKPolarity = SPI_POLARITY_LOW; + handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; + handle->Init.CRCPolynomial = 7; + handle->Init.DataSize = SPI_DATASIZE_8BIT; + handle->Init.FirstBit = SPI_FIRSTBIT_MSB; + handle->Init.TIMode = SPI_TIMODE_DISABLED; + init_spi(obj); } @@ -231,7 +221,7 @@ void spi_free(spi_t *obj) pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(spiobj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - if (spiobj->nss != SPI_NSS_SOFT) { + if (handle->Init.NSS != SPI_NSS_SOFT) { pin_function(spiobj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); } } @@ -239,36 +229,37 @@ void spi_free(spi_t *obj) void spi_format(spi_t *obj, int bits, int mode, int slave) { struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave); // Save new values - spiobj->bits = bits; + handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; switch (mode) { case 0: - spiobj->cpol = SPI_POLARITY_LOW; - spiobj->cpha = SPI_PHASE_1EDGE; + handle->Init.CLKPolarity = SPI_POLARITY_LOW; + handle->Init.CLKPhase = SPI_PHASE_1EDGE; break; case 1: - spiobj->cpol = SPI_POLARITY_LOW; - spiobj->cpha = SPI_PHASE_2EDGE; + handle->Init.CLKPolarity = SPI_POLARITY_LOW; + handle->Init.CLKPhase = SPI_PHASE_2EDGE; break; case 2: - spiobj->cpol = SPI_POLARITY_HIGH; - spiobj->cpha = SPI_PHASE_1EDGE; + handle->Init.CLKPolarity = SPI_POLARITY_HIGH; + handle->Init.CLKPhase = SPI_PHASE_1EDGE; break; default: - spiobj->cpol = SPI_POLARITY_HIGH; - spiobj->cpha = SPI_PHASE_2EDGE; + handle->Init.CLKPolarity = SPI_POLARITY_HIGH; + handle->Init.CLKPhase = SPI_PHASE_2EDGE; break; } - if (spiobj->nss != SPI_NSS_SOFT) { - spiobj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; + if (handle->Init.NSS != SPI_NSS_SOFT) { + handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; } - spiobj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; + handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; init_spi(obj); } @@ -285,6 +276,7 @@ static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2, void spi_frequency(spi_t *obj, int hz) { struct spi_s *spiobj = SPI_S(obj); + SPI_HandleTypeDef *handle = &(spiobj->handle); int spi_hz = 0; uint8_t prescaler_rank = 0; @@ -323,7 +315,7 @@ void spi_frequency(spi_t *obj, int hz) } if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) { - spiobj->br_presc = baudrate_prescaler_table[prescaler_rank-1]; + handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank-1]; } else { error("Couldn't setup requested SPI frequency"); } From 3140b4bb2918d76480140fd28e0eba6cdcb1c842 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Wed, 24 Aug 2016 15:57:59 +0200 Subject: [PATCH 4/8] UTEST Spi Asynch Update test to be able to test on NUCLEO boards using generic default pins definitions --- .../utest/spi_asynch/spi_master_asynch.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp b/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp index 03e3db92393..a7247e903b1 100644 --- a/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp +++ b/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp @@ -64,6 +64,18 @@ #define TEST_SCLK_PIN P10_12 #define TEST_CS_PIN P10_13 +#elif defined(TARGET_FF_ARDUINO) +#define TEST_MOSI_PIN D11 +#define TEST_MISO_PIN D12 +#define TEST_SCLK_PIN D13 +#define TEST_CS_PIN D10 + +#elif defined(TARGET_DISCO_F429ZI) +#define TEST_MOSI_PIN PC_12 +#define TEST_MISO_PIN PC_11 +#define TEST_SCLK_PIN PC_10 +#define TEST_CS_PIN PA_15 + #else #error Target not supported #endif @@ -152,7 +164,7 @@ TEST(SPI_Master_Asynchronous, short_tx_0_rx) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer( tx_buf,SHORT_XFR,NULL,0, callback, -1); + rc = obj->transfer( (const uint8_t *) tx_buf, SHORT_XFR, (uint8_t *) NULL, 0, callback, 255); CHECK_EQUAL(0, rc); while (!complete); @@ -171,7 +183,7 @@ TEST(SPI_Master_Asynchronous, short_tx_0_rx_nn) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer( tx_buf,SHORT_XFR,rx_buf,0,callback, -1); + rc = obj->transfer( (const uint8_t *)tx_buf,SHORT_XFR,(uint8_t *) rx_buf, 0,callback, -1); CHECK_EQUAL(0, rc); while (!complete); @@ -189,7 +201,7 @@ TEST(SPI_Master_Asynchronous, 0_tx_short_rx) { int rc; // Read a buffer of Short Transfer length. - rc = obj->transfer( NULL,0,rx_buf,SHORT_XFR,callback, -1); + rc = obj->transfer( (const uint8_t *)NULL,0,(uint8_t *) rx_buf,SHORT_XFR,callback, -1); CHECK_EQUAL(0, rc); while (!complete); From e68b550c2a3671f82d2a8e7a0b3d24df8e48c275 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Wed, 24 Aug 2016 16:47:13 +0200 Subject: [PATCH 5/8] [STM32F4] enable SPI ASYNCH --- hal/targets.json | 53 +++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/hal/targets.json b/hal/targets.json index b948d3de9df..83cfe637e87 100644 --- a/hal/targets.json +++ b/hal/targets.json @@ -782,7 +782,8 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f401re"}, "detect_code": ["0720"], - "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "NUCLEO_F410RB": { @@ -793,9 +794,9 @@ "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "inherits": ["Target"], "progen": {"target": "nucleo-f410rb"}, - "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT"], + "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT", "TRANSACTION_QUEUE_SIZE_SPI=2"], "detect_code": ["0740"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "NUCLEO_F411RE": { @@ -807,7 +808,8 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f411re"}, "detect_code": ["0740"], - "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "ELMO_F411RE": { @@ -818,7 +820,8 @@ "supported_toolchains": ["ARM", "uARM", "GCC_ARM"], "inherits": ["Target"], "detect_code": ["----"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "default_lib": "small", "release_versions": ["2"] }, @@ -830,8 +833,8 @@ "extra_labels": ["STM", "STM32F4", "STM32F429", "STM32F429ZI", "STM32F429xx"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "progen": {"target": "nucleo-f429zi"}, - "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "RTC_LSI", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT", "DEVICE_RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "detect_code": ["0796"], "features": ["IPV4"], "release_versions": ["2", "5"] @@ -845,7 +848,8 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f446re"}, "detect_code": ["0777"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "NUCLEO_F446ZE": { @@ -857,8 +861,8 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f446ze"}, "detect_code": ["0778"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], - "release_versions": ["2", "5"] + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"] }, "B96B_F446VE": { @@ -869,7 +873,8 @@ "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "inherits": ["Target"], "detect_code": ["0840"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "NUCLEO_F746ZG": { @@ -1061,17 +1066,18 @@ "progen": {"target": "disco-f407vg"}, "extra_labels": ["STM", "STM32F4", "STM32F407", "STM32F407VG"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"] + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"] }, "DISCO_F429ZI": { "inherits": ["Target"], "core": "Cortex-M4F", "default_toolchain": "ARM", "extra_labels": ["STM", "STM32F4", "STM32F429", "STM32F429ZI", "STM32F429xx"], - "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT", "DEVICE_RTC_LSI=1"], + "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT","DEVICE_RTC_LSI=1","TRANSACTION_QUEUE_SIZE_SPI=2"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "progen": {"target": "disco-f429zi"}, - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "DISCO_F469NI": { @@ -1081,10 +1087,10 @@ "extra_labels": ["STM", "STM32F4", "STM32F469", "STM32F469NI", "STM32F469xx"], "supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"], "inherits": ["Target"], - "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT"], + "macros": ["MBEDTLS_ENTROPY_HARDWARE_ALT","TRANSACTION_QUEUE_SIZE_SPI=2"], "progen": {"target": "disco-f469ni"}, "detect_code": ["0788"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "DISCO_L053C8": { @@ -1140,9 +1146,9 @@ "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "extra_labels": ["STM", "STM32F4", "STM32F405RG"], "is_disk_virtual": true, - "macros": ["HSE_VALUE=26000000", "OS_CLOCK=48000000"], + "macros": ["HSE_VALUE=26000000", "OS_CLOCK=48000000", "TRANSACTION_QUEUE_SIZE_SPI=2"], "progen": {"target": "mts-mdot-f405rg"}, - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2"] }, "MTS_MDOT_F411RE": { @@ -1150,13 +1156,13 @@ "core": "Cortex-M4F", "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "extra_labels": ["STM", "STM32F4", "STM32F411RE"], - "macros": ["HSE_VALUE=26000000", "OS_CLOCK=96000000", "USE_PLL_HSE_EXTC=0", "VECT_TAB_OFFSET=0x00010000"], + "macros": ["HSE_VALUE=26000000", "OS_CLOCK=96000000", "USE_PLL_HSE_EXTC=0", "VECT_TAB_OFFSET=0x00010000","TRANSACTION_QUEUE_SIZE_SPI=2"], "post_binary_hook": { "function": "MTSCode.combine_bins_mts_dot", "toolchains": ["GCC_ARM", "ARM_STD", "ARM_MICRO"] }, "progen": {"target": "mts-mdot-f411re"}, - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "MTS_DRAGONFLY_F411RE": { @@ -1164,13 +1170,13 @@ "core": "Cortex-M4F", "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "extra_labels": ["STM", "STM32F4", "STM32F411RE"], - "macros": ["HSE_VALUE=26000000", "VECT_TAB_OFFSET=0x08010000"], + "macros": ["HSE_VALUE=26000000", "VECT_TAB_OFFSET=0x08010000","TRANSACTION_QUEUE_SIZE_SPI=2"], "post_binary_hook": { "function": "MTSCode.combine_bins_mts_dragonfly", "toolchains": ["GCC_ARM", "ARM_STD", "ARM_MICRO"] }, "progen": {"target": "mts-dragonfly-f411re"}, - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "MOTE_L152RC": { @@ -1192,7 +1198,8 @@ "default_toolchain": "GCC_ARM", "extra_labels": ["STM", "STM32F4", "STM32F401", "STM32F401VC"], "supported_toolchains": ["GCC_ARM"], - "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"] + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"] }, "UBLOX_C029": { "supported_form_factors": ["ARDUINO"], From 00086a6f4439bb4f15c06b0bba75b8e41ec0bc7f Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Tue, 13 Sep 2016 17:01:23 +0200 Subject: [PATCH 6/8] [STM32F4] Simplify spi Asynch transfer implementation Following discussion on: it seems now clear that the transfer API is meant to be used either with only Rx, or only Tx or Rx and Tx with the same lenth. Therefore we're removing support of transfers of Rx and Tx with different lenghts - this makes porting to HAL more direct and simpler. --- .../hal/TARGET_STM/TARGET_STM32F4/spi_api.c | 59 +++++-------------- 1 file changed, 14 insertions(+), 45 deletions(-) diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c index 267bac40b74..aa1a8b7b4ec 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F4/spi_api.c @@ -433,7 +433,7 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer NVIC_EnableIRQ(irq_n); // enable the right hal transfer - static uint16_t sink; + //static uint16_t sink; int rc = 0; switch(transfer_type) { case SPI_TRANSFER_TYPE_TXRX: @@ -442,9 +442,9 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer case SPI_TRANSFER_TYPE_TX: // TODO: we do not use `HAL_SPI_Transmit_IT`, since it has some unknown bug // and makes the HAL keep some state and then that fails successive transfers - // rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words); - rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)&sink, 1); - length = is16bit ? 2 : 1; + rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words); + //rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)&sink, 1); + //length = is16bit ? 2 : 1; break; case SPI_TRANSFER_TYPE_RX: // the receive function also "transmits" the receive buffer so in order @@ -503,8 +503,13 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, // enable the right hal transfer if (use_tx && use_rx) { - // transfer with the min(tx, rx), then later either transmit _or_ receive the remainder + // we cannot manage different rx / tx sizes, let's use smaller one size_t size = (tx_length < rx_length)? tx_length : rx_length; + if(tx_length != rx_length) { + DEBUG_PRINTF("SPI: Full duplex transfer only 1 size: %d\n", size); + obj->tx_buff.length = size; + obj->rx_buff.length = size; + } spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size); } else if (use_tx) { spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length); @@ -524,25 +529,7 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) HAL_SPI_IRQHandler(handle); if (HAL_SPI_GetState(handle) == HAL_SPI_STATE_READY) { - // adjust buffer positions - size_t tx_size = (handle->TxXferSize - handle->TxXferCount); - size_t rx_size = (handle->RxXferSize - handle->RxXferCount); - // 16 bit transfers need to be doubled to get bytes - if (handle->Init.DataSize == SPI_DATASIZE_16BIT) { - tx_size *= 2; - rx_size *= 2; - } - // adjust buffer positions - if (obj->spi.transfer_type != SPI_TRANSFER_TYPE_RX) { - obj->tx_buff.pos += tx_size; - } - if (obj->spi.transfer_type != SPI_TRANSFER_TYPE_TX) { - obj->rx_buff.pos += rx_size; - } - - if (handle->TxXferCount > 0) {DEBUG_PRINTF("SPI: TxXferCount: %u\n", handle->TxXferCount);} - if (handle->RxXferCount > 0) {DEBUG_PRINTF("SPI: RxXferCount: %u\n", handle->RxXferCount);} - + // When HAL SPI is back to READY state, check if there was an error int error = HAL_SPI_GetError(handle); if(error != HAL_SPI_ERROR_NONE) { // something went wrong and the transfer has definitely completed @@ -553,27 +540,9 @@ uint32_t spi_irq_handler_asynch(spi_t *obj) event |= SPI_EVENT_RX_OVERFLOW; } } else { - // figure out if we need to transfer more data: - if (obj->tx_buff.pos < obj->tx_buff.length) { - //DEBUG_PRINTF("t%u ", obj->tx_buff.pos); - // we need to transfer more data - spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, - obj->tx_buff.buffer + obj->tx_buff.pos, // offset the initial buffer by the position - NULL, // there is no receive buffer - obj->tx_buff.length - obj->tx_buff.pos); // transfer the remaining bytes only - } else if (obj->rx_buff.pos < obj->rx_buff.length) { - //DEBUG_PRINTF("r%u ", obj->rx_buff.pos); - // we need to receive more data - spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, - NULL, // there is no transmit buffer - obj->rx_buff.buffer + obj->rx_buff.pos, // offset the initial buffer by the position - obj->rx_buff.length - obj->rx_buff.pos); // transfer one byte at a time, until we received everything - } else { - // everything is ok, nothing else needs to be transferred - event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; - DEBUG_PRINTF("SPI: Done: %u, %u\n", obj->tx_buff.pos, obj->rx_buff.pos); - } - } + // else we're done + event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + } } if (event) DEBUG_PRINTF("SPI: Event: 0x%x\n", event); From 04fe4d258870b33992c814ba9b4ce3be9d85118c Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Tue, 13 Sep 2016 17:02:30 +0200 Subject: [PATCH 7/8] [STM32F4 HAL] Avoid SPI spurious interrupt If SPI TXE is not disabled at the end of transfer, MBED application callback that is registered for transfer completion might be called twice --- hal/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hal/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_spi.c b/hal/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_spi.c index ba900173a7d..8b9d2043811 100644 --- a/hal/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_spi.c +++ b/hal/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_spi.c @@ -2450,6 +2450,7 @@ static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi) SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); } #endif /* USE_SPI_CRC */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE)); SPI_CloseTx_ISR(hspi); } } @@ -2476,6 +2477,7 @@ static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi) SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); } #endif /* USE_SPI_CRC */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE)); SPI_CloseTx_ISR(hspi); } } From b7a39d04d473d4c754f6c50f571256ef8bf4366b Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Wed, 21 Sep 2016 12:38:47 +0200 Subject: [PATCH 8/8] fixup! UTEST Spi Asynch --- .../utest/spi_asynch/spi_master_asynch.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp b/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp index a7247e903b1..07fcc5c467d 100644 --- a/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp +++ b/libraries/tests/utest/spi_asynch/spi_master_asynch.cpp @@ -164,7 +164,7 @@ TEST(SPI_Master_Asynchronous, short_tx_0_rx) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer( (const uint8_t *) tx_buf, SHORT_XFR, (uint8_t *) NULL, 0, callback, 255); + rc = obj->transfer( (const uint8_t *) tx_buf, SHORT_XFR, (uint8_t *) NULL, 0, callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -183,7 +183,7 @@ TEST(SPI_Master_Asynchronous, short_tx_0_rx_nn) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer( (const uint8_t *)tx_buf,SHORT_XFR,(uint8_t *) rx_buf, 0,callback, -1); + rc = obj->transfer( (const uint8_t *)tx_buf,SHORT_XFR,(uint8_t *) rx_buf, 0,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -201,7 +201,7 @@ TEST(SPI_Master_Asynchronous, 0_tx_short_rx) { int rc; // Read a buffer of Short Transfer length. - rc = obj->transfer( (const uint8_t *)NULL,0,(uint8_t *) rx_buf,SHORT_XFR,callback, -1); + rc = obj->transfer( (const uint8_t *)NULL,0,(uint8_t *) rx_buf,SHORT_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -222,7 +222,7 @@ TEST(SPI_Master_Asynchronous, 0_tx_nn_short_rx) { int rc; // Read a buffer of Short Transfer length. - rc = obj->transfer(tx_buf,0,rx_buf,SHORT_XFR,callback, -1); + rc = obj->transfer(tx_buf,0,rx_buf,SHORT_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -242,7 +242,7 @@ TEST(SPI_Master_Asynchronous, short_tx_short_rx) { int rc; // Write/Read a buffer of Long Transfer length. - rc = obj->transfer( tx_buf,SHORT_XFR,rx_buf,SHORT_XFR,callback, -1); + rc = obj->transfer( tx_buf,SHORT_XFR,rx_buf,SHORT_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -261,7 +261,7 @@ TEST(SPI_Master_Asynchronous, long_tx_long_rx) { int rc; // Write/Read a buffer of Long Transfer length. - rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,LONG_XFR,callback, -1); + rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,LONG_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -282,7 +282,7 @@ TEST(SPI_Master_Asynchronous, long_tx_short_rx) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,SHORT_XFR,callback, -1); + rc = obj->transfer(tx_buf,LONG_XFR,rx_buf,SHORT_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -302,7 +302,7 @@ TEST(SPI_Master_Asynchronous, short_tx_long_rx) { int rc; // Write a buffer of Short Transfer length. - rc = obj->transfer(tx_buf,SHORT_XFR,rx_buf,LONG_XFR,callback, -1); + rc = obj->transfer(tx_buf,SHORT_XFR,rx_buf,LONG_XFR,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete); @@ -327,7 +327,7 @@ TEST(SPI_Master_Asynchronous, queue_test) CHECK_EQUAL(0, rc); rc = obj->transfer( &tx_buf[4],4, &rx_buf[4],4,callback, 0); CHECK_EQUAL(0, rc); - rc = obj->transfer( &tx_buf[8],4, &rx_buf[8],4,callback, -1); + rc = obj->transfer( &tx_buf[8],4, &rx_buf[8],4,callback, SPI_EVENT_ALL); CHECK_EQUAL(0, rc); while (!complete);