Mistake on this page?
Report an issue in GitHub or email us
test_utils.h
1 /*
2  * Copyright (c) 2019, Arm Limited and affiliates.
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef TEST_UTILS_H
19 #define TEST_UTILS_H
20 
21 #include <list>
22 
23 // test function prototypes
24 typedef void (*TF1)(PinName p0);
25 typedef void (*TF2)(PinName p0, PinName p1);
26 typedef void (*TF3)(PinName p0, PinName p1, PinName p2);
27 typedef void (*TF4)(PinName p0, PinName p1, PinName p2, PinName p3);
28 typedef void (*TF5)(PinName p0, PinName p1, PinName p2, PinName p3, PinName p4);
29 
30 template<typename PortType, typename FunctionType, FunctionType f>
32 
33 };
34 
35 template<typename PortType, TF1 f>
36 struct FunctionCaller<PortType, TF1, f> {
37  void operator()(PortType &port)
38  {
39  f(port.pins[0]);
40  }
41 };
42 
43 template<typename PortType, TF2 f>
44 struct FunctionCaller<PortType, TF2, f> {
45  void operator()(PortType &port)
46  {
47  f(port.pins[0], port.pins[1]);
48  }
49 };
50 
51 template<typename PortType, TF3 f>
52 struct FunctionCaller<PortType, TF3, f> {
53  void operator()(PortType &port)
54  {
55  f(port.pins[0], port.pins[1], port.pins[2]);
56  }
57 };
58 
59 template<typename PortType, TF4 f>
60 struct FunctionCaller<PortType, TF4, f> {
61  void operator()(PortType &port)
62  {
63  f(port.pins[0], port.pins[1], port.pins[2], port.pins[3]);
64  }
65 };
66 
67 template<typename PortType, TF5 f>
68 struct FunctionCaller<PortType, TF5, f> {
69  void operator()(PortType &port)
70  {
71  f(port.pins[0], port.pins[1], port.pins[2], port.pins[3], port.pins[4]);
72  }
73 };
74 
75 template <typename PortType>
76 bool peripheral_comparator(const PortType &port1, const PortType &port2)
77 {
78  return port1.peripheral == port2.peripheral;
79 }
80 
81 template <typename PortType>
82 bool peripheral_less(const PortType &port1, const PortType &port2)
83 {
84  return port1.peripheral < port2.peripheral;
85 }
86 
87 template<typename PortType, typename FormFactorType>
88 static bool find_port_pins(PortType &port)
89 {
90  return pinmap_find_peripheral_pins(FormFactorType::pins(), FormFactorType::restricted_pins(),
91  port.peripheral, PortType::PinMap::maps, port.ppins, PortType::pin_count);
92 }
93 
94 template<typename PortType, typename FormFactorType>
95 void find_ports(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
96 {
97  // Loop through every pin type
98  for (uint32_t i = 0; i < PortType::pin_count; i++) {
99  const PinMap *map = PortType::PinMap::maps[i];
100  const char *pin_type = PortType::PinMap::pin_type_names[i];
101 
102  // Loop through each pin of a given type
103  for (; map->pin != NC; map++) {
104  PortType port;
105  // Set pin being tested
106  port.pins[i] = map->pin;
107  port.peripheral = map->peripheral;
108  // Only form factor pins can be tested
109  if (!pinmap_list_has_pin(FormFactorType::pins(), port.pins[i])) {
110  continue;
111  }
112  // Don't test restricted pins
113  if (pinmap_list_has_pin(FormFactorType::restricted_pins(), port.pins[i])) {
114  utest_printf("Skipping %s pin %s (%i)\r\n", pin_type,
115  FormFactorType::pin_to_string(port.pins[i]), port.pins[i]);
116  continue;
117  }
119  utest_printf("Skipping %s peripheral %i with pin %s (%i)\r\n", pin_type,
120  port.peripheral, FormFactorType::pin_to_string(port.pins[i]), port.pins[i]);
121  continue;
122  }
123  // skipp pin searching if single pin port type
124  if (PortType::pin_count > 1) {
125  find_port_pins<PortType, FormFactorType>(port);
126  }
127  if (port.empty()) {
128  not_matched_ports.push_back(port);
129  } else {
130  matched_ports.push_back(port);
131  }
132  }
133  }
134 }
135 
136 
137 template<typename PortType, typename FormFactorType, typename FunctionType, FunctionType f>
138 void test_all_ports(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
139 {
140  typedef typename std::list<PortType>::iterator Iter;
141  utest_printf("***Testing %s on all form factor ports***\n", PortType::PinMap::name);
142  const PinList *ff_pins = FormFactorType::pins();
144 
145  if (matched_ports.empty() && not_matched_ports.empty()) {
146  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
147  return;
148  }
149 
150  for (uint32_t i = 0; i < ff_pins->count; i++) {
151  for (Iter it = matched_ports.begin(); it != matched_ports.end(); ++it) {
152  PortType &port = *it;
153  for (uint32_t j = 0; j < PortType::pin_count; j++) {
154  if (ff_pins->pins[i] == port.pins[j]) {
155  utest_printf("%3s - %s pin tested on port: %s...", FormFactorType::pin_to_string(ff_pins->pins[i]),
156  PortType::PinMap::pin_type_names[j], port.str());
157  if (port.status == PortType::StatusNotTested) {
158  call(port);
159  port.status = PortType::StatusPass;
160  }
161  utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
162  goto end_port_iteration;
163  }
164  }
165  }
166  for (Iter it = not_matched_ports.begin(); it != not_matched_ports.end(); ++it) {
167  PortType &port = *it;
168  for (uint32_t j = 0; j < PortType::pin_count; j++) {
169  if (ff_pins->pins[i] == port.pins[j]) {
170  utest_printf("%3s - Could not find pins to test %s pin %s (%d)\n",
171  FormFactorType::pin_to_string(ff_pins->pins[i]),
172  PortType::PinMap::pin_type_names[j],
173  FormFactorType::pin_to_string(ff_pins->pins[i]),
174  ff_pins->pins[i]);
175  goto end_port_iteration;
176  }
177  }
178  }
179 end_port_iteration:
180  ;
181  }
182 }
183 
184 template<typename PortType, typename FunctionType, FunctionType f>
185 void test_peripheral(PortType &port)
186 {
187  if (port.empty()) {
188  utest_printf("%d - Could not find pins to test peripheral\n", port.peripheral);
189  } else {
190  utest_printf("%d - peripheral tested on port: %s...", port.peripheral, port.str());
191  if (port.status == PortType::StatusNotTested) {
193  call(port); // run test
194  port.status = PortType::StatusPass;
195  }
196  utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
197  }
198 }
199 
200 template<typename PortType, typename FunctionType, FunctionType f>
201 void test_all_peripherals(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
202 {
203  typedef typename std::list<PortType>::iterator Iter;
204  utest_printf("***Testing all %s peripherals***\n", PortType::PinMap::name);
205 
206  if (matched_ports.empty() && not_matched_ports.empty()) {
207  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
208  return;
209  }
210 
211  matched_ports.sort(peripheral_less<PortType>);
212  not_matched_ports.sort(peripheral_less<PortType>);
213 
214  for (Iter m_it = matched_ports.begin(), nm_it = not_matched_ports.begin();
215  m_it != matched_ports.end() || nm_it != not_matched_ports.end();) {
216  if (m_it != matched_ports.end() && nm_it != not_matched_ports.end()) {
217  if ((*m_it).peripheral < (*nm_it).peripheral) {
218  test_peripheral<PortType, FunctionType, f>(*m_it);
219  ++m_it;
220  } else {
221  test_peripheral<PortType, FunctionType, f>(*nm_it);
222  ++nm_it;
223  }
224  } else if (m_it != matched_ports.end()) {
225  test_peripheral<PortType, FunctionType, f>(*m_it);
226  ++m_it;
227  } else if (nm_it != not_matched_ports.end()) {
228  test_peripheral<PortType, FunctionType, f>(*nm_it);
229  ++nm_it;
230  }
231  }
232 }
233 
234 /**
235  * Test function for all pinouts of all peripherals of a given type
236  *
237  * This template function takes in three template parameters:
238  * - PortType - The type of peripheral to test
239  * - FormFactorType - The form factor to test on
240  * - f - The test function to run.
241  *
242  * This function calls the test function multiple times with
243  * the appropriate combinations of pins.
244  */
245 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
246 void all_ports()
247 {
248  std::list<PortType> matched_ports, not_matched_ports;
249  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
250  matched_ports.unique();
251  not_matched_ports.unique();
252  test_all_ports<PortType, FormFactorType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
253 }
254 
255 /**
256  * Test function for one pinout of all peripherals of a given type
257  *
258  * This template function takes in three template parameters:
259  * - PortType - The type of peripheral to test
260  * - FormFactorType - The form factor to test on
261  * - f - The test function to run.
262  *
263  * This function calls the test function once for each peripheral
264  * of the given type.
265  */
266 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
267 void all_peripherals()
268 {
269  std::list<PortType> matched_ports, not_matched_ports;
270  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
271 
272  matched_ports.sort(peripheral_less<PortType>);
273  not_matched_ports.sort(peripheral_less<PortType>);
274  matched_ports.unique(peripheral_comparator<PortType>);
275  not_matched_ports.unique(peripheral_comparator<PortType>);
276 
277  test_all_peripherals<PortType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
278 }
279 
280 /**
281  * Test function for one pinout of one peripheral of a given type
282  *
283  * This template function takes in three template parameters:
284  * - PortType - The type of peripheral to test
285  * - FormFactorType - The form factor to test on
286  * - f - The test function to run.
287  *
288  * This function calls the test function once for one peripheral
289  * of the given type.
290  */
291 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
292 void one_peripheral()
293 {
294  std::list<PortType> matched_ports, not_matched_ports;
295  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
296 
297  utest_printf("***Testing one %s pin configuration***\n", PortType::PinMap::name);
298  if (matched_ports.empty()) {
299  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
300  } else {
301  test_peripheral<PortType, typename PortType::TestFunctionType, f>(matched_ports.front());
302  }
303 }
304 
305 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
306 class Port;
307 
308 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
311 
312 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
313 class Port {
314 public:
315  int peripheral;
316  PinName pins[N];
317  PinName *ppins[N];
318 
319  static const uint32_t pin_count = N;
320  typedef PinMapType PinMap;
321  typedef FunctionType TestFunctionType;
322 
323  enum Status { StatusPass, StatusFail, StatusNotTested };
324  Status status;
325 
326  Port(): peripheral(NC), status(StatusNotTested)
327  {
328  init_pins();
329  }
330 
331  Port(const Port &port)
332  {
333  init_pins();
334  copy_from(port);
335  }
336 
337  void init_pins()
338  {
339  for (uint32_t i = 0; i < N; i++) {
340  pins[i] = NC;
341  ppins[i] = &pins[i];
342  }
343  }
344 
345  void copy_from(const Port &port)
346  {
347  peripheral = port.peripheral;
348  status = port.status;
349  for (uint32_t i = 0; i < N; i++) {
350  pins[i] = port.pins[i];
351  }
352  }
353 
354  bool empty()
355  {
356  if (peripheral == NC) {
357  return true;
358  }
359  for (uint32_t i = 0; i < N; i++) {
360  if (pins[i] == NC) {
361  return true;
362  }
363  }
364  return false;
365  }
366 
367  const char *str()
368  {
369  static char port_str[128];
370  char pin_str[32];
371  sprintf(port_str, "peripheral=(%d) ", peripheral);
372  for (uint32_t i = 0; i < N; i++) {
373  sprintf(pin_str, "%s=(%s) ", PinMap::pin_type_names[i], FormFactorType::pin_to_string(pins[i]));
374  strcat(port_str, pin_str);
375  }
376  return port_str;
377  }
378 
380 };
381 
382 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
384 
385 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
387 {
388  if (port1.peripheral != port2.peripheral) {
389  return false;
390  }
391  for (uint32_t i = 0; i < N; i++) {
392  if (port1.pins[i] != port2.pins[i]) {
393  return false;
394  }
395  }
396  return true;
397 }
398 
399 /**
400  * This is a convenience class for use with the above templates
401  *
402  * This class can be passed as a template parameter to all_ports,
403  * all_peripherals or one_peripheral to choose test pins from
404  * the default form factor.
405  */
407 public:
408  static const PinList *pins()
409  {
410  return pinmap_ff_default_pins();
411  }
412 
413  static const PinList *restricted_pins()
414  {
415  return pinmap_restricted_pins();
416  }
417 
418  static const char *pin_to_string(PinName pin)
419  {
420  return pinmap_ff_default_pin_to_string(pin);
421  }
422 };
423 
424 /*
425  * Peripheral port declarations are given below
426  *
427  * Each Port type represents a set of pins used by a peripheral.
428  * The Port typedef is used as a template parameter to the functions
429  * all_ports, all_peripherals and one_peripheral to select the peripheral
430  * pin set to use for testing.
431  */
432 
433 struct GPIOMaps {
434  static const PinMap *maps[];
435  static const char *const pin_type_names[];
436  static const char *const name;
437 };
438 const PinMap *GPIOMaps::maps[] = { gpio_pinmap() };
439 const char *const GPIOMaps::pin_type_names[] = { "IO" };
440 const char *const GPIOMaps::name = "GPIO";
442 
443 #if DEVICE_INTERRUPTIN
444 #include "gpio_irq_api.h"
445 struct GPIOIRQMaps {
446  static const PinMap *maps[];
447  static const char *const pin_type_names[];
448  static const char *const name;
449 };
450 const PinMap *GPIOIRQMaps::maps[] = { gpio_irq_pinmap() };
451 const char *const GPIOIRQMaps::pin_type_names[] = { "IRQ_IN" };
452 const char *const GPIOIRQMaps::name = "GPIO_IRQ";
454 #endif
455 
456 #if DEVICE_SPI
457 #include "spi_api.h"
458 struct SPIMaps {
459  static const PinMap *maps[];
460  static const char *const pin_type_names[];
461  static const char *const name;
462 };
463 const PinMap *SPIMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap(), spi_master_cs_pinmap() };
464 const char *const SPIMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
465 const char *const SPIMaps::name = "SPI";
467 
468 struct SPINoCSMaps {
469  static const PinMap *maps[];
470  static const char *const pin_type_names[];
471  static const char *const name;
472 };
473 const PinMap *SPINoCSMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap()};
474 const char *const SPINoCSMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK" };
475 const char *const SPINoCSMaps::name = "SPI";
477 
478 struct SPISlaveMaps {
479  static const PinMap *maps[];
480  static const char *const pin_type_names[];
481  static const char *const name;
482 };
483 const PinMap *SPISlaveMaps::maps[] = { spi_slave_mosi_pinmap(), spi_slave_miso_pinmap(), spi_slave_clk_pinmap(), spi_slave_cs_pinmap() };
484 const char *const SPISlaveMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
485 const char *const SPISlaveMaps::name = "SPISlave";
487 #endif
488 
489 #if DEVICE_I2C
490 #include "i2c_api.h"
491 struct I2CMaps {
492  static const PinMap *maps[];
493  static const char *const pin_type_names[];
494  static const char *const name;
495 };
496 const PinMap *I2CMaps::maps[] = { i2c_master_sda_pinmap(), i2c_master_scl_pinmap() };
497 const char *const I2CMaps::pin_type_names[] = { "SDA", "SCL" };
498 const char *const I2CMaps::name = "I2C";
500 #endif
501 
502 #if DEVICE_PWMOUT
503 #include "pwmout_api.h"
504 struct PWMMaps {
505  static const PinMap *maps[];
506  static const char *const pin_type_names[];
507  static const char *const name;
508 };
509 const PinMap *PWMMaps::maps[] = { pwmout_pinmap() };
510 const char *const PWMMaps::pin_type_names[] = { "PWM_OUT" };
511 const char *const PWMMaps::name = "PWM";
513 #endif
514 
515 #if DEVICE_ANALOGIN
516 #include "analogin_api.h"
517 struct AnaloginMaps {
518  static const PinMap *maps[];
519  static const char *const pin_type_names[];
520  static const char *const name;
521 };
522 const PinMap *AnaloginMaps::maps[] = { analogin_pinmap() };
523 const char *const AnaloginMaps::pin_type_names[] = { "ADC_IN" };
524 const char *const AnaloginMaps::name = "ADC";
526 #endif
527 
528 #if DEVICE_ANALOGOUT
529 #include "analogout_api.h"
531  static const PinMap *maps[];
532  static const char *const pin_type_names[];
533  static const char *const name;
534 };
535 const PinMap *AnalogoutMaps::maps[] = { analogout_pinmap() };
536 const char *const AnalogoutMaps::pin_type_names[] = { "DAC_OUT" };
537 const char *const AnalogoutMaps::name = "DAC";
539 #endif
540 
541 #if DEVICE_SERIAL
542 #if DEVICE_SERIAL_FC
543 struct UARTMaps {
544  static const PinMap *maps[];
545  static const char *const pin_type_names[];
546  static const char *const name;
547 };
548 const PinMap *UARTMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap(), serial_cts_pinmap(), serial_rts_pinmap() };
549 const char *const UARTMaps::pin_type_names[] = { "TX", "RX", "CLS", "RTS" };
550 const char *const UARTMaps::name = "UART";
552 #endif
553 
554 struct UARTNoFCMaps {
555  static const PinMap *maps[];
556  static const char *const pin_type_names[];
557  static const char *const name;
558 };
559 const PinMap *UARTNoFCMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap() };
560 const char *const UARTNoFCMaps::pin_type_names[] = { "TX", "RX" };
561 const char *const UARTNoFCMaps::name = "UART-no-FC";
563 #endif
564 
565 #endif
const PinMap * serial_tx_pinmap(void)
Get the pins that support Serial TX.
const PinMap * i2c_master_scl_pinmap(void)
Get the pins that support I2C SCL.
const PinMap * spi_master_mosi_pinmap(void)
Get the pins that support SPI MOSI.
This is a convenience class for use with the above templates.
Definition: test_utils.h:406
const PinMap * i2c_master_sda_pinmap(void)
Get the pins that support I2C SDA.
Definition: pinmap.h:37
bool pinmap_list_has_peripheral(const PeripheralList *list, int peripheral)
Check if the peripheral is in the list.
const PinMap * gpio_pinmap(void)
Get the pins that support all GPIO tests.
bool pinmap_find_peripheral_pins(const PinList *whitelist, const PinList *blacklist, int per, const PinMap *const *maps, PinName **pins, uint32_t count)
Find a combination of pins suitable for use given the constraints.
const PinMap * serial_cts_pinmap(void)
Get the pins that support Serial CTS.
const PinMap * spi_master_miso_pinmap(void)
Get the pins that support SPI MISO.
const PinMap * spi_master_cs_pinmap(void)
Get the pins that support SPI CS.
bool pinmap_list_has_pin(const PinList *list, PinName pin)
Check if the pin is in the list.
const PinMap * spi_master_clk_pinmap(void)
Get the pins that support SPI CLK.
const PeripheralList * pinmap_restricted_peripherals(void)
Get the pin list of peripherals to avoid during testing.
const PinMap * gpio_irq_pinmap(void)
Get the pins that support all GPIO IRQ tests.
const PinMap * pwmout_pinmap(void)
Get the pins that support PWM.
const PinMap * serial_rts_pinmap(void)
Get the pins that support Serial RTS.
const PinMap * serial_rx_pinmap(void)
Get the pins that support Serial RX.
void operator==(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
Definition: SafeBool.h:130
const PinMap * spi_slave_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * spi_slave_mosi_pinmap(void)
Get the pins that support SPI MOSI.
Definition: pinmap.h:31
const PinList * pinmap_restricted_pins(void)
Get the pin list of pins to avoid during testing.
const PinMap * analogout_pinmap(void)
Get the pins that support analogout.
const PinMap * spi_slave_clk_pinmap(void)
Get the pins that support SPI CLK.
const PinMap * spi_slave_miso_pinmap(void)
Get the pins that support SPI MISO.
const PinMap * analogin_pinmap(void)
Get the pins that support analogin.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.