Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
test_utils.h
00001 /* 00002 * Copyright (c) 2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef TEST_UTILS_H 00019 #define TEST_UTILS_H 00020 00021 #include <list> 00022 00023 // test function prototypes 00024 typedef void (*TF1)(PinName p0); 00025 typedef void (*TF2)(PinName p0, PinName p1); 00026 typedef void (*TF3)(PinName p0, PinName p1, PinName p2); 00027 typedef void (*TF4)(PinName p0, PinName p1, PinName p2, PinName p3); 00028 typedef void (*TF5)(PinName p0, PinName p1, PinName p2, PinName p3, PinName p4); 00029 00030 template<typename PortType, typename FunctionType, FunctionType f> 00031 struct FunctionCaller { 00032 00033 }; 00034 00035 template<typename PortType, TF1 f> 00036 struct FunctionCaller<PortType, TF1, f> { 00037 void operator()(PortType &port) 00038 { 00039 f(port.pins[0]); 00040 } 00041 }; 00042 00043 template<typename PortType, TF2 f> 00044 struct FunctionCaller<PortType, TF2, f> { 00045 void operator()(PortType &port) 00046 { 00047 f(port.pins[0], port.pins[1]); 00048 } 00049 }; 00050 00051 template<typename PortType, TF3 f> 00052 struct FunctionCaller<PortType, TF3, f> { 00053 void operator()(PortType &port) 00054 { 00055 f(port.pins[0], port.pins[1], port.pins[2]); 00056 } 00057 }; 00058 00059 template<typename PortType, TF4 f> 00060 struct FunctionCaller<PortType, TF4, f> { 00061 void operator()(PortType &port) 00062 { 00063 f(port.pins[0], port.pins[1], port.pins[2], port.pins[3]); 00064 } 00065 }; 00066 00067 template<typename PortType, TF5 f> 00068 struct FunctionCaller<PortType, TF5, f> { 00069 void operator()(PortType &port) 00070 { 00071 f(port.pins[0], port.pins[1], port.pins[2], port.pins[3], port.pins[4]); 00072 } 00073 }; 00074 00075 template <typename PortType> 00076 bool peripheral_comparator(const PortType &port1, const PortType &port2) 00077 { 00078 return port1.peripheral == port2.peripheral; 00079 } 00080 00081 template <typename PortType> 00082 bool peripheral_less(const PortType &port1, const PortType &port2) 00083 { 00084 return port1.peripheral < port2.peripheral; 00085 } 00086 00087 template<typename PortType, typename FormFactorType> 00088 static bool find_port_pins(PortType &port) 00089 { 00090 return pinmap_find_peripheral_pins(FormFactorType::pins(), FormFactorType::restricted_pins(), 00091 port.peripheral, PortType::PinMap::maps, port.ppins, PortType::pin_count); 00092 } 00093 00094 template<typename PortType, typename FormFactorType> 00095 void find_ports(std::list<PortType> &matched_ports, std::list<PortType> ¬_matched_ports) 00096 { 00097 // Loop through every pin type 00098 for (uint32_t i = 0; i < PortType::pin_count; i++) { 00099 const PinMap *map = PortType::PinMap::maps[i]; 00100 const char *pin_type = PortType::PinMap::pin_type_names[i]; 00101 00102 // Loop through each pin of a given type 00103 for (; map->pin != NC; map++) { 00104 PortType port; 00105 // Set pin being tested 00106 port.pins[i] = map->pin; 00107 port.peripheral = map->peripheral; 00108 // Only form factor pins can be tested 00109 if (!pinmap_list_has_pin(FormFactorType::pins(), port.pins[i])) { 00110 continue; 00111 } 00112 // Don't test restricted pins 00113 if (pinmap_list_has_pin(FormFactorType::restricted_pins(), port.pins[i])) { 00114 utest_printf("Skipping %s pin %s (%i)\r\n", pin_type, 00115 FormFactorType::pin_to_string(port.pins[i]), port.pins[i]); 00116 continue; 00117 } 00118 if (pinmap_list_has_peripheral(pinmap_restricted_peripherals(), port.peripheral)) { 00119 utest_printf("Skipping %s peripheral %i with pin %s (%i)\r\n", pin_type, 00120 port.peripheral, FormFactorType::pin_to_string(port.pins[i]), port.pins[i]); 00121 continue; 00122 } 00123 // skipp pin searching if single pin port type 00124 if (PortType::pin_count > 1) { 00125 find_port_pins<PortType, FormFactorType>(port); 00126 } 00127 if (port.empty()) { 00128 not_matched_ports.push_back(port); 00129 } else { 00130 matched_ports.push_back(port); 00131 } 00132 } 00133 } 00134 } 00135 00136 00137 template<typename PortType, typename FormFactorType, typename FunctionType, FunctionType f> 00138 void test_all_ports(std::list<PortType> &matched_ports, std::list<PortType> ¬_matched_ports) 00139 { 00140 typedef typename std::list<PortType>::iterator Iter; 00141 utest_printf("***Testing %s on all form factor ports***\n", PortType::PinMap::name); 00142 const PinList *ff_pins = FormFactorType::pins(); 00143 FunctionCaller<PortType, FunctionType, f> call; 00144 00145 if (matched_ports.empty() && not_matched_ports.empty()) { 00146 utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name); 00147 return; 00148 } 00149 00150 for (uint32_t i = 0; i < ff_pins->count; i++) { 00151 for (Iter it = matched_ports.begin(); it != matched_ports.end(); ++it) { 00152 PortType &port = *it; 00153 for (uint32_t j = 0; j < PortType::pin_count; j++) { 00154 if (ff_pins->pins[i] == port.pins[j]) { 00155 utest_printf("%3s - %s pin tested on port: %s...", FormFactorType::pin_to_string(ff_pins->pins[i]), 00156 PortType::PinMap::pin_type_names[j], port.str()); 00157 if (port.status == PortType::StatusNotTested) { 00158 call(port); 00159 port.status = PortType::StatusPass; 00160 } 00161 utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed"); 00162 goto end_port_iteration; 00163 } 00164 } 00165 } 00166 for (Iter it = not_matched_ports.begin(); it != not_matched_ports.end(); ++it) { 00167 PortType &port = *it; 00168 for (uint32_t j = 0; j < PortType::pin_count; j++) { 00169 if (ff_pins->pins[i] == port.pins[j]) { 00170 utest_printf("%3s - Could not find pins to test %s pin %s (%d)\n", 00171 FormFactorType::pin_to_string(ff_pins->pins[i]), 00172 PortType::PinMap::pin_type_names[j], 00173 FormFactorType::pin_to_string(ff_pins->pins[i]), 00174 ff_pins->pins[i]); 00175 goto end_port_iteration; 00176 } 00177 } 00178 } 00179 end_port_iteration: 00180 ; 00181 } 00182 } 00183 00184 template<typename PortType, typename FunctionType, FunctionType f> 00185 void test_peripheral(PortType &port) 00186 { 00187 if (port.empty()) { 00188 utest_printf("%d - Could not find pins to test peripheral\n", port.peripheral); 00189 } else { 00190 utest_printf("%d - peripheral tested on port: %s...", port.peripheral, port.str()); 00191 if (port.status == PortType::StatusNotTested) { 00192 FunctionCaller<PortType, FunctionType, f> call; 00193 call(port); // run test 00194 port.status = PortType::StatusPass; 00195 } 00196 utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed"); 00197 } 00198 } 00199 00200 template<typename PortType, typename FunctionType, FunctionType f> 00201 void test_all_peripherals(std::list<PortType> &matched_ports, std::list<PortType> ¬_matched_ports) 00202 { 00203 typedef typename std::list<PortType>::iterator Iter; 00204 utest_printf("***Testing all %s peripherals***\n", PortType::PinMap::name); 00205 00206 if (matched_ports.empty() && not_matched_ports.empty()) { 00207 utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name); 00208 return; 00209 } 00210 00211 matched_ports.sort(peripheral_less<PortType>); 00212 not_matched_ports.sort(peripheral_less<PortType>); 00213 00214 for (Iter m_it = matched_ports.begin(), nm_it = not_matched_ports.begin(); 00215 m_it != matched_ports.end() || nm_it != not_matched_ports.end();) { 00216 if (m_it != matched_ports.end() && nm_it != not_matched_ports.end()) { 00217 if ((*m_it).peripheral < (*nm_it).peripheral) { 00218 test_peripheral<PortType, FunctionType, f>(*m_it); 00219 ++m_it; 00220 } else { 00221 test_peripheral<PortType, FunctionType, f>(*nm_it); 00222 ++nm_it; 00223 } 00224 } else if (m_it != matched_ports.end()) { 00225 test_peripheral<PortType, FunctionType, f>(*m_it); 00226 ++m_it; 00227 } else if (nm_it != not_matched_ports.end()) { 00228 test_peripheral<PortType, FunctionType, f>(*nm_it); 00229 ++nm_it; 00230 } 00231 } 00232 } 00233 00234 /** 00235 * Test function for all pinouts of all peripherals of a given type 00236 * 00237 * This template function takes in three template parameters: 00238 * - PortType - The type of peripheral to test 00239 * - FormFactorType - The form factor to test on 00240 * - f - The test function to run. 00241 * 00242 * This function calls the test function multiple times with 00243 * the appropriate combinations of pins. 00244 */ 00245 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f> 00246 void all_ports() 00247 { 00248 std::list<PortType> matched_ports, not_matched_ports; 00249 find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports); 00250 matched_ports.unique(); 00251 not_matched_ports.unique(); 00252 test_all_ports<PortType, FormFactorType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports); 00253 } 00254 00255 /** 00256 * Test function for one pinout of all peripherals of a given type 00257 * 00258 * This template function takes in three template parameters: 00259 * - PortType - The type of peripheral to test 00260 * - FormFactorType - The form factor to test on 00261 * - f - The test function to run. 00262 * 00263 * This function calls the test function once for each peripheral 00264 * of the given type. 00265 */ 00266 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f> 00267 void all_peripherals() 00268 { 00269 std::list<PortType> matched_ports, not_matched_ports; 00270 find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports); 00271 00272 matched_ports.sort(peripheral_less<PortType>); 00273 not_matched_ports.sort(peripheral_less<PortType>); 00274 matched_ports.unique(peripheral_comparator<PortType>); 00275 not_matched_ports.unique(peripheral_comparator<PortType>); 00276 00277 test_all_peripherals<PortType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports); 00278 } 00279 00280 /** 00281 * Test function for one pinout of one peripheral of a given type 00282 * 00283 * This template function takes in three template parameters: 00284 * - PortType - The type of peripheral to test 00285 * - FormFactorType - The form factor to test on 00286 * - f - The test function to run. 00287 * 00288 * This function calls the test function once for one peripheral 00289 * of the given type. 00290 */ 00291 template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f> 00292 void one_peripheral() 00293 { 00294 std::list<PortType> matched_ports, not_matched_ports; 00295 find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports); 00296 00297 utest_printf("***Testing one %s pin configuration***\n", PortType::PinMap::name); 00298 if (matched_ports.empty()) { 00299 utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name); 00300 } else { 00301 test_peripheral<PortType, typename PortType::TestFunctionType, f>(matched_ports.front()); 00302 } 00303 } 00304 00305 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType> 00306 class Port; 00307 00308 template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType> 00309 bool operator== (const Port<N, PinMapType, FormFactorType, TestFunctionType> &port1, 00310 const Port<N, PinMapType, FormFactorType, TestFunctionType> &port2); 00311 00312 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType> 00313 class Port { 00314 public: 00315 int peripheral; 00316 PinName pins[N]; 00317 PinName *ppins[N]; 00318 00319 static const uint32_t pin_count = N; 00320 typedef PinMapType PinMap; 00321 typedef FunctionType TestFunctionType; 00322 00323 enum Status { StatusPass, StatusFail, StatusNotTested }; 00324 Status status; 00325 00326 Port(): peripheral(NC), status(StatusNotTested) 00327 { 00328 init_pins(); 00329 } 00330 00331 Port(const Port &port) 00332 { 00333 init_pins(); 00334 copy_from(port); 00335 } 00336 00337 void init_pins() 00338 { 00339 for (uint32_t i = 0; i < N; i++) { 00340 pins[i] = NC; 00341 ppins[i] = &pins[i]; 00342 } 00343 } 00344 00345 void copy_from(const Port &port) 00346 { 00347 peripheral = port.peripheral; 00348 status = port.status; 00349 for (uint32_t i = 0; i < N; i++) { 00350 pins[i] = port.pins[i]; 00351 } 00352 } 00353 00354 bool empty() 00355 { 00356 if (peripheral == NC) { 00357 return true; 00358 } 00359 for (uint32_t i = 0; i < N; i++) { 00360 if (pins[i] == NC) { 00361 return true; 00362 } 00363 } 00364 return false; 00365 } 00366 00367 const char *str() 00368 { 00369 static char port_str[128]; 00370 char pin_str[32]; 00371 sprintf(port_str, "peripheral=(%d) ", peripheral); 00372 for (uint32_t i = 0; i < N; i++) { 00373 sprintf(pin_str, "%s=(%s) ", PinMap::pin_type_names[i], FormFactorType::pin_to_string(pins[i])); 00374 strcat(port_str, pin_str); 00375 } 00376 return port_str; 00377 } 00378 00379 friend bool operator==<> (const Port<N, PinMapType, FormFactorType, FunctionType> &port1, const Port<N, PinMapType, FormFactorType, FunctionType> &port2); 00380 }; 00381 00382 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType> 00383 const uint32_t Port<N, PinMapType, FormFactorType, FunctionType>::pin_count; 00384 00385 template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType> 00386 bool operator== (const Port<N, PinMapType, FormFactorType, FunctionType> &port1, const Port<N, PinMapType, FormFactorType, FunctionType> &port2) 00387 { 00388 if (port1.peripheral != port2.peripheral) { 00389 return false; 00390 } 00391 for (uint32_t i = 0; i < N; i++) { 00392 if (port1.pins[i] != port2.pins[i]) { 00393 return false; 00394 } 00395 } 00396 return true; 00397 } 00398 00399 /** 00400 * This is a convenience class for use with the above templates 00401 * 00402 * This class can be passed as a template parameter to all_ports, 00403 * all_peripherals or one_peripheral to choose test pins from 00404 * the default form factor. 00405 */ 00406 class DefaultFormFactor { 00407 public: 00408 static const PinList *pins() 00409 { 00410 return pinmap_ff_default_pins(); 00411 } 00412 00413 static const PinList *restricted_pins() 00414 { 00415 return pinmap_restricted_pins(); 00416 } 00417 00418 static const char *pin_to_string(PinName pin) 00419 { 00420 return pinmap_ff_default_pin_to_string(pin); 00421 } 00422 }; 00423 00424 /* 00425 * Peripheral port declarations are given below 00426 * 00427 * Each Port type represents a set of pins used by a peripheral. 00428 * The Port typedef is used as a template parameter to the functions 00429 * all_ports, all_peripherals and one_peripheral to select the peripheral 00430 * pin set to use for testing. 00431 */ 00432 00433 struct GPIOMaps { 00434 static const PinMap *maps[]; 00435 static const char *const pin_type_names[]; 00436 static const char *const name; 00437 }; 00438 const PinMap *GPIOMaps::maps[] = { gpio_pinmap() }; 00439 const char *const GPIOMaps::pin_type_names[] = { "IO" }; 00440 const char *const GPIOMaps::name = "GPIO"; 00441 typedef Port<1, GPIOMaps, DefaultFormFactor, TF1> GPIOPort; 00442 00443 #if DEVICE_INTERRUPTIN 00444 #include "gpio_irq_api.h" 00445 struct GPIOIRQMaps { 00446 static const PinMap *maps[]; 00447 static const char *const pin_type_names[]; 00448 static const char *const name; 00449 }; 00450 const PinMap *GPIOIRQMaps::maps[] = { gpio_irq_pinmap() }; 00451 const char *const GPIOIRQMaps::pin_type_names[] = { "IRQ_IN" }; 00452 const char *const GPIOIRQMaps::name = "GPIO_IRQ"; 00453 typedef Port<1, GPIOIRQMaps, DefaultFormFactor, TF1> GPIOIRQPort; 00454 #endif 00455 00456 #if DEVICE_SPI 00457 #include "spi_api.h" 00458 struct SPIMaps { 00459 static const PinMap *maps[]; 00460 static const char *const pin_type_names[]; 00461 static const char *const name; 00462 }; 00463 const PinMap *SPIMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap(), spi_master_cs_pinmap() }; 00464 const char *const SPIMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" }; 00465 const char *const SPIMaps::name = "SPI"; 00466 typedef Port<4, SPIMaps, DefaultFormFactor, TF4> SPIPort; 00467 00468 struct SPINoCSMaps { 00469 static const PinMap *maps[]; 00470 static const char *const pin_type_names[]; 00471 static const char *const name; 00472 }; 00473 const PinMap *SPINoCSMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap()}; 00474 const char *const SPINoCSMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK" }; 00475 const char *const SPINoCSMaps::name = "SPI"; 00476 typedef Port<3, SPINoCSMaps, DefaultFormFactor, TF3> SPINoCSPort; 00477 00478 struct SPISlaveMaps { 00479 static const PinMap *maps[]; 00480 static const char *const pin_type_names[]; 00481 static const char *const name; 00482 }; 00483 const PinMap *SPISlaveMaps::maps[] = { spi_slave_mosi_pinmap(), spi_slave_miso_pinmap(), spi_slave_clk_pinmap(), spi_slave_cs_pinmap() }; 00484 const char *const SPISlaveMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" }; 00485 const char *const SPISlaveMaps::name = "SPISlave"; 00486 typedef Port<4, SPISlaveMaps, DefaultFormFactor, TF4> SPISlavePort; 00487 #endif 00488 00489 #if DEVICE_I2C 00490 #include "i2c_api.h" 00491 struct I2CMaps { 00492 static const PinMap *maps[]; 00493 static const char *const pin_type_names[]; 00494 static const char *const name; 00495 }; 00496 const PinMap *I2CMaps::maps[] = { i2c_master_sda_pinmap(), i2c_master_scl_pinmap() }; 00497 const char *const I2CMaps::pin_type_names[] = { "SDA", "SCL" }; 00498 const char *const I2CMaps::name = "I2C"; 00499 typedef Port<2, I2CMaps, DefaultFormFactor, TF2> I2CPort; 00500 #endif 00501 00502 #if DEVICE_PWMOUT 00503 #include "pwmout_api.h" 00504 struct PWMMaps { 00505 static const PinMap *maps[]; 00506 static const char *const pin_type_names[]; 00507 static const char *const name; 00508 }; 00509 const PinMap *PWMMaps::maps[] = { pwmout_pinmap() }; 00510 const char *const PWMMaps::pin_type_names[] = { "PWM_OUT" }; 00511 const char *const PWMMaps::name = "PWM"; 00512 typedef Port<1, PWMMaps, DefaultFormFactor, TF1> PWMPort; 00513 #endif 00514 00515 #if DEVICE_ANALOGIN 00516 #include "analogin_api.h" 00517 struct AnaloginMaps { 00518 static const PinMap *maps[]; 00519 static const char *const pin_type_names[]; 00520 static const char *const name; 00521 }; 00522 const PinMap *AnaloginMaps::maps[] = { analogin_pinmap() }; 00523 const char *const AnaloginMaps::pin_type_names[] = { "ADC_IN" }; 00524 const char *const AnaloginMaps::name = "ADC"; 00525 typedef Port<1, AnaloginMaps, DefaultFormFactor, TF1> AnaloginPort; 00526 #endif 00527 00528 #if DEVICE_ANALOGOUT 00529 #include "analogout_api.h" 00530 struct AnalogoutMaps { 00531 static const PinMap *maps[]; 00532 static const char *const pin_type_names[]; 00533 static const char *const name; 00534 }; 00535 const PinMap *AnalogoutMaps::maps[] = { analogout_pinmap() }; 00536 const char *const AnalogoutMaps::pin_type_names[] = { "DAC_OUT" }; 00537 const char *const AnalogoutMaps::name = "DAC"; 00538 typedef Port<1, AnalogoutMaps, DefaultFormFactor, TF1> AnalogoutPort; 00539 #endif 00540 00541 #if DEVICE_SERIAL 00542 #if DEVICE_SERIAL_FC 00543 struct UARTMaps { 00544 static const PinMap *maps[]; 00545 static const char *const pin_type_names[]; 00546 static const char *const name; 00547 }; 00548 const PinMap *UARTMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap(), serial_cts_pinmap(), serial_rts_pinmap() }; 00549 const char *const UARTMaps::pin_type_names[] = { "TX", "RX", "CLS", "RTS" }; 00550 const char *const UARTMaps::name = "UART"; 00551 typedef Port<4, UARTMaps, DefaultFormFactor, TF4> UARTPort; 00552 #endif 00553 00554 struct UARTNoFCMaps { 00555 static const PinMap *maps[]; 00556 static const char *const pin_type_names[]; 00557 static const char *const name; 00558 }; 00559 const PinMap *UARTNoFCMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap() }; 00560 const char *const UARTNoFCMaps::pin_type_names[] = { "TX", "RX" }; 00561 const char *const UARTNoFCMaps::name = "UART-no-FC"; 00562 typedef Port<2, UARTNoFCMaps, DefaultFormFactor, TF2> UARTNoFCPort; 00563 #endif 00564 00565 #endif
Generated on Tue Jul 12 2022 13:54:56 by
