17 #if !defined(MBED_CONF_APP_SPI_MASTER_MISO) || \ 18 !defined(MBED_CONF_APP_SPI_MASTER_MOSI) || \ 19 !defined(MBED_CONF_APP_SPI_MASTER_CLK) || \ 20 !defined(MBED_CONF_APP_SPI_MASTER_SS) || \ 21 !defined(MBED_CONF_APP_SPI_MASTER_HALF_DUPLEX_DATA) || \ 22 !defined(MBED_CONF_APP_SPI_MASTER_SS_ACTIVE_HIGH) || \ 23 !defined(MBED_CONF_APP_SPI_MASTER_DELAY) || \ 24 !defined(MBED_CONF_APP_SPI_SLAVE_MISO) || \ 25 !defined(MBED_CONF_APP_SPI_SLAVE_MOSI) || \ 26 !defined(MBED_CONF_APP_SPI_SLAVE_CLK) || \ 27 !defined(MBED_CONF_APP_SPI_SLAVE_SS) || \ 28 !defined(MBED_CONF_APP_SPI_SLAVE_HALF_DUPLEX_DATA) || \ 29 !defined(MBED_CONF_APP_SPI_SLAVE_DELAY) 30 #error [NOT_SUPPORTED] Configuration not found! 33 #define DEFAULT_TEST_SYM_CNT 5 34 #define SHORTER_TEST_SYM_CNT 3 35 #define SHORTEST_TEST_SYM_CNT 1 36 #define LONG_TEST_SYM_CNT 64 38 #define FREQ_200KHZ (200000) 39 #define FREQ_1MHZ (1000000) 40 #define FREQ_2MHZ (2000000) 43 #define US_PER_MS (1000) 44 #define US_PER_S (1000000) 46 #define MASTER_SYNC_BIT_MASK 1 47 #define SLAVE_SYNC_BIT_MASK 2 49 #define MASTER_SPI_MISO MBED_CONF_APP_SPI_MASTER_MISO 50 #define MASTER_SPI_MOSI MBED_CONF_APP_SPI_MASTER_MOSI 51 #define MASTER_SPI_CLK MBED_CONF_APP_SPI_MASTER_CLK 52 #define MASTER_SPI_SS MBED_CONF_APP_SPI_MASTER_SS 53 #define MASTER_SPI_HF_DATA MBED_CONF_APP_SPI_MASTER_HALF_DUPLEX_DATA 54 #define MASTER_SPI_SS_ACTIVE_HIGH MBED_CONF_APP_SPI_MASTER_SS_ACTIVE_HIGH 55 #define MASTER_TRANSMISSION_DELAY_MS MBED_CONF_APP_SPI_MASTER_DELAY 57 #define SLAVE_SPI_MISO MBED_CONF_APP_SPI_SLAVE_MISO 58 #define SLAVE_SPI_MOSI MBED_CONF_APP_SPI_SLAVE_MOSI 59 #define SLAVE_SPI_CLK MBED_CONF_APP_SPI_SLAVE_CLK 60 #define SLAVE_SPI_SS MBED_CONF_APP_SPI_SLAVE_SS 61 #define SLAVE_SPI_HF_DATA MBED_CONF_APP_SPI_SLAVE_HALF_DUPLEX_DATA 62 #define SLAVE_TRANSMISSION_DELAY_MS MBED_CONF_APP_SPI_SLAVE_DELAY 63 #define SLAVE_TRANSMISSION_DELAY_MASTER_MS MBED_CONF_APP_SPI_MASTER_DELAY 65 #define TEST_CAPABILITY_BIT(MASK, CAP) ((1 << CAP) & (MASK)) 67 #define DEBUG MBED_CONF_APP_SPI_DEBUG 69 #if(MASTER_SPI_SS_ACTIVE_HIGH) 92 SPI_BUFFERS_MASTER_TX_GT_RX,
93 SPI_BUFFERS_MASTER_TX_LT_RX,
94 SPI_BUFFERS_SLAVE_TX_GT_RX,
95 SPI_BUFFERS_SLAVE_TX_LT_RX,
106 uint32_t master_tx_cnt;
107 uint32_t master_rx_cnt;
108 uint32_t slave_tx_cnt;
109 uint32_t slave_rx_cnt;
110 bool master_tx_defined;
111 bool master_rx_defined;
112 bool slave_tx_defined;
113 bool slave_rx_defined;
130 void init_transmission_buffers_master(
config_test_case_t *config, T *p_tx_pattern, T *p_rx1_pattern, T *p_rx2_pattern,
131 T *p_tx_buff, T *p_rx_buff, T *p_fill_symbol);
134 void init_transmission_buffers_slave(
config_test_case_t *config, T *p_tx_pattern, T *p_rx1_pattern, T *p_rx2_pattern,
135 T *p_tx_buff, T *p_rx_buff, T *p_fill_symbol);
138 static uint32_t sym_count = 0;
141 static volatile bool transfer_finished;
144 static Semaphore transm_sem(0, 1);
147 static void transm_timeout_handler()
149 transm_sem.release();
153 static void msg_insert_symbol(uint8_t *buffer, uint8_t *symbol_str)
155 sprintf((
char *) buffer,
" %s", (
char *) symbol_str);
160 static void mgs_init(uint8_t *buffer, T *symbols,
const char *dut,
const char *buf_name)
162 uint8_t *p_buffer = buffer;
165 sprintf((
char *) buffer,
"%s %s", dut, buf_name);
166 p_buffer += strlen((
const char *) buffer);
168 for (uint32_t i = 0; i < sym_count; i++) {
169 sprintf((
char *) symbol,
"0x%X", symbols[i]);
171 msg_insert_symbol(p_buffer, symbol);
172 p_buffer += (strlen((
const char *) symbol) + 1);
175 sprintf((
char *) p_buffer,
"%s",
"\r\n");
180 static void dump_buffers(target_t target, T *tx_pattern, T *rx1_pattern, T *rx2_pattern, T *tx_buff, T *rx_buff)
183 uint8_t buffer[1024];
186 if (target == MASTER) {
189 strcpy((
char *)dut,
"master");
191 strcpy((
char *)dut,
"slave");
194 printf(
"%s - buffers dump: \r\n", dut);
195 mgs_init<T>(buffer, rx1_pattern, (
const char *)dut,
"rx1 pattern:");
196 printf((
const char *)buffer);
197 mgs_init<T>(buffer, rx2_pattern, (
const char *)dut,
"rx2 pattern:");
198 printf((
const char *)buffer);
199 mgs_init<T>(buffer, tx_buff, (
const char *)dut,
"tx buffer: ");
200 printf((
const char *)buffer);
201 mgs_init<T>(buffer, rx_buff, (
const char *)dut,
"rx buffer: ");
202 printf((
const char *)buffer);
210 printf(
"TEST CONFIGURATION\r\n");
211 printf(
"symbol_size: %lu\r\n", (uint32_t) config->symbol_size);
212 printf(
"spi_mode: %lu\r\n", (uint32_t) config->mode);
213 printf(
"bit_ordering: %lu\r\n", (uint32_t) config->bit_ordering);
214 printf(
"freq: %lu\r\n", (uint32_t) config->freq_hz);
215 printf(
"master tx cnt: %lu\r\n", (uint32_t) config->master_tx_cnt);
216 printf(
"master rx cnt: %lu\r\n", (uint32_t) config->master_rx_cnt);
217 printf(
"slave tx cnt: %lu\r\n", (uint32_t) config->slave_tx_cnt);
218 printf(
"slave rx cnt: %lu\r\n", (uint32_t) config->slave_rx_cnt);
219 printf(
"master tx defined: %lu\r\n", (uint32_t) config->master_tx_defined);
220 printf(
"master rx defined: %lu\r\n", (uint32_t) config->master_rx_defined);
221 printf(
"slave tx defined: %lu\r\n", (uint32_t) config->slave_tx_defined);
222 printf(
"slave rx defined: %lu\r\n", (uint32_t) config->slave_rx_defined);
223 printf(
"auto ss: %lu\r\n", (uint32_t) config->auto_ss);
224 printf(
"duplex: %lu\r\n", (uint32_t) config->duplex);
225 printf(
"master sync mode: %lu\r\n", (uint32_t) config->master_sync);
226 printf(
"slave sync mode: %lu\r\n", (uint32_t) config->slave_sync);
231 static void set_buffer(
void *addr, uint32_t size, uint8_t val)
233 char *p_char = (
char *) addr;
235 for (uint32_t i = 0; i < size; i++) {
248 static void init_buffer_with_pattern(
void *p_buffer, uint32_t sym_count, uint32_t sym_size, uint8_t *p_pattern,
249 uint32_t pattern_sym_count)
251 uint32_t pattern_idx = 0;
254 set_buffer(p_buffer, sym_size, p_pattern[pattern_idx]);
256 p_buffer += sym_size;
259 if (pattern_idx == pattern_sym_count) {
268 static void handle_ss(DigitalOut *ss,
bool select)
279 #ifdef DEVICE_SPI_ASYNCH 281 static uint32_t context;
282 static volatile bool async_transm_done;
283 static volatile uint32_t async_transfered;
286 async_transm_done =
true;
287 async_transfered =
event->transfered;
302 if ((!TEST_CAPABILITY_BIT(capabilities.
word_length, (tc_config->symbol_size - 1))) ||
303 (!TEST_CAPABILITY_BIT(capabilities.
clk_modes, tc_config->mode)) ||
304 (!TEST_CAPABILITY_BIT(capabilities.
bit_order, tc_config->bit_ordering)) ||
306 (tc_config->freq_hz != FREQ_MAX && tc_config->freq_hz != FREQ_MIN && tc_config->freq_hz < capabilities.
minimum_frequency && tc_config->freq_hz > capabilities.
maximum_frequency) ||
307 (!slave && !tc_config->master_sync && !capabilities.
async_mode) ||
308 (slave && !tc_config->slave_sync && !capabilities.
async_mode) ||
309 (tc_config->duplex == HALF_DUPLEX && !capabilities.
half_duplex) ||
310 (!slave && tc_config->auto_ss && !capabilities.
hw_cs_handle)
313 printf(
"SKIP: Configuration not supported by master.\r\n");
315 printf(
"SKIP: Configuration not supported by slave.\r\n");
323 static uint32_t sync_async_transfer(spi_t *obj,
const void *tx, uint32_t tx_len,
void *rx, uint32_t rx_len,
324 const void *fill_symbol,
bool sync_mode)
329 count =
spi_transfer(obj, tx, tx_len, rx, rx_len, fill_symbol);
331 #ifdef DEVICE_SPI_ASYNCH 333 async_transm_done =
false;
334 async_transfered = 0;
336 spi_transfer_async(obj, tx, tx_len, rx, rx_len, fill_symbol, spi_async_callback, &context, DMA_USAGE_NEVER);
339 while (!async_transm_done) {
342 count = async_transfered;
356 static void wait_before_transmission(target_t target)
358 if (target == MASTER) {
359 wait_ms(MASTER_TRANSMISSION_DELAY_MS);
361 wait_ms(SLAVE_TRANSMISSION_DELAY_MS);
368 static bool check_buffers(
void *p_pattern,
void *p_buffer, uint32_t size)
370 const char *p_byte_pattern = (
const char *) p_pattern;
371 const char *p_byte_buffer = (
const char *) p_buffer;
373 if (p_buffer == NULL || p_pattern == NULL) {
378 if (*p_byte_pattern != *p_byte_buffer) {
398 static int perform_transfer(target_t target, spi_t *obj,
config_test_case_t *config, DigitalOut *ss)
405 T *tx_pattern =
new T[sym_count];
406 T *rx1_pattern =
new T[sym_count];
407 T *rx2_pattern =
new T[sym_count];
408 T *tx_buff =
new T[sym_count];
409 T *rx_buff =
new T[sym_count];
412 void *p_tx_buff = tx_buff;
413 void *p_rx_buff = rx_buff;
415 uint32_t clocked_symbols_1 = sym_count;
416 uint32_t clocked_symbols_2 = sym_count;
418 if (config->duplex != FULL_DUPLEX) {
419 if (target == MASTER) {
420 clocked_symbols_1 = (config->master_tx_cnt + config->master_rx_cnt);
422 clocked_symbols_1 = (config->slave_tx_cnt + config->slave_rx_cnt);
425 clocked_symbols_2 = (sym_count + sym_count);
428 if (target == MASTER) {
429 if (!config->master_tx_defined) {
433 if (!config->master_rx_defined) {
436 sync = config->master_sync;
438 if (!config->slave_tx_defined) {
442 if (!config->slave_rx_defined) {
445 sync = config->slave_sync;
448 if (target == MASTER) {
449 init_transmission_buffers_master<T>(config, &tx_pattern[0], &rx1_pattern[0], &rx2_pattern[0], &tx_buff[0], &rx_buff[0],
452 init_transmission_buffers_slave<T>(config, &tx_pattern[0], &rx1_pattern[0], &rx2_pattern[0], &tx_buff[0], &rx_buff[0],
457 wait_before_transmission(target);
459 if (target == MASTER) {
461 count = sync_async_transfer(obj, p_tx_buff, config->master_tx_cnt, p_rx_buff, config->master_rx_cnt, (
void *) &fill_symbol, sync);
462 handle_ss(ss,
false);
464 count = sync_async_transfer(obj, p_tx_buff, config->slave_tx_cnt, p_rx_buff, config->slave_rx_cnt,
465 (
void *) &fill_symbol, sync);
468 if (!check_buffers(rx1_pattern, p_rx_buff,
sizeof(T) * sym_count)) {
469 if (target == MASTER) {
470 printf(
"ERROR (T1): Master RX buffer invalid. \r\n ");
472 printf(
"ERROR (T1): Slave RX buffer invalid. \r\n ");
477 if (!check_buffers(tx_pattern, p_tx_buff,
sizeof(T) * sym_count)) {
478 if (target == MASTER) {
479 printf(
"ERROR (T1): Master TX buffer invalid. \r\n ");
481 printf(
"ERROR (T1): Slave TX buffer invalid. \r\n ");
486 if (clocked_symbols_1 != count) {
487 if (target == MASTER) {
488 printf(
"ERROR (T1): Master Clocked symbol count invalid (expected: %lu actual: %lu). \r\n ", clocked_symbols_1, count);
490 printf(
"ERROR (T1): Slave Clocked symbol count invalid (expected: %lu actual: %lu). \r\n ", clocked_symbols_1,
497 dump_buffers<T>(target, tx_pattern, rx1_pattern, rx2_pattern, tx_buff, rx_buff);
502 if (p_tx_buff && p_rx_buff) {
503 memcpy(p_tx_buff, p_rx_buff,
sizeof(T) * sym_count);
504 memcpy(tx_pattern, p_rx_buff,
sizeof(T) * sym_count);
507 set_buffer(rx_buff,
sizeof(T) * sym_count, 0x00);
510 wait_before_transmission(target);
512 if (target == MASTER) {
516 count = sync_async_transfer(obj, p_tx_buff, sym_count, p_rx_buff, sym_count, (
void *) &fill_symbol, sync);
518 if (target == MASTER) {
519 handle_ss(ss,
false);
522 if (!check_buffers(rx2_pattern, p_rx_buff,
sizeof(T) * sym_count)) {
523 if (target == MASTER) {
524 printf(
"ERROR (T2): Master RX buffer invalid. \r\n ");
526 printf(
"ERROR (T2): Slave RX buffer invalid. \r\n ");
532 if (!check_buffers(tx_pattern, p_tx_buff,
sizeof(T) * sym_count)) {
533 if (target == MASTER) {
534 printf(
"ERROR (T2): Master TX buffer invalid. \r\n ");
536 printf(
"ERROR (T2): Slave TX buffer invalid. \r\n ");
541 if (clocked_symbols_2 != count) {
542 if (target == MASTER) {
543 printf(
"ERROR (T2): Master Clocked symbol count invalid (expected: %lu actual: %lu). \r\n ", clocked_symbols_2, count);
545 printf(
"ERROR (T2): Slave Clocked symbol count invalid (expected: %lu actual: %lu). \r\n ", clocked_symbols_2,
552 dump_buffers<T>(target, tx_pattern, rx1_pattern, rx2_pattern, tx_buff, rx_buff);
568 void transfer_thread(
void *thread_params)
573 if (params->config->symbol_size <= 8) {
574 status = perform_transfer<uint8_t>(params->target, params->obj, params->config, params->ss);
575 }
else if (params->config->symbol_size <= 16) {
576 status = perform_transfer<uint16_t>(params->target, params->obj, params->config, params->ss);
578 status = perform_transfer<uint32_t>(params->target, params->obj, params->config, params->ss);
581 transfer_finished =
true;
583 params->status = status;
585 transm_sem.release();
bool hw_cs_handle
If true, in SPI master mode Chip Select can be handled by hardware.
bool support_slave_mode
If true, the device can handle SPI slave mode using hardware management on the specified ssel pin...
uint32_t minimum_frequency
Minimum frequency supported must be set by target device and it will be assessed during testing...
Event data reported to interrupt's callback.
uint32_t maximum_frequency
Maximum frequency supported must be set by target device and it will be assessed during testing...
uint8_t clk_modes
specifies supported modes from spi_mode_t.
uint8_t bit_order
specifies supported bit order from spi_bit_ordering_t.
SPIName spi_get_module(PinName mosi, PinName miso, PinName mclk)
Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device...
void spi_get_capabilities(SPIName name, PinName ssel, bool slave, spi_capabilities_t *cap)
Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
Describes the capabilities of a SPI peripherals.
bool async_mode
If true, in async mode is supported.
enum _spi_mode_t spi_mode_t
SPI modes.
enum _spi_bit_ordering_t spi_bit_ordering_t
SPI bit ordering.
bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol, spi_async_handler_f handler, void *ctx, DMAUsage hint)
Transfer data returning immediately.
#define CMDLINE_RETCODE_SUCCESS
Execution Success.
uint32_t spi_transfer(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol)
Transfer data blocking until the end of the operation.
bool half_duplex
If true, the device also supports SPI transmissions using only 3 wires.
uint32_t word_length
Each bit represents the corresponding word length.