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  }
118  // skipp pin searching if single pin port type
119  if (PortType::pin_count > 1) {
120  find_port_pins<PortType, FormFactorType>(port);
121  }
122  if (port.empty()) {
123  not_matched_ports.push_back(port);
124  } else {
125  matched_ports.push_back(port);
126  }
127  }
128  }
129 }
130 
131 
132 template<typename PortType, typename FormFactorType, typename FunctionType, FunctionType f>
133 void test_all_ports(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
134 {
135  typedef typename std::list<PortType>::iterator Iter;
136  utest_printf("***Testing %s on all form factor ports***\n", PortType::PinMap::name);
137  const PinList *ff_pins = FormFactorType::pins();
139 
140  if (matched_ports.empty() && not_matched_ports.empty()) {
141  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
142  return;
143  }
144 
145  for (uint32_t i = 0; i < ff_pins->count; i++) {
146  for (Iter it = matched_ports.begin(); it != matched_ports.end(); ++it) {
147  PortType &port = *it;
148  for (uint32_t j = 0; j < PortType::pin_count; j++) {
149  if (ff_pins->pins[i] == port.pins[j]) {
150  utest_printf("%3s - %s pin tested on port: %s...", FormFactorType::pin_to_string(ff_pins->pins[i]),
151  PortType::PinMap::pin_type_names[j], port.str());
152  if (port.status == PortType::StatusNotTested) {
153  call(port);
154  port.status = PortType::StatusPass;
155  }
156  utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
157  goto end_port_iteration;
158  }
159  }
160  }
161  for (Iter it = not_matched_ports.begin(); it != not_matched_ports.end(); ++it) {
162  PortType &port = *it;
163  for (uint32_t j = 0; j < PortType::pin_count; j++) {
164  if (ff_pins->pins[i] == port.pins[j]) {
165  utest_printf("%3s - Could not find pins to test %s pin %s (%d)\n",
166  FormFactorType::pin_to_string(ff_pins->pins[i]),
167  PortType::PinMap::pin_type_names[j],
168  FormFactorType::pin_to_string(ff_pins->pins[i]),
169  ff_pins->pins[i]);
170  goto end_port_iteration;
171  }
172  }
173  }
174 end_port_iteration:
175  ;
176  }
177 }
178 
179 template<typename PortType, typename FunctionType, FunctionType f>
180 void test_peripheral(PortType &port)
181 {
182  if (port.empty()) {
183  utest_printf("%d - Could not find pins to test peripheral\n", port.peripheral);
184  } else {
185  utest_printf("%d - peripheral tested on port: %s...", port.peripheral, port.str());
186  if (port.status == PortType::StatusNotTested) {
188  call(port); // run test
189  port.status = PortType::StatusPass;
190  }
191  utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
192  }
193 }
194 
195 template<typename PortType, typename FunctionType, FunctionType f>
196 void test_all_peripherals(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
197 {
198  typedef typename std::list<PortType>::iterator Iter;
199  utest_printf("***Testing all %s peripherals***\n", PortType::PinMap::name);
200 
201  if (matched_ports.empty() && not_matched_ports.empty()) {
202  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
203  return;
204  }
205 
206  matched_ports.sort(peripheral_less<PortType>);
207  not_matched_ports.sort(peripheral_less<PortType>);
208 
209  for (Iter m_it = matched_ports.begin(), nm_it = not_matched_ports.begin();
210  m_it != matched_ports.end() || nm_it != not_matched_ports.end();) {
211  if (m_it != matched_ports.end() && nm_it != not_matched_ports.end()) {
212  if ((*m_it).peripheral < (*nm_it).peripheral) {
213  test_peripheral<PortType, FunctionType, f>(*m_it);
214  ++m_it;
215  } else {
216  test_peripheral<PortType, FunctionType, f>(*nm_it);
217  ++nm_it;
218  }
219  } else if (m_it != matched_ports.end()) {
220  test_peripheral<PortType, FunctionType, f>(*m_it);
221  ++m_it;
222  } else if (nm_it != not_matched_ports.end()) {
223  test_peripheral<PortType, FunctionType, f>(*nm_it);
224  ++nm_it;
225  }
226  }
227 }
228 
229 /**
230  * Test function for all pinouts of all peripherals of a given type
231  *
232  * This template function takes in three template parameters:
233  * - PortType - The type of peripheral to test
234  * - FormFactorType - The form factor to test on
235  * - f - The test function to run.
236  *
237  * This function calls the test function multiple times with
238  * the appropriate combinations of pins.
239  */
240 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
241 void all_ports()
242 {
243  std::list<PortType> matched_ports, not_matched_ports;
244  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
245  matched_ports.unique();
246  not_matched_ports.unique();
247  test_all_ports<PortType, FormFactorType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
248 }
249 
250 /**
251  * Test function for one pinout of all peripherals of a given type
252  *
253  * This template function takes in three template parameters:
254  * - PortType - The type of peripheral to test
255  * - FormFactorType - The form factor to test on
256  * - f - The test function to run.
257  *
258  * This function calls the test function once for each peripheral
259  * of the given type.
260  */
261 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
262 void all_peripherals()
263 {
264  std::list<PortType> matched_ports, not_matched_ports;
265  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
266 
267  matched_ports.sort(peripheral_less<PortType>);
268  not_matched_ports.sort(peripheral_less<PortType>);
269  matched_ports.unique(peripheral_comparator<PortType>);
270  not_matched_ports.unique(peripheral_comparator<PortType>);
271 
272  test_all_peripherals<PortType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
273 }
274 
275 /**
276  * Test function for one pinout of one peripheral of a given type
277  *
278  * This template function takes in three template parameters:
279  * - PortType - The type of peripheral to test
280  * - FormFactorType - The form factor to test on
281  * - f - The test function to run.
282  *
283  * This function calls the test function once for one peripheral
284  * of the given type.
285  */
286 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
287 void one_peripheral()
288 {
289  std::list<PortType> matched_ports, not_matched_ports;
290  find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
291 
292  utest_printf("***Testing one %s pin configuration***\n", PortType::PinMap::name);
293  if (matched_ports.empty()) {
294  utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
295  } else {
296  test_peripheral<PortType, typename PortType::TestFunctionType, f>(matched_ports.front());
297  }
298 }
299 
300 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
301 class Port;
302 
303 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
306 
307 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
308 class Port {
309 public:
310  int peripheral;
311  PinName pins[N];
312  PinName *ppins[N];
313 
314  static const uint32_t pin_count = N;
315  typedef PinMapType PinMap;
316  typedef FunctionType TestFunctionType;
317 
318  enum Status { StatusPass, StatusFail, StatusNotTested };
319  Status status;
320 
321  Port(): peripheral(NC), status(StatusNotTested)
322  {
323  init_pins();
324  }
325 
326  Port(const Port &port)
327  {
328  init_pins();
329  copy_from(port);
330  }
331 
332  void init_pins()
333  {
334  for (uint32_t i = 0; i < N; i++) {
335  pins[i] = NC;
336  ppins[i] = &pins[i];
337  }
338  }
339 
340  void copy_from(const Port &port)
341  {
342  peripheral = port.peripheral;
343  status = port.status;
344  for (uint32_t i = 0; i < N; i++) {
345  pins[i] = port.pins[i];
346  }
347  }
348 
349  bool empty()
350  {
351  if (peripheral == NC) {
352  return true;
353  }
354  for (uint32_t i = 0; i < N; i++) {
355  if (pins[i] == NC) {
356  return true;
357  }
358  }
359  return false;
360  }
361 
362  const char *str()
363  {
364  static char port_str[128];
365  char pin_str[32];
366  sprintf(port_str, "peripheral=(%d) ", peripheral);
367  for (uint32_t i = 0; i < N; i++) {
368  sprintf(pin_str, "%s=(%s) ", PinMap::pin_type_names[i], FormFactorType::pin_to_string(pins[i]));
369  strcat(port_str, pin_str);
370  }
371  return port_str;
372  }
373 
375 };
376 
377 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
379 
380 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
382 {
383  if (port1.peripheral != port2.peripheral) {
384  return false;
385  }
386  for (uint32_t i = 0; i < N; i++) {
387  if (port1.pins[i] != port2.pins[i]) {
388  return false;
389  }
390  }
391  return true;
392 }
393 
394 /**
395  * This is a convenience class for use with the above templates
396  *
397  * This class can be passed as a template parameter to all_ports,
398  * all_peripherals or one_peripheral to choose test pins from
399  * the default form factor.
400  */
402 public:
403  static const PinList *pins()
404  {
405  return pinmap_ff_default_pins();
406  }
407 
408  static const PinList *restricted_pins()
409  {
410  return pinmap_restricted_pins();
411  }
412 
413  static const char *pin_to_string(PinName pin)
414  {
415  return pinmap_ff_default_pin_to_string(pin);
416  }
417 };
418 
419 /*
420  * Peripheral port declarations are given below
421  *
422  * Each Port type represents a set of pins used by a peripheral.
423  * The Port typedef is used as a template parameter to the functions
424  * all_ports, all_peripherals and one_peripheral to select the peripheral
425  * pin set to use for testing.
426  */
427 
428 #if DEVICE_SPI
429 #include "spi_api.h"
430 struct SPIMaps {
431  static const PinMap *maps[];
432  static const char *const pin_type_names[];
433  static const char *const name;
434 };
435 const PinMap *SPIMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap(), spi_master_cs_pinmap() };
436 const char *const SPIMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
437 const char *const SPIMaps::name = "SPI";
439 
440 struct SPINoCSMaps {
441  static const PinMap *maps[];
442  static const char *const pin_type_names[];
443  static const char *const name;
444 };
445 const PinMap *SPINoCSMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap()};
446 const char *const SPINoCSMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK" };
447 const char *const SPINoCSMaps::name = "SPI";
449 
450 struct SPISlaveMaps {
451  static const PinMap *maps[];
452  static const char *const pin_type_names[];
453  static const char *const name;
454 };
455 const PinMap *SPISlaveMaps::maps[] = { spi_slave_mosi_pinmap(), spi_slave_miso_pinmap(), spi_slave_clk_pinmap(), spi_slave_cs_pinmap() };
456 const char *const SPISlaveMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
457 const char *const SPISlaveMaps::name = "SPISlave";
459 #endif
460 
461 #if DEVICE_I2C
462 #include "i2c_api.h"
463 struct I2CMaps {
464  static const PinMap *maps[];
465  static const char *const pin_type_names[];
466  static const char *const name;
467 };
468 const PinMap *I2CMaps::maps[] = { i2c_master_sda_pinmap(), i2c_master_scl_pinmap() };
469 const char *const I2CMaps::pin_type_names[] = { "SDA", "SCL" };
470 const char *const I2CMaps::name = "I2C";
472 #endif
473 
474 #if DEVICE_PWMOUT
475 #include "pwmout_api.h"
476 struct PWMMaps {
477  static const PinMap *maps[];
478  static const char *const pin_type_names[];
479  static const char *const name;
480 };
481 const PinMap *PWMMaps::maps[] = { pwmout_pinmap() };
482 const char *const PWMMaps::pin_type_names[] = { "PWM_OUT" };
483 const char *const PWMMaps::name = "PWM";
485 #endif
486 
487 #if DEVICE_ANALOGIN
488 #include "analogin_api.h"
489 struct AnaloginMaps {
490  static const PinMap *maps[];
491  static const char *const pin_type_names[];
492  static const char *const name;
493 };
494 const PinMap *AnaloginMaps::maps[] = { analogin_pinmap() };
495 const char *const AnaloginMaps::pin_type_names[] = { "ADC_IN" };
496 const char *const AnaloginMaps::name = "ADC";
498 #endif
499 
500 #if DEVICE_ANALOGOUT
501 #include "analogout_api.h"
503  static const PinMap *maps[];
504  static const char *const pin_type_names[];
505  static const char *const name;
506 };
507 const PinMap *AnalogoutMaps::maps[] = { analogout_pinmap() };
508 const char *const AnalogoutMaps::pin_type_names[] = { "DAC_OUT" };
509 const char *const AnalogoutMaps::name = "DAC";
511 #endif
512 
513 #if DEVICE_SERIAL
514 struct UARTMaps {
515  static const PinMap *maps[];
516  static const char *const pin_type_names[];
517  static const char *const name;
518 };
519 const PinMap *UARTMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap(), serial_cts_pinmap(), serial_rts_pinmap() };
520 const char *const UARTMaps::pin_type_names[] = { "TX", "RX", "CLS", "RTS" };
521 const char *const UARTMaps::name = "UART";
523 
524 struct UARTNoFCMaps {
525  static const PinMap *maps[];
526  static const char *const pin_type_names[];
527  static const char *const name;
528 };
529 const PinMap *UARTNoFCMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap() };
530 const char *const UARTNoFCMaps::pin_type_names[] = { "TX", "RX" };
531 const char *const UARTNoFCMaps::name = "UART-no-FC";
533 #endif
534 
535 #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.
This is a convenience class for use with the above templates.
Definition: test_utils.h:401
const PinMap * i2c_master_sda_pinmap(void)
Get the pins that support I2C SDA.
const PinMap * spi_slave_mosi_pinmap(void)
Get the pins that support SPI MOSI.
Definition: pinmap.h:36
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 * 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 * serial_cts_pinmap(void)
Get the pins that support Serial CTS.
const PinMap * spi_master_clk_pinmap(void)
Get the pins that support SPI CLK.
bool pinmap_list_has_pin(const PinList *list, PinName pin)
Check if the pin is in the list.
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 * spi_master_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * serial_rx_pinmap(void)
Get the pins that support Serial RX.
const PinMap * spi_master_mosi_pinmap(void)
Get the pins that support SPI MOSI.
void operator==(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
Definition: SafeBool.h:130
Definition: pinmap.h:30
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_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * analogin_pinmap(void)
Get the pins that support analogin.
const PinMap * spi_master_miso_pinmap(void)
Get the pins that support SPI MISO.
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.