Add spi_get_capabilities() function to HAL API

Add also default weak version of spi_get_capabilities() which provides default/most common SPI parameters.
This function can be replaced if a specific target has different capabilities.
pull/11682/head
Przemyslaw Stekiel 2019-11-05 12:34:31 +01:00
parent 766c3647d7
commit 4b1b4f72af
2 changed files with 82 additions and 0 deletions

View File

@ -17,6 +17,7 @@
#include "analogin_api.h" #include "analogin_api.h"
#include "i2c_api.h" #include "i2c_api.h"
#include "spi_api.h"
#include "gpio_api.h" #include "gpio_api.h"
#include "mbed_toolchain.h" #include "mbed_toolchain.h"
@ -41,3 +42,52 @@ MBED_WEAK void analogin_free(analogin_t *obj)
// Do nothing // Do nothing
} }
#endif #endif
#if DEVICE_SPI
// Default SPI capabilities. If specific target has different capabilities this function needs to be re-implemented.
MBED_WEAK void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap)
{
if (slave) {
cap->minimum_frequency = 200000; // 200 kHz
cap->maximum_frequency = 2000000; // 2 MHz
cap->word_length = 0x00008080; // 8 and 16 bit symbols
cap->support_slave_mode = false; // to be determined later based on ssel
cap->hw_cs_handle = false; // irrelevant in slave mode
cap->slave_delay_between_symbols_ns = 2500; // 2.5 us
cap->clk_modes = 0x0f; // all clock modes
#if DEVICE_SPI_ASYNCH
cap->async_mode = true;
#else
cap->async_mode = false;
#endif
} else {
cap->minimum_frequency = 200000; // 200 kHz
cap->maximum_frequency = 2000000; // 2 MHz
cap->word_length = 0x00008080; // 8 and 16 bit symbols
cap->support_slave_mode = false; // to be determined later based on ssel
cap->hw_cs_handle = false; // to be determined later based on ssel
cap->slave_delay_between_symbols_ns = 0; // irrelevant in master mode
cap->clk_modes = 0x0f; // all clock modes
#if DEVICE_SPI_ASYNCH
cap->async_mode = true;
#else
cap->async_mode = false;
#endif
}
// check if given ssel pin is in the cs pinmap
const PinMap *cs_pins = spi_master_cs_pinmap();
PinName pin = NC;
while (cs_pins->pin != NC) {
if (cs_pins->pin == ssel) {
#if DEVICE_SPISLAVE
cap->support_slave_mode = true;
#endif
cap->hw_cs_handle = true;
break;
}
cs_pins++;
}
}
#endif

View File

@ -53,6 +53,28 @@ typedef struct spi_s spi_t;
#endif #endif
/**
* Describes the capabilities of a SPI peripherals
*/
typedef struct {
/** Minimum frequency supported must be set by target device and it will be assessed during
* testing.
*/
uint32_t minimum_frequency;
/** Maximum frequency supported must be set by target device and it will be assessed during
* testing.
*/
uint32_t maximum_frequency;
/** Each bit represents the corresponding word length. lsb => 1bit, msb => 32bit. */
uint32_t word_length;
uint16_t slave_delay_between_symbols_ns; /**< specifies required number of ns between transmission of successive symbols in slave mode. */
uint8_t clk_modes; /**< specifies supported modes from spi_mode_t. Each bit represents the corresponding mode. */
bool support_slave_mode; /**< If true, the device can handle SPI slave mode using hardware management on the specified ssel pin. */
bool hw_cs_handle; /**< If true, in SPI master mode Chip Select can be handled by hardware. */
bool async_mode; /**< If true, in async mode is supported. */
} spi_capabilities_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -63,6 +85,11 @@ extern "C" {
* # Defined behavior * # Defined behavior
* * ::spi_init initializes the spi_t control structure * * ::spi_init initializes the spi_t control structure
* * ::spi_init configures the pins used by SPI * * ::spi_init configures the pins used by SPI
* * ::spi_get_capabilities() fills the given `spi_capabilities_t` instance
* * ::spi_get_capabilities() should consider the `ssel` pin when evaluation the `support_slave_mode` and `hw_cs_handle` capability
* * ::spi_get_capabilities(): if the given `ssel` pin cannot be managed by hardware, `support_slave_mode` and `hw_cs_handle` should be false
* * At least a symbol width of 8bit must be supported
* * The supported frequency range must include the range [0.2..2] MHz
* * ::spi_free returns the pins owned by the SPI object to their reset state * * ::spi_free returns the pins owned by the SPI object to their reset state
* * ::spi_format sets the number of bits per frame * * ::spi_format sets the number of bits per frame
* * ::spi_format configures clock polarity and phase * * ::spi_format configures clock polarity and phase
@ -125,6 +152,11 @@ extern "C" {
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName mclk); SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName mclk);
#endif #endif
/**
* Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
*/
void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap);
/** Initialize the SPI peripheral /** Initialize the SPI peripheral
* *
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral