mirror of https://github.com/ARMmbed/mbed-os.git
SPI fpga test: use get_capabilities() function to skip test cases for unsupported features
parent
4b1b4f72af
commit
b24afed5ae
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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> >),
|
||||
#if !defined(TARGET_NRF52840_DK)
|
||||
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> >),
|
||||
#endif
|
||||
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
|
||||
|
|
|
@ -105,7 +105,7 @@ static void spi_configure_driver_instance(spi_t *obj)
|
|||
|
||||
/* Clean up and uninitialize peripheral if already initialized. */
|
||||
if (nordic_nrf5_spi_initialized[instance]) {
|
||||
nrfx_spi_uninit(&nordic_nrf5_spi_instance[instance]);
|
||||
nrfx_spi_uninit(&nordic_nrf5_spi_instance[instance]);
|
||||
}
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
|
@ -128,6 +128,51 @@ static void spi_configure_driver_instance(spi_t *obj)
|
|||
}
|
||||
}
|
||||
|
||||
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 = 0x00000080; // 8 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 = 0x00000080; // 8 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++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize the SPI peripheral
|
||||
*
|
||||
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
|
||||
|
@ -191,7 +236,7 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
|||
/* Register interrupt handlers in driver with the NVIC. */
|
||||
NVIC_SetVector(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, (uint32_t) SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler);
|
||||
NVIC_SetVector(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, (uint32_t) SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler);
|
||||
NVIC_SetVector(SPIM2_SPIS2_SPI2_IRQn, (uint32_t) SPIM2_SPIS2_SPI2_IRQHandler);
|
||||
NVIC_SetVector(SPIM2_SPIS2_SPI2_IRQn, (uint32_t) SPIM2_SPIS2_SPI2_IRQHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,13 +292,13 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|||
nrf_spi_mode_t new_mode = NRF_SPI_MODE_0;
|
||||
|
||||
/* Convert Mbed HAL mode to Nordic mode. */
|
||||
if(mode == 0) {
|
||||
if (mode == 0) {
|
||||
new_mode = NRF_SPI_MODE_0;
|
||||
} else if(mode == 1) {
|
||||
} else if (mode == 1) {
|
||||
new_mode = NRF_SPI_MODE_1;
|
||||
} else if(mode == 2) {
|
||||
} else if (mode == 2) {
|
||||
new_mode = NRF_SPI_MODE_2;
|
||||
} else if(mode == 3) {
|
||||
} else if (mode == 3) {
|
||||
new_mode = NRF_SPI_MODE_3;
|
||||
}
|
||||
|
||||
|
@ -351,8 +396,9 @@ int spi_master_write(spi_t *obj, int value)
|
|||
desc.rx_length = 1;
|
||||
ret = nrfx_spi_xfer(&nordic_nrf5_spi_instance[instance], &desc, 0);
|
||||
|
||||
if (ret != NRFX_SUCCESS)
|
||||
if (ret != NRFX_SUCCESS) {
|
||||
DEBUG_PRINTF("%d error returned from nrf_spi_xfer\n\r");
|
||||
}
|
||||
|
||||
/* Manually set chip select pin if defined. */
|
||||
if (spi_inst->cs != NC) {
|
||||
|
@ -421,17 +467,17 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha
|
|||
int tx_actual_length = (tx_length > 255) ? 255 : tx_length;
|
||||
|
||||
/* Set tx buffer pointer. Set to NULL if no data is going to be transmitted. */
|
||||
const uint8_t * tx_actual_buffer = (tx_actual_length > 0) ?
|
||||
(const uint8_t *)(tx_buffer + tx_offset) :
|
||||
NULL;
|
||||
const uint8_t *tx_actual_buffer = (tx_actual_length > 0) ?
|
||||
(const uint8_t *)(tx_buffer + tx_offset) :
|
||||
NULL;
|
||||
|
||||
/* Check if rx_length is larger than 255 and if so, limit to 255. */
|
||||
int rx_actual_length = (rx_length > 255) ? 255 : rx_length;
|
||||
|
||||
/* Set rx buffer pointer. Set to NULL if no data is going to be received. */
|
||||
uint8_t * rx_actual_buffer = (rx_actual_length > 0) ?
|
||||
(uint8_t *)(rx_buffer + rx_offset) :
|
||||
NULL;
|
||||
uint8_t *rx_actual_buffer = (rx_actual_length > 0) ?
|
||||
(uint8_t *)(rx_buffer + rx_offset) :
|
||||
NULL;
|
||||
|
||||
/* Blocking transfer. */
|
||||
desc.p_tx_buffer = tx_actual_buffer;
|
||||
|
@ -439,7 +485,7 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha
|
|||
desc.tx_length = tx_actual_length;
|
||||
desc.rx_length = rx_actual_length;
|
||||
result = nrfx_spi_xfer(&nordic_nrf5_spi_instance[instance],
|
||||
&desc, 0);
|
||||
&desc, 0);
|
||||
|
||||
/* Update loop variables. */
|
||||
tx_length -= tx_actual_length;
|
||||
|
@ -596,7 +642,7 @@ static ret_code_t spi_master_transfer_async_continue(spi_t *obj)
|
|||
desc.rx_length = rx_length;
|
||||
|
||||
ret_code_t result = nrfx_spi_xfer(&nordic_nrf5_spi_instance[obj->spi.instance],
|
||||
&desc, 0);
|
||||
&desc, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -662,7 +708,7 @@ static void nordic_nrf5_spi_event_handler(nrfx_spi_evt_t const *p_event, void *p
|
|||
callback();
|
||||
}
|
||||
|
||||
/* Transfer failed, signal error if mask is set. */
|
||||
/* Transfer failed, signal error if mask is set. */
|
||||
} else if (signal_error) {
|
||||
|
||||
/* Signal error if event mask matches and event handler is set. */
|
||||
|
@ -721,7 +767,7 @@ void spi_master_transfer(spi_t *obj,
|
|||
struct buffer_s *buffer_pointer;
|
||||
|
||||
buffer_pointer = &obj->tx_buff;
|
||||
buffer_pointer->buffer = (void*) tx;
|
||||
buffer_pointer->buffer = (void *) tx;
|
||||
buffer_pointer->length = tx_length;
|
||||
buffer_pointer->pos = 0;
|
||||
buffer_pointer->width = 8;
|
||||
|
|
Loading…
Reference in New Issue