Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make FPGA tests to pass on CI targets (SPI, analogIn, PWM) #11682

Merged
merged 6 commits into from
Nov 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions TESTS/mbed_hal_fpga_ci_test_shield/pwm/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,26 +190,26 @@ Case cases[] = {
Case("PWM - period: 10 ms, fill: 90%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<10, 90, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 10 ms, fill: 90%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<10, 90, PERIOD_PULSEWIDTH_US> >),

Case("PWM - period: 50 ms, fill: 10%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_WRITE> >),
Case("PWM - period: 50 ms, fill: 10%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_MS_WRITE> >),
Case("PWM - period: 50 ms, fill: 10%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_US_WRITE> >),
Case("PWM - period: 50 ms, fill: 10%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 50 ms, fill: 10%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 50 ms, fill: 10%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 10, PERIOD_PULSEWIDTH_US> >),

Case("PWM - period: 50 ms, fill: 50%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_WRITE> >),
Case("PWM - period: 50 ms, fill: 50%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_MS_WRITE> >),
Case("PWM - period: 50 ms, fill: 50%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_US_WRITE> >),
Case("PWM - period: 50 ms, fill: 50%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 50 ms, fill: 50%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 50 ms, fill: 50%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 50, PERIOD_PULSEWIDTH_US> >),

Case("PWM - period: 50 ms, fill: 90%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_WRITE> >),
Case("PWM - period: 50 ms, fill: 90%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_MS_WRITE> >),
Case("PWM - period: 50 ms, fill: 90%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_US_WRITE> >),
Case("PWM - period: 50 ms, fill: 90%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 50 ms, fill: 90%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 50 ms, fill: 90%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<50, 90, PERIOD_PULSEWIDTH_US> >)
Case("PWM - period: 30 ms, fill: 10%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_WRITE> >),
Case("PWM - period: 30 ms, fill: 10%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_MS_WRITE> >),
Case("PWM - period: 30 ms, fill: 10%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_US_WRITE> >),
Case("PWM - period: 30 ms, fill: 10%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 30 ms, fill: 10%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 30 ms, fill: 10%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 10, PERIOD_PULSEWIDTH_US> >),

Case("PWM - period: 30 ms, fill: 50%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_WRITE> >),
Case("PWM - period: 30 ms, fill: 50%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_MS_WRITE> >),
Case("PWM - period: 30 ms, fill: 50%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_US_WRITE> >),
Case("PWM - period: 30 ms, fill: 50%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 30 ms, fill: 50%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 30 ms, fill: 50%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 50, PERIOD_PULSEWIDTH_US> >),

Case("PWM - period: 30 ms, fill: 90%, api: period/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_WRITE> >),
Case("PWM - period: 30 ms, fill: 90%, api: period_ms/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_MS_WRITE> >),
Case("PWM - period: 30 ms, fill: 90%, api: period_us/write", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_US_WRITE> >),
Case("PWM - period: 30 ms, fill: 90%, api: period/pulse_width", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_PULSEWIDTH> >),
Case("PWM - period: 30 ms, fill: 90%, api: period/pulse_width_ms", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_PULSEWIDTH_MS> >),
Case("PWM - period: 30 ms, fill: 90%, api: period/pulse_width_us", one_peripheral<PWMPort, DefaultFormFactor, fpga_pwm_period_fill_test<30, 90, PERIOD_PULSEWIDTH_US> >)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
Expand Down
53 changes: 46 additions & 7 deletions TESTS/mbed_hal_fpga_ci_test_shield/spi/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ typedef enum {
TRANSFER_SPI_MASTER_TRANSFER_ASYNC
} transfer_type_t;

#define FREQ_500_KHZ 500000
#define FREQ_1_MHZ 1000000
#define FREQ_2_MHZ 2000000
#define FREQ_500_KHZ 500000
#define FREQ_1_MHZ 1000000
#define FREQ_2_MHZ 2000000
#define FREQ_MIN ((uint32_t)0)
#define FREQ_MAX ((uint32_t)-1)

#define TEST_CAPABILITY_BIT(MASK, CAP) ((1 << CAP) & (MASK))

const int TRANSFER_COUNT = 300;
SPIMasterTester tester(DefaultFormFactor::pins(), DefaultFormFactor::restricted_pins());
Expand All @@ -62,6 +66,36 @@ void spi_async_handler()
}
#endif

/* Auxiliary function to check platform capabilities against test case. */
static bool check_capabilities(const spi_capabilities_t *capabilities, SPITester::SpiMode spi_mode, uint32_t sym_size, transfer_type_t transfer_type, uint32_t frequency)
{
// Symbol size
if (!TEST_CAPABILITY_BIT(capabilities->word_length, (sym_size - 1))) {
utest_printf("\n<Specified symbol size is not supported on this platform> skipped ");
return false;
}

// SPI clock mode
if (!TEST_CAPABILITY_BIT(capabilities->clk_modes, spi_mode)) {
utest_printf("\n<Specified spi clock mode is not supported on this platform> skipped");
return false;
}

// Frequency
if (frequency != FREQ_MAX && frequency != FREQ_MIN && frequency < capabilities->minimum_frequency && frequency > capabilities->maximum_frequency) {
utest_printf("\n<Specified frequency is not supported on this platform> skipped ");
return false;
}

// Async mode
if (transfer_type == TRANSFER_SPI_MASTER_TRANSFER_ASYNC && capabilities->async_mode == false) {
utest_printf("\n<Async mode is not supported on this platform> skipped ");
return false;
}

return true;
}

void fpga_spi_test_init_free(PinName mosi, PinName miso, PinName sclk, PinName ssel)
{
spi_init(&spi, mosi, miso, sclk, ssel);
Expand All @@ -72,6 +106,15 @@ void fpga_spi_test_init_free(PinName mosi, PinName miso, PinName sclk, PinName s

void fpga_spi_test_common(PinName mosi, PinName miso, PinName sclk, PinName ssel, SPITester::SpiMode spi_mode, uint32_t sym_size, transfer_type_t transfer_type, uint32_t frequency)
{
spi_capabilities_t capabilities;


spi_get_capabilities(ssel, false, &capabilities);

if (check_capabilities(&capabilities, spi_mode, sym_size, transfer_type, frequency) == false) {
return;
}

uint32_t sym_mask = ((1 << sym_size) - 1);

// Remap pins for test
Expand Down Expand Up @@ -178,14 +221,10 @@ Case cases[] = {
Case("SPI - mode testing (MODE_1)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode1, 8, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_1_MHZ> >),
Case("SPI - mode testing (MODE_2)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode2, 8, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_1_MHZ> >),
Case("SPI - mode testing (MODE_3)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode3, 8, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_1_MHZ> >),

Case("SPI - symbol size testing (16)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode0, 16, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_1_MHZ> >),

Case("SPI - frequency testing (500 kHz)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode0, 8, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_500_KHZ> >),
Case("SPI - frequency testing (2 MHz)", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode0, 8, TRANSFER_SPI_MASTER_WRITE_SYNC, FREQ_2_MHZ> >),

Case("SPI - block write", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode0, 8, TRANSFER_SPI_MASTER_BLOCK_WRITE_SYNC, FREQ_1_MHZ> >),

#if DEVICE_SPI_ASYNCH
Case("SPI - async mode", one_peripheral<SPIPort, DefaultFormFactor, fpga_spi_test_common<SPITester::Mode0, 8, TRANSFER_SPI_MASTER_TRANSFER_ASYNC, FREQ_1_MHZ> >)
#endif
Expand Down
50 changes: 50 additions & 0 deletions hal/mbed_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "analogin_api.h"
#include "i2c_api.h"
#include "spi_api.h"
#include "gpio_api.h"
#include "mbed_toolchain.h"

Expand All @@ -40,4 +41,53 @@ MBED_WEAK void analogin_free(analogin_t *obj)
{
// Do nothing
}
#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
32 changes: 32 additions & 0 deletions hal/spi_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,28 @@ typedef struct spi_s spi_t;

#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
extern "C" {
#endif
Expand All @@ -63,6 +85,11 @@ extern "C" {
* # Defined behavior
* * ::spi_init initializes the spi_t control structure
* * ::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_format sets the number of bits per frame
* * ::spi_format configures clock polarity and phase
Expand Down Expand Up @@ -125,6 +152,11 @@ extern "C" {
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName mclk);
#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
*
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
Expand Down
3 changes: 1 addition & 2 deletions targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/pwmout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void pwmout_pulsewidth(pwmout_t *obj, float pulse)
DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse);

/* Cap pulsewidth to period before setting it. */
if ((pulse * 1000000) > (float) (obj->pulse & ~SEQ_POLARITY_BIT)) {
if ((pulse * 1000000) > (float) obj->period) {
obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= obj->period;
pwmout_pulsewidth_us(obj, obj->pulse);
Expand Down Expand Up @@ -354,4 +354,3 @@ const PinMap *pwmout_pinmap()
}

#endif // DEVICE_PWMOUT

Loading