mirror of https://github.com/ARMmbed/mbed-os.git
commit
81beeb175b
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,6 +49,21 @@ struct pwmout_s {
|
||||||
uint8_t inverted;
|
uint8_t inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
PinName pin_mosi;
|
||||||
|
PinName pin_sclk;
|
||||||
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
UARTName uart;
|
UARTName uart;
|
||||||
int index; // Used by irq
|
int index; // Used by irq
|
||||||
|
|
|
@ -32,260 +32,23 @@
|
||||||
#include "spi_api.h"
|
#include "spi_api.h"
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
static void init_spi(spi_t *obj) {
|
#else
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
|
|
||||||
__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;
|
|
||||||
|
|
||||||
HAL_SPI_Init(&SpiHandle);
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Configure the SPI pins
|
/*
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
* Only the frequency is managed in the family specific part
|
||||||
pinmap_pinout(miso, PinMap_SPI_MISO);
|
* the rest of SPI management is common to all STM32 families
|
||||||
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
*/
|
||||||
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
// Save new values
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
obj->br_presc = SPI_BAUDRATEPRESCALER_256;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj) {
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_FORCE_RESET();
|
|
||||||
__SPI1_RELEASE_RESET();
|
|
||||||
__SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_FORCE_RESET();
|
|
||||||
__SPI2_RELEASE_RESET();
|
|
||||||
__SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave) {
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz) {
|
|
||||||
int spi_hz = 0;
|
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* SPI_1, SPI_2. Source CLK is PCKL1 */
|
/* SPI_1, SPI_2. Source CLK is PCKL1 */
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
return HAL_RCC_GetPCLK1Freq();
|
||||||
|
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj) {
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj) {
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj) {
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value) {
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj) {
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj) {
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value) {
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj) {
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint8_t channel;
|
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint8_t channel;
|
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint8_t channel;
|
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -68,6 +68,21 @@ struct serial_s {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
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"
|
#include "gpio_object.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -32,159 +32,26 @@
|
||||||
#include "spi_api.h"
|
#include "spi_api.h"
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
|
#else
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
|
#endif
|
||||||
|
|
||||||
static void init_spi(spi_t *obj)
|
/*
|
||||||
{
|
* Only the frequency is managed in the family specific part
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
* the rest of SPI management is common to all STM32 families
|
||||||
|
*/
|
||||||
__HAL_SPI_DISABLE(&SpiHandle);
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
SpiHandle.Init.Mode = obj->mode;
|
int spi_hz = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
HAL_SPI_Init(&SpiHandle);
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_FORCE_RESET();
|
|
||||||
__SPI1_RELEASE_RESET();
|
|
||||||
__SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_FORCE_RESET();
|
|
||||||
__SPI2_RELEASE_RESET();
|
|
||||||
__SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
/* SPI_1. Source CLK is PCKL2 */
|
/* SPI_1. Source CLK is PCKL2 */
|
||||||
spi_hz = HAL_RCC_GetPCLK2Freq();
|
spi_hz = HAL_RCC_GetPCLK2Freq();
|
||||||
|
@ -194,120 +61,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -85,17 +85,18 @@ struct serial_s {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spi_s {
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
SPIName spi;
|
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_miso;
|
||||||
PinName pin_mosi;
|
PinName pin_mosi;
|
||||||
PinName pin_sclk;
|
PinName pin_sclk;
|
||||||
PinName pin_ssel;
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct i2c_s {
|
struct i2c_s {
|
||||||
|
|
|
@ -33,217 +33,27 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
static void init_spi(spi_t *obj)
|
#else
|
||||||
{
|
#define SPI_S(obj) (( struct spi_s *)(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) {
|
|
||||||
error("Cannot initialize SPI");
|
|
||||||
}
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined SPI3_BASE
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined SPI4_BASE
|
/*
|
||||||
if (obj->spi == SPI_4) {
|
* Only the frequency is managed in the family specific part
|
||||||
__HAL_RCC_SPI4_CLK_ENABLE();
|
* the rest of SPI management is common to all STM32 families
|
||||||
}
|
*/
|
||||||
#endif
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
#if defined SPI5_BASE
|
|
||||||
if (obj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI6_BASE
|
|
||||||
if (obj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI1_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->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) {
|
|
||||||
__HAL_RCC_SPI3_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI3_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI3_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI4_BASE
|
|
||||||
if (obj->spi == SPI_4) {
|
|
||||||
__HAL_RCC_SPI4_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI4_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI4_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI5_BASE
|
|
||||||
if (obj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI5_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI5_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI6_BASE
|
|
||||||
if (obj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI6_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI6_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
#if defined SPI4_BASE
|
#if defined SPI4_BASE
|
||||||
case SPI_4:
|
case SPI_4:
|
||||||
|
@ -266,91 +76,9 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
// The 'features' section in 'target.json' is now used to create the device's hardware preprocessor switches.
|
|
||||||
// Check the 'features' section of the target description in 'targets.json' for more details.
|
|
||||||
/* mbed Microcontroller Library
|
|
||||||
*******************************************************************************
|
|
||||||
* Copyright (c) 2015, STMicroelectronics
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*******************************************************************************
|
|
||||||
*/
|
|
||||||
#ifndef MBED_DEVICE_H
|
|
||||||
#define MBED_DEVICE_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=======================================
|
|
||||||
|
|
||||||
#define DEVICE_ID_LENGTH 24
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "objects.h"
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -66,51 +66,17 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_t channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct serial_s {
|
|
||||||
UARTName uart;
|
|
||||||
int index; // Used by irq
|
|
||||||
uint32_t baudrate;
|
|
||||||
uint32_t databits;
|
|
||||||
uint32_t stopbits;
|
|
||||||
uint32_t parity;
|
|
||||||
PinName pin_tx;
|
|
||||||
PinName pin_rx;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pwmout_s {
|
|
||||||
PWMName pwm;
|
|
||||||
PinName pin;
|
|
||||||
uint32_t prescaler;
|
|
||||||
uint32_t period;
|
|
||||||
uint32_t pulse;
|
|
||||||
uint32_t channel;
|
|
||||||
uint32_t inverted;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct can_s {
|
struct can_s {
|
||||||
CANName can;
|
CANName can;
|
||||||
int index;
|
int index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "common_objects.h"
|
||||||
#include "gpio_object.h"
|
#include "gpio_object.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -49,6 +49,21 @@ struct pwmout_s {
|
||||||
uint8_t inverted;
|
uint8_t inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
PinName pin_mosi;
|
||||||
|
PinName pin_sclk;
|
||||||
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
UARTName uart;
|
UARTName uart;
|
||||||
int index; // Used by irq
|
int index; // Used by irq
|
||||||
|
|
|
@ -33,199 +33,27 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
|
||||||
|
|
||||||
static void init_spi(spi_t *obj)
|
#if DEVICE_SPI_ASYNCH
|
||||||
{
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
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;
|
|
||||||
|
|
||||||
HAL_SPI_Init(&SpiHandle);
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
#if defined(SPI1_BASE)
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI3_BASE)
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__SPI3_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI4_BASE)
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__SPI4_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
#if defined(TARGET_STM32F334C8)
|
|
||||||
obj->br_presc = SPI_BAUDRATEPRESCALER_256;
|
|
||||||
#else
|
#else
|
||||||
obj->br_presc = SPI_BAUDRATEPRESCALER_32; // 1 MHz (HSI) or 1.13 MHz (HSE)
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
/*
|
||||||
obj->pin_mosi = mosi;
|
* Only the frequency is managed in the family specific part
|
||||||
obj->pin_sclk = sclk;
|
* the rest of SPI management is common to all STM32 families
|
||||||
obj->pin_ssel = ssel;
|
*/
|
||||||
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
if (ssel != NC) {
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
#if defined(SPI1_BASE)
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_FORCE_RESET();
|
|
||||||
__SPI1_RELEASE_RESET();
|
|
||||||
__SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_FORCE_RESET();
|
|
||||||
__SPI2_RELEASE_RESET();
|
|
||||||
__SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI3_BASE)
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__SPI3_FORCE_RESET();
|
|
||||||
__SPI3_RELEASE_RESET();
|
|
||||||
__SPI3_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPI4_BASE)
|
|
||||||
if (obj->spi == SPI_4) {
|
|
||||||
__SPI4_FORCE_RESET();
|
|
||||||
__SPI4_RELEASE_RESET();
|
|
||||||
__SPI4_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
#if defined SPI1_BASE
|
#if defined SPI1_BASE
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
/* SPI_1. Source CLK is PCKL2 */
|
/* SPI_1. Source CLK is PCKL2 */
|
||||||
|
@ -245,120 +73,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -196,8 +196,8 @@ const PinMap PinMap_SPI_SCLK[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_SSEL[] = {
|
const PinMap PinMap_SPI_SSEL[] = {
|
||||||
{PA_4, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
// {PA_4, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
||||||
// {PA_4, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
{PA_4, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
||||||
{PA_15, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
{PA_15, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
||||||
// {PA_15, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
// {PA_15, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
||||||
{PB_1, SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI5)},
|
{PB_1, SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI5)},
|
||||||
|
|
|
@ -208,8 +208,8 @@ const PinMap PinMap_SPI_SCLK[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_SSEL[] = {
|
const PinMap PinMap_SPI_SSEL[] = {
|
||||||
{PA_4, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
// {PA_4, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
||||||
// {PA_4, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
{PA_4, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
||||||
{PA_15, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
{PA_15, SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
|
||||||
// {PA_15, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
// {PA_15, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
|
||||||
{PB_1, SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI5)},
|
{PB_1, SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI5)},
|
||||||
|
|
|
@ -39,248 +39,19 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
#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
|
#if DEVICE_SPI_ASYNCH
|
||||||
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
#else
|
#else
|
||||||
#define SPI_S(obj) (( struct spi_s *)(obj))
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEBUG_STDIO
|
/*
|
||||||
# define DEBUG_STDIO 0
|
* Only the frequency is managed in the family specific part
|
||||||
#endif
|
* the rest of SPI management is common to all STM32 families
|
||||||
|
*/
|
||||||
#if DEBUG_STDIO
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
# include <stdio.h>
|
|
||||||
# define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
|
|
||||||
#else
|
|
||||||
# define DEBUG_PRINTF(...) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void init_spi(spi_t *obj)
|
|
||||||
{
|
|
||||||
struct spi_s *spiobj = SPI_S(obj);
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
|
|
||||||
__HAL_SPI_DISABLE(handle);
|
|
||||||
|
|
||||||
DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance);
|
|
||||||
if (HAL_SPI_Init(handle) != HAL_OK) {
|
|
||||||
error("Cannot initialize SPI");
|
|
||||||
}
|
|
||||||
|
|
||||||
__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);
|
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
|
||||||
|
|
||||||
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
|
||||||
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
|
||||||
|
|
||||||
spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
|
||||||
MBED_ASSERT(spiobj->spi != (SPIName)NC);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (spiobj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI1_IRQn;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spiobj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI2_IRQn;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined SPI3_BASE
|
|
||||||
if (spiobj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI3_IRQn;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI4_BASE
|
|
||||||
if (spiobj->spi == SPI_4) {
|
|
||||||
__HAL_RCC_SPI4_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI4_IRQn;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI5_BASE
|
|
||||||
if (spiobj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI5_IRQn;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI6_BASE
|
|
||||||
if (spiobj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_CLK_ENABLE();
|
|
||||||
spiobj->spiIRQ = SPI6_IRQn;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
pinmap_pinout(miso, PinMap_SPI_MISO);
|
|
||||||
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
|
||||||
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 {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (spiobj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI1_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (spiobj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI3_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI3_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI4_BASE
|
|
||||||
if (spiobj->spi == SPI_4) {
|
|
||||||
__HAL_RCC_SPI4_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI4_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI4_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI5_BASE
|
|
||||||
if (spiobj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI5_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI5_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined SPI6_BASE
|
|
||||||
if (spiobj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI6_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI6_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure GPIOs
|
|
||||||
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 (handle->Init.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);
|
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
|
|
||||||
DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave);
|
|
||||||
|
|
||||||
// Save new values
|
|
||||||
handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT;
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
handle->Init.CLKPolarity = SPI_POLARITY_LOW;
|
|
||||||
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
handle->Init.CLKPolarity = SPI_POLARITY_LOW;
|
|
||||||
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
|
|
||||||
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
|
|
||||||
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle->Init.NSS != SPI_NSS_SOFT) {
|
|
||||||
handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
struct spi_s *spiobj = SPI_S(obj);
|
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
DEBUG_PRINTF("spi_frequency:%d\r\n", hz);
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)spiobj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
|
@ -305,284 +76,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
}
|
|
||||||
|
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
struct spi_s *spiobj = SPI_S(obj);
|
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
struct spi_s *spiobj = SPI_S(obj);
|
|
||||||
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
|
||||||
|
|
||||||
// Check if data is transmitted
|
|
||||||
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_INST(obj);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = SPI_INST(obj);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
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_INST(obj);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
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;
|
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
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) {
|
|
||||||
// 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);
|
|
||||||
} 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) {
|
|
||||||
// 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
|
|
||||||
event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
|
||||||
|
|
||||||
if (error & HAL_SPI_ERROR_OVR) {
|
|
||||||
// buffer overrun
|
|
||||||
event |= SPI_EVENT_RX_OVERFLOW;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// else we're done
|
|
||||||
event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -49,6 +49,21 @@ struct pwmout_s {
|
||||||
uint8_t inverted;
|
uint8_t inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
PinName pin_mosi;
|
||||||
|
PinName pin_sclk;
|
||||||
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
UARTName uart;
|
UARTName uart;
|
||||||
int index; // Used by irq
|
int index; // Used by irq
|
||||||
|
|
|
@ -33,202 +33,27 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
|
#else
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
|
#endif
|
||||||
|
|
||||||
static void init_spi(spi_t *obj)
|
/*
|
||||||
{
|
* Only the frequency is managed in the family specific part
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
* the rest of SPI management is common to all STM32 families
|
||||||
|
*/
|
||||||
__HAL_SPI_DISABLE(&SpiHandle);
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
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) {
|
|
||||||
error("Cannot initialize SPI");
|
|
||||||
}
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_4) {
|
|
||||||
__HAL_RCC_SPI4_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI1_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI2_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI3_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI3_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_4) {
|
|
||||||
__HAL_RCC_SPI4_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI4_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI4_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_5) {
|
|
||||||
__HAL_RCC_SPI5_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI5_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI5_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_6) {
|
|
||||||
__HAL_RCC_SPI6_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI6_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI6_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
case SPI_4:
|
case SPI_4:
|
||||||
case SPI_5:
|
case SPI_5:
|
||||||
|
@ -242,120 +67,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,20 +60,6 @@ struct analogin_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,6 +49,21 @@ struct pwmout_s {
|
||||||
uint8_t inverted;
|
uint8_t inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
PinName pin_mosi;
|
||||||
|
PinName pin_sclk;
|
||||||
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
UARTName uart;
|
UARTName uart;
|
||||||
int index; // Used by irq
|
int index; // Used by irq
|
||||||
|
|
|
@ -33,166 +33,28 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
static void init_spi(spi_t *obj)
|
#else
|
||||||
{
|
#define SPI_S(obj) (( struct spi_s *)(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) {
|
|
||||||
error("Cannot initialize SPI");
|
|
||||||
}
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
pinmap_pinout(miso, PinMap_SPI_MISO);
|
|
||||||
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
|
||||||
|
|
||||||
// Save new values
|
/*
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
* Only the frequency is managed in the family specific part
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
* the rest of SPI management is common to all STM32 families
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
*/
|
||||||
obj->br_presc = SPI_BAUDRATEPRESCALER_256;
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_FORCE_RESET();
|
|
||||||
__SPI1_RELEASE_RESET();
|
|
||||||
__SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_FORCE_RESET();
|
|
||||||
__SPI2_RELEASE_RESET();
|
|
||||||
__SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Configure GPIO
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
/* SPI_1. Source CLK is PCKL2 */
|
/* SPI_1. Source CLK is PCKL2 */
|
||||||
spi_hz = HAL_RCC_GetPCLK2Freq();
|
spi_hz = HAL_RCC_GetPCLK2Freq();
|
||||||
|
@ -204,92 +66,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return (ssp_readable(obj) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -65,20 +65,6 @@ struct dac_s {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -65,20 +65,6 @@ struct dac_s {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -65,20 +65,6 @@ struct dac_s {
|
||||||
PinName pin;
|
PinName pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,6 +66,21 @@ struct serial_s {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
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"
|
#include "gpio_object.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -33,167 +33,27 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
|
||||||
|
|
||||||
static void init_spi(spi_t *obj)
|
#if DEVICE_SPI_ASYNCH
|
||||||
{
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
#else
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||||
|
#endif
|
||||||
|
|
||||||
__HAL_SPI_DISABLE(&SpiHandle);
|
/*
|
||||||
|
* Only the frequency is managed in the family specific part
|
||||||
SpiHandle.Init.Mode = obj->mode;
|
* the rest of SPI management is common to all STM32 families
|
||||||
SpiHandle.Init.BaudRatePrescaler = obj->br_presc;
|
*/
|
||||||
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
SpiHandle.Init.CLKPhase = obj->cpha;
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
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;
|
|
||||||
|
|
||||||
HAL_SPI_Init(&SpiHandle);
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__SPI3_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel != NC) {
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
} else {
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__SPI1_FORCE_RESET();
|
|
||||||
__SPI1_RELEASE_RESET();
|
|
||||||
__SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__SPI2_FORCE_RESET();
|
|
||||||
__SPI2_RELEASE_RESET();
|
|
||||||
__SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__SPI3_FORCE_RESET();
|
|
||||||
__SPI3_RELEASE_RESET();
|
|
||||||
__SPI3_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure GPIO
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->nss != SPI_NSS_SOFT) {
|
|
||||||
obj->nss = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
/* SPI_1. Source CLK is PCKL2 */
|
/* SPI_1. Source CLK is PCKL2 */
|
||||||
spi_hz = HAL_RCC_GetPCLK2Freq();
|
spi_hz = HAL_RCC_GetPCLK2Freq();
|
||||||
|
@ -204,92 +64,10 @@ void spi_frequency(spi_t *obj, int hz)
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return (ssp_readable(obj) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -66,20 +66,6 @@ struct dac_s {
|
||||||
uint32_t channel;
|
uint32_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 {
|
struct i2c_s {
|
||||||
I2CName i2c;
|
I2CName i2c;
|
||||||
uint32_t slave;
|
uint32_t slave;
|
||||||
|
|
|
@ -49,6 +49,21 @@ struct pwmout_s {
|
||||||
uint8_t inverted;
|
uint8_t inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spi_s {
|
||||||
|
SPI_HandleTypeDef handle;
|
||||||
|
IRQn_Type spiIRQ;
|
||||||
|
SPIName spi;
|
||||||
|
PinName pin_miso;
|
||||||
|
PinName pin_mosi;
|
||||||
|
PinName pin_sclk;
|
||||||
|
PinName pin_ssel;
|
||||||
|
#ifdef DEVICE_SPI_ASYNCH
|
||||||
|
uint32_t event;
|
||||||
|
uint8_t module;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_s {
|
struct serial_s {
|
||||||
UARTName uart;
|
UARTName uart;
|
||||||
int index; // Used by irq
|
int index; // Used by irq
|
||||||
|
|
|
@ -32,311 +32,43 @@
|
||||||
|
|
||||||
#if DEVICE_SPI
|
#if DEVICE_SPI
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static SPI_HandleTypeDef SpiHandle;
|
#if DEVICE_SPI_ASYNCH
|
||||||
|
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||||
static void init_spi(spi_t *obj)
|
#else
|
||||||
{
|
#define SPI_S(obj) (( struct spi_s *)(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_DISABLE;
|
|
||||||
SpiHandle.Init.CRCPolynomial = 7;
|
|
||||||
SpiHandle.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
|
|
||||||
SpiHandle.Init.DataSize = obj->bits;
|
|
||||||
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
|
||||||
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
|
|
||||||
SpiHandle.Init.NSS = obj->nss;
|
|
||||||
SpiHandle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
|
|
||||||
|
|
||||||
if (HAL_SPI_Init(&SpiHandle) != HAL_OK) {
|
|
||||||
error("Cannot initialize SPI\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
__HAL_SPI_ENABLE(&SpiHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
|
||||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_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);
|
|
||||||
|
|
||||||
// Enable SPI clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (obj->spi == SPI_3) {
|
|
||||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the SPI pins
|
|
||||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
|
||||||
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;
|
|
||||||
|
|
||||||
obj->pin_miso = miso;
|
|
||||||
obj->pin_mosi = mosi;
|
|
||||||
obj->pin_sclk = sclk;
|
|
||||||
obj->pin_ssel = ssel;
|
|
||||||
|
|
||||||
if (ssel == NC) { // SW NSS Master mode
|
|
||||||
obj->mode = SPI_MODE_MASTER;
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
} else { // Slave
|
|
||||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
|
||||||
obj->mode = SPI_MODE_SLAVE;
|
|
||||||
obj->nss = SPI_NSS_HARD_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_free(spi_t *obj)
|
|
||||||
{
|
|
||||||
// Reset SPI and disable clock
|
|
||||||
if (obj->spi == SPI_1) {
|
|
||||||
__HAL_RCC_SPI1_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI1_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SPI2_BASE)
|
|
||||||
if (obj->spi == SPI_2) {
|
|
||||||
__HAL_RCC_SPI2_FORCE_RESET();
|
|
||||||
__HAL_RCC_SPI2_RELEASE_RESET();
|
|
||||||
__HAL_RCC_SPI2_CLK_DISABLE();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (obj->spi == SPI_3) {
|
/*
|
||||||
__HAL_RCC_SPI3_FORCE_RESET();
|
* Only the frequency is managed in the family specific part
|
||||||
__HAL_RCC_SPI3_RELEASE_RESET();
|
* the rest of SPI management is common to all STM32 families
|
||||||
__HAL_RCC_SPI3_CLK_DISABLE();
|
*/
|
||||||
}
|
int spi_get_clock_freq(spi_t *obj) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
// Configure GPIO
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|
||||||
{
|
|
||||||
// Save new values
|
|
||||||
if (bits == 16) {
|
|
||||||
obj->bits = SPI_DATASIZE_16BIT;
|
|
||||||
} else {
|
|
||||||
obj->bits = SPI_DATASIZE_8BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case 0:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
obj->cpol = SPI_POLARITY_LOW;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_1EDGE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
obj->cpol = SPI_POLARITY_HIGH;
|
|
||||||
obj->cpha = SPI_PHASE_2EDGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slave == 0) {
|
|
||||||
obj->mode = SPI_MODE_MASTER;
|
|
||||||
obj->nss = SPI_NSS_SOFT;
|
|
||||||
} else {
|
|
||||||
obj->mode = SPI_MODE_SLAVE;
|
|
||||||
obj->nss = SPI_NSS_HARD_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
|
||||||
SPI_BAUDRATEPRESCALER_4,
|
|
||||||
SPI_BAUDRATEPRESCALER_8,
|
|
||||||
SPI_BAUDRATEPRESCALER_16,
|
|
||||||
SPI_BAUDRATEPRESCALER_32,
|
|
||||||
SPI_BAUDRATEPRESCALER_64,
|
|
||||||
SPI_BAUDRATEPRESCALER_128,
|
|
||||||
SPI_BAUDRATEPRESCALER_256};
|
|
||||||
|
|
||||||
void spi_frequency(spi_t *obj, int hz)
|
|
||||||
{
|
|
||||||
int spi_hz = 0;
|
int spi_hz = 0;
|
||||||
uint8_t prescaler_rank = 0;
|
|
||||||
|
|
||||||
/* Get source clock depending on SPI instance */
|
/* Get source clock depending on SPI instance */
|
||||||
switch ((int)obj->spi) {
|
switch ((int)spiobj->spi) {
|
||||||
case SPI_1:
|
case SPI_1:
|
||||||
/* SPI_1. Source CLK is PCKL2 */
|
/* SPI_1. Source CLK is PCKL2 */
|
||||||
spi_hz = HAL_RCC_GetPCLK2Freq();
|
spi_hz = HAL_RCC_GetPCLK2Freq();
|
||||||
break;
|
break;
|
||||||
#if defined(SPI2_BASE)
|
#if defined(SPI2_BASE)
|
||||||
case SPI_2:
|
case SPI_2:
|
||||||
#endif
|
#endif
|
||||||
case SPI_3:
|
case SPI_3:
|
||||||
/* SPI_2, SPI_3. Source CLK is PCKL1 */
|
/* SPI_2, SPI_3. Source CLK is PCKL1 */
|
||||||
spi_hz = HAL_RCC_GetPCLK1Freq();
|
spi_hz = HAL_RCC_GetPCLK1Freq();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("SPI instance not set");
|
error("CLK: SPI instance not set");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return spi_hz;
|
||||||
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
|
||||||
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
|
||||||
spi_hz = spi_hz / 2;
|
|
||||||
prescaler_rank++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
|
||||||
obj->br_presc = baudrate_prescaler_table[prescaler_rank-1];
|
|
||||||
} else {
|
|
||||||
error("Couldn't setup requested SPI frequency");
|
|
||||||
}
|
|
||||||
|
|
||||||
init_spi(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_readable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is received
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_writeable(spi_t *obj)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
SpiHandle.Instance = (SPI_TypeDef *)(obj->spi);
|
|
||||||
// Check if data is transmitted
|
|
||||||
status = ((__HAL_SPI_GET_FLAG(&SpiHandle, 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);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
//spi->DR = (uint16_t)value;
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ssp_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
//return (int)spi->DR;
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_master_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
ssp_write(obj, value);
|
|
||||||
return ssp_read(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_slave_receive(spi_t *obj)
|
|
||||||
{
|
|
||||||
return (ssp_readable(obj) ? 1 : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
int spi_slave_read(spi_t *obj)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_readable(obj));
|
|
||||||
//return (int)spi->DR;
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
return (int)(*p_spi_dr);
|
|
||||||
} else {
|
|
||||||
return (int)spi->DR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_slave_write(spi_t *obj, int value)
|
|
||||||
{
|
|
||||||
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
|
|
||||||
while (!ssp_writeable(obj));
|
|
||||||
//spi->DR = (uint16_t)value;
|
|
||||||
if (obj->bits == SPI_DATASIZE_8BIT) {
|
|
||||||
// Force 8-bit access to the data register
|
|
||||||
uint8_t *p_spi_dr = 0;
|
|
||||||
p_spi_dr = (uint8_t *) & (spi->DR);
|
|
||||||
*p_spi_dr = (uint8_t)value;
|
|
||||||
} else { // SPI_DATASIZE_16BIT
|
|
||||||
spi->DR = (uint16_t)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spi_busy(spi_t *obj)
|
|
||||||
{
|
|
||||||
return ssp_busy(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,590 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
*******************************************************************************
|
||||||
|
* Copyright (c) 2015, STMicroelectronics
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*******************************************************************************
|
||||||
|
*/
|
||||||
|
#include "mbed_assert.h"
|
||||||
|
#include "mbed_error.h"
|
||||||
|
#include "spi_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_SPI
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "cmsis.h"
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
|
#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 <stdio.h>
|
||||||
|
# define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
|
||||||
|
#else
|
||||||
|
# define DEBUG_PRINTF(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init_spi(spi_t *obj)
|
||||||
|
{
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
__HAL_SPI_DISABLE(handle);
|
||||||
|
|
||||||
|
DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance);
|
||||||
|
if (HAL_SPI_Init(handle) != HAL_OK) {
|
||||||
|
error("Cannot initialize SPI");
|
||||||
|
}
|
||||||
|
|
||||||
|
__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);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||||
|
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||||
|
|
||||||
|
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||||
|
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
||||||
|
|
||||||
|
spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
||||||
|
MBED_ASSERT(spiobj->spi != (SPIName)NC);
|
||||||
|
|
||||||
|
#if defined SPI1_BASE
|
||||||
|
// Enable SPI clock
|
||||||
|
if (spiobj->spi == SPI_1) {
|
||||||
|
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI1_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI2_BASE
|
||||||
|
if (spiobj->spi == SPI_2) {
|
||||||
|
__HAL_RCC_SPI2_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI2_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI3_BASE
|
||||||
|
if (spiobj->spi == SPI_3) {
|
||||||
|
__HAL_RCC_SPI3_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI3_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI4_BASE
|
||||||
|
if (spiobj->spi == SPI_4) {
|
||||||
|
__HAL_RCC_SPI4_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI4_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI5_BASE
|
||||||
|
if (spiobj->spi == SPI_5) {
|
||||||
|
__HAL_RCC_SPI5_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI5_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI6_BASE
|
||||||
|
if (spiobj->spi == SPI_6) {
|
||||||
|
__HAL_RCC_SPI6_CLK_ENABLE();
|
||||||
|
spiobj->spiIRQ = SPI6_IRQn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure the SPI pins
|
||||||
|
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
||||||
|
pinmap_pinout(miso, PinMap_SPI_MISO);
|
||||||
|
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
||||||
|
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 {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#if defined SPI1_BASE
|
||||||
|
// Reset SPI and disable clock
|
||||||
|
if (spiobj->spi == SPI_1) {
|
||||||
|
__HAL_RCC_SPI1_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI1_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI1_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined SPI2_BASE
|
||||||
|
if (spiobj->spi == SPI_2) {
|
||||||
|
__HAL_RCC_SPI2_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI2_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI2_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI3_BASE
|
||||||
|
if (spiobj->spi == SPI_3) {
|
||||||
|
__HAL_RCC_SPI3_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI3_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI3_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI4_BASE
|
||||||
|
if (spiobj->spi == SPI_4) {
|
||||||
|
__HAL_RCC_SPI4_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI4_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI4_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI5_BASE
|
||||||
|
if (spiobj->spi == SPI_5) {
|
||||||
|
__HAL_RCC_SPI5_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI5_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI5_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined SPI6_BASE
|
||||||
|
if (spiobj->spi == SPI_6) {
|
||||||
|
__HAL_RCC_SPI6_FORCE_RESET();
|
||||||
|
__HAL_RCC_SPI6_RELEASE_RESET();
|
||||||
|
__HAL_RCC_SPI6_CLK_DISABLE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Configure GPIOs
|
||||||
|
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 (handle->Init.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);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave);
|
||||||
|
|
||||||
|
// Save new values
|
||||||
|
handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
handle->Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||||
|
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
handle->Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||||
|
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||||
|
handle->Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle->Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||||
|
handle->Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->Init.NSS != SPI_NSS_SOFT) {
|
||||||
|
handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
|
||||||
|
|
||||||
|
init_spi(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only the IP clock input is family dependant so it computed
|
||||||
|
* separately in spi_get_clock_freq
|
||||||
|
*/
|
||||||
|
extern int spi_get_clock_freq(spi_t *obj);
|
||||||
|
|
||||||
|
static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2,
|
||||||
|
SPI_BAUDRATEPRESCALER_4,
|
||||||
|
SPI_BAUDRATEPRESCALER_8,
|
||||||
|
SPI_BAUDRATEPRESCALER_16,
|
||||||
|
SPI_BAUDRATEPRESCALER_32,
|
||||||
|
SPI_BAUDRATEPRESCALER_64,
|
||||||
|
SPI_BAUDRATEPRESCALER_128,
|
||||||
|
SPI_BAUDRATEPRESCALER_256};
|
||||||
|
|
||||||
|
void spi_frequency(spi_t *obj, int hz) {
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
int spi_hz = 0;
|
||||||
|
uint8_t prescaler_rank = 0;
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
/* Get the clock of the peripheral */
|
||||||
|
spi_hz = spi_get_clock_freq(obj);
|
||||||
|
|
||||||
|
/* Define pre-scaler in order to get highest available frequency below requested frequency */
|
||||||
|
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
|
||||||
|
spi_hz = spi_hz / 2;
|
||||||
|
prescaler_rank++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
|
||||||
|
handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank-1];
|
||||||
|
} else {
|
||||||
|
error("Couldn't setup requested SPI frequency");
|
||||||
|
}
|
||||||
|
|
||||||
|
init_spi(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_readable(spi_t *obj)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
// Check if data is received
|
||||||
|
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_writeable(spi_t *obj)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
// Check if data is transmitted
|
||||||
|
status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ssp_busy(spi_t *obj)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_master_write(spi_t *obj, int value)
|
||||||
|
{
|
||||||
|
uint16_t size, Rx, ret;
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
|
||||||
|
size = (handle->Init.DataSize == SPI_DATASIZE_16BIT) ? 2 : 1;
|
||||||
|
|
||||||
|
/* Use 10ms timeout */
|
||||||
|
ret = HAL_SPI_TransmitReceive(handle,(uint8_t*)&value,(uint8_t*)&Rx,size,10);
|
||||||
|
|
||||||
|
if(ret == HAL_OK) {
|
||||||
|
return Rx;
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTF("SPI inst=0x%8X ERROR in write\r\n", (int)handle->Instance);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_slave_receive(spi_t *obj)
|
||||||
|
{
|
||||||
|
return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
int spi_slave_read(spi_t *obj)
|
||||||
|
{
|
||||||
|
SPI_TypeDef *spi = SPI_INST(obj);
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
while (!ssp_readable(obj));
|
||||||
|
if (handle->Init.DataSize == SPI_DATASIZE_8BIT) {
|
||||||
|
// Force 8-bit access to the data register
|
||||||
|
uint8_t *p_spi_dr = 0;
|
||||||
|
p_spi_dr = (uint8_t *) & (spi->DR);
|
||||||
|
return (int)(*p_spi_dr);
|
||||||
|
} else {
|
||||||
|
return (int)spi->DR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_slave_write(spi_t *obj, int value)
|
||||||
|
{
|
||||||
|
SPI_TypeDef *spi = SPI_INST(obj);
|
||||||
|
struct spi_s *spiobj = SPI_S(obj);
|
||||||
|
SPI_HandleTypeDef *handle = &(spiobj->handle);
|
||||||
|
while (!ssp_writeable(obj));
|
||||||
|
if (handle->Init.DataSize == SPI_DATASIZE_8BIT) {
|
||||||
|
// Force 8-bit access to the data register
|
||||||
|
uint8_t *p_spi_dr = 0;
|
||||||
|
p_spi_dr = (uint8_t *) & (spi->DR);
|
||||||
|
*p_spi_dr = (uint8_t)value;
|
||||||
|
} else { // SPI_DATASIZE_16BIT
|
||||||
|
spi->DR = (uint16_t)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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:
|
||||||
|
rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words);
|
||||||
|
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) {
|
||||||
|
// 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);
|
||||||
|
} 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) {
|
||||||
|
// 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
|
||||||
|
event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||||
|
|
||||||
|
if (error & HAL_SPI_ERROR_OVR) {
|
||||||
|
// buffer overrun
|
||||||
|
event |= SPI_EVENT_RX_OVERFLOW;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// else we're done
|
||||||
|
event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
|
@ -595,7 +595,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0725"],
|
"detect_code": ["0725"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F030R8"
|
"device_name": "STM32F030R8"
|
||||||
|
@ -605,11 +606,11 @@
|
||||||
"core": "Cortex-M0",
|
"core": "Cortex-M0",
|
||||||
"default_toolchain": "uARM",
|
"default_toolchain": "uARM",
|
||||||
"extra_labels": ["STM", "STM32F0", "STM32F031K6"],
|
"extra_labels": ["STM", "STM32F0", "STM32F031K6"],
|
||||||
"macros": ["RTC_LSI=1"],
|
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0791"],
|
"detect_code": ["0791"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F031K6"
|
"device_name": "STM32F031K6"
|
||||||
|
@ -619,11 +620,11 @@
|
||||||
"core": "Cortex-M0",
|
"core": "Cortex-M0",
|
||||||
"default_toolchain": "uARM",
|
"default_toolchain": "uARM",
|
||||||
"extra_labels": ["STM", "STM32F0", "STM32F042K6"],
|
"extra_labels": ["STM", "STM32F0", "STM32F042K6"],
|
||||||
"macros": ["RTC_LSI=1"],
|
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0785"],
|
"detect_code": ["0785"],
|
||||||
"device_has": ["ANALOGIN", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F042K6"
|
"device_name": "STM32F042K6"
|
||||||
|
@ -636,7 +637,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0755"],
|
"detect_code": ["0755"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F070RB"
|
"device_name": "STM32F070RB"
|
||||||
},
|
},
|
||||||
|
@ -648,7 +650,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0730"],
|
"detect_code": ["0730"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F072RB"
|
"device_name": "STM32F072RB"
|
||||||
},
|
},
|
||||||
|
@ -660,7 +663,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0750"],
|
"detect_code": ["0750"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F091RC"
|
"device_name": "STM32F091RC"
|
||||||
},
|
},
|
||||||
|
@ -672,7 +676,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0700"],
|
"detect_code": ["0700"],
|
||||||
"device_has": ["ANALOGIN", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F103RB"
|
"device_name": "STM32F103RB"
|
||||||
},
|
},
|
||||||
|
@ -684,7 +689,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0835"],
|
"detect_code": ["0835"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "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", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"features": ["LWIP"],
|
"features": ["LWIP"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name" : "STM32F207ZG"
|
"device_name" : "STM32F207ZG"
|
||||||
|
@ -697,7 +703,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0705"],
|
"detect_code": ["0705"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "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", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F302R8"
|
"device_name": "STM32F302R8"
|
||||||
|
@ -707,12 +714,12 @@
|
||||||
"core": "Cortex-M4F",
|
"core": "Cortex-M4F",
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"extra_labels": ["STM", "STM32F3", "STM32F303K8"],
|
"extra_labels": ["STM", "STM32F3", "STM32F303K8"],
|
||||||
"macros": ["RTC_LSI=1"],
|
"macros": ["RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0775"],
|
"detect_code": ["0775"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F303K8"
|
"device_name": "STM32F303K8"
|
||||||
},
|
},
|
||||||
|
@ -724,7 +731,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0745"],
|
"detect_code": ["0745"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "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", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F303RE"
|
"device_name": "STM32F303RE"
|
||||||
},
|
},
|
||||||
|
@ -736,7 +744,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0747"],
|
"detect_code": ["0747"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F303RE"
|
"device_name": "STM32F303RE"
|
||||||
},
|
},
|
||||||
|
@ -748,7 +757,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0735"],
|
"detect_code": ["0735"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "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", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F334R8"
|
"device_name": "STM32F334R8"
|
||||||
|
@ -788,7 +798,7 @@
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0740"],
|
"detect_code": ["0740"],
|
||||||
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ERROR_RED", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F411RE"
|
"device_name": "STM32F411RE"
|
||||||
},
|
},
|
||||||
|
@ -866,9 +876,10 @@
|
||||||
"extra_labels": ["STM", "STM32F7", "STM32F746", "STM32F746ZG"],
|
"extra_labels": ["STM", "STM32F7", "STM32F746", "STM32F746ZG"],
|
||||||
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"supported_form_factors": ["ARDUINO"],
|
"supported_form_factors": ["ARDUINO"],
|
||||||
"detect_code": ["0816"],
|
"detect_code": ["0816"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"features": ["LWIP"],
|
"features": ["LWIP"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F746ZG"
|
"device_name": "STM32F746ZG"
|
||||||
|
@ -880,8 +891,9 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
"supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"supported_form_factors": ["ARDUINO"],
|
"supported_form_factors": ["ARDUINO"],
|
||||||
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"detect_code": ["0818"],
|
"detect_code": ["0818"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"features": ["LWIP"],
|
"features": ["LWIP"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name" : "STM32F767ZI"
|
"device_name" : "STM32F767ZI"
|
||||||
|
@ -957,7 +969,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0770"],
|
"detect_code": ["0770"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "CAN", "STDIO_MESSAGES", "TRNG"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "CAN", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name" : "STM32L432KC"
|
"device_name" : "STM32L432KC"
|
||||||
},
|
},
|
||||||
|
@ -969,7 +982,8 @@
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"detect_code": ["0765"],
|
"detect_code": ["0765"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "stm32l476rg"
|
"device_name": "stm32l476rg"
|
||||||
},
|
},
|
||||||
|
@ -994,7 +1008,8 @@
|
||||||
"extra_labels": ["STM", "STM32F4", "STM32F407", "STM32F407VG"],
|
"extra_labels": ["STM", "STM32F4", "STM32F407", "STM32F407VG"],
|
||||||
"macros": ["LSI_VALUE=32000"],
|
"macros": ["LSI_VALUE=32000"],
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F407VG"
|
"device_name": "STM32F407VG"
|
||||||
},
|
},
|
||||||
|
@ -1004,7 +1019,8 @@
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"extra_labels": ["STM", "STM32F0", "STM32F051", "STM32F051R8"],
|
"extra_labels": ["STM", "STM32F0", "STM32F051", "STM32F051R8"],
|
||||||
"supported_toolchains": ["GCC_ARM"],
|
"supported_toolchains": ["GCC_ARM"],
|
||||||
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"device_name": "STM32F051R8"
|
"device_name": "STM32F051R8"
|
||||||
},
|
},
|
||||||
"DISCO_F100RB": {
|
"DISCO_F100RB": {
|
||||||
|
@ -1013,7 +1029,8 @@
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"extra_labels": ["STM", "STM32F1", "STM32F100RB"],
|
"extra_labels": ["STM", "STM32F1", "STM32F100RB"],
|
||||||
"supported_toolchains": ["GCC_ARM"],
|
"supported_toolchains": ["GCC_ARM"],
|
||||||
"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"],
|
||||||
"device_name": "STM32F100RB"
|
"device_name": "STM32F100RB"
|
||||||
},
|
},
|
||||||
"DISCO_F303VC": {
|
"DISCO_F303VC": {
|
||||||
|
@ -1021,9 +1038,9 @@
|
||||||
"core": "Cortex-M4F",
|
"core": "Cortex-M4F",
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"extra_labels": ["STM", "STM32F3", "STM32F303", "STM32F303VC"],
|
"extra_labels": ["STM", "STM32F3", "STM32F303", "STM32F303VC"],
|
||||||
"macros": ["RTC_LSI=1"],
|
"macros": ["RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"supported_toolchains": ["GCC_ARM"],
|
"supported_toolchains": ["GCC_ARM"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"device_name": "STM32F303VC"
|
"device_name": "STM32F303VC"
|
||||||
},
|
},
|
||||||
"DISCO_F334C8": {
|
"DISCO_F334C8": {
|
||||||
|
@ -1031,10 +1048,10 @@
|
||||||
"core": "Cortex-M4F",
|
"core": "Cortex-M4F",
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"extra_labels": ["STM", "STM32F3", "STM32F334C8"],
|
"extra_labels": ["STM", "STM32F3", "STM32F334C8"],
|
||||||
"macros": ["RTC_LSI=1"],
|
"macros": ["RTC_LSI=1", "TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"detect_code": ["0810"],
|
"detect_code": ["0810"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_lib": "small",
|
"default_lib": "small",
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F334C8"
|
"device_name": "STM32F334C8"
|
||||||
|
@ -1068,7 +1085,7 @@
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
"detect_code": ["0788"],
|
"detect_code": ["0788"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F469NI"
|
"device_name": "STM32F469NI"
|
||||||
},
|
},
|
||||||
|
@ -1091,7 +1108,8 @@
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"supported_form_factors": ["ARDUINO"],
|
"supported_form_factors": ["ARDUINO"],
|
||||||
"detect_code": ["0815"],
|
"detect_code": ["0815"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"features": ["LWIP"],
|
"features": ["LWIP"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "STM32F746NG"
|
"device_name": "STM32F746NG"
|
||||||
|
@ -1103,7 +1121,8 @@
|
||||||
"supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
|
"supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
|
||||||
"default_toolchain": "ARM",
|
"default_toolchain": "ARM",
|
||||||
"detect_code": ["0817"],
|
"detect_code": ["0817"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"features": ["LWIP"],
|
"features": ["LWIP"],
|
||||||
"release_versions": ["2"],
|
"release_versions": ["2"],
|
||||||
"device_name": "STM32F769NI"
|
"device_name": "STM32F769NI"
|
||||||
|
@ -1115,7 +1134,8 @@
|
||||||
"extra_labels": ["STM", "STM32L4", "STM32L476VG"],
|
"extra_labels": ["STM", "STM32L4", "STM32L476VG"],
|
||||||
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
|
||||||
"detect_code": ["0820"],
|
"detect_code": ["0820"],
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
|
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
|
||||||
|
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
|
||||||
"release_versions": ["2", "5"],
|
"release_versions": ["2", "5"],
|
||||||
"device_name": "stm32l476vg"
|
"device_name": "stm32l476vg"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue