Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lint.py
00001 """A linting utility for targets.json 00002 00003 This linting utility may be called as follows: 00004 python <path-to>/lint.py targets TARGET [TARGET ...] 00005 00006 all targets will be linted 00007 """ 00008 00009 # mbed SDK 00010 # Copyright (c) 2017 ARM Limited 00011 # 00012 # Licensed under the Apache License, Version 2.0 (the "License"); 00013 # you may not use this file except in compliance with the License. 00014 # You may obtain a copy of the License at 00015 # 00016 # http://www.apache.org/licenses/LICENSE-2.0 00017 # 00018 # Unless required by applicable law or agreed to in writing, software 00019 # distributed under the License is distributed on an "AS IS" BASIS, 00020 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00021 # See the License for the specific language governing permissions and 00022 # limitations under the License. 00023 00024 from os.path import join, abspath, dirname 00025 if __name__ == "__main__": 00026 import sys 00027 ROOT = abspath(join(dirname(__file__), "..", "..")) 00028 sys.path.insert(0, ROOT) 00029 from copy import copy 00030 from yaml import dump_all 00031 import argparse 00032 00033 from tools.targets import Target, set_targets_json_location, TARGET_MAP 00034 00035 def must_have_keys (keys, dict): 00036 """Require keys in an MCU/Board 00037 00038 is a generator for errors 00039 """ 00040 for key in keys: 00041 if key not in dict: 00042 yield "%s not found, and is required" % key 00043 00044 def may_have_keys (keys, dict): 00045 """Disable all other keys in an MCU/Board 00046 00047 is a generator for errors 00048 """ 00049 for key in dict.keys(): 00050 if key not in keys: 00051 yield "%s found, and is not allowed" % key 00052 00053 def check_extra_labels (dict): 00054 """Check that extra_labels does not contain any Target names 00055 00056 is a generator for errors 00057 """ 00058 for label in (dict.get("extra_labels", []) + 00059 dict.get("extra_labels_add", [])): 00060 if label in Target.get_json_target_data(): 00061 yield "%s is not allowed in extra_labels" % label 00062 00063 def check_release_version (dict): 00064 """Verify that release version 5 is combined with support for all toolcahins 00065 00066 is a generator for errors 00067 """ 00068 if ("release_versions" in dict and 00069 "5" in dict["release_versions"] and 00070 "supported_toolchains" in dict): 00071 for toolc in ["GCC_ARM", "ARM", "IAR"]: 00072 if toolc not in dict["supported_toolchains"]: 00073 yield ("%s not found in supported_toolchains, and is " 00074 "required by mbed OS 5" % toolc) 00075 00076 def check_inherits(dict): 00077 if ("inherits" in dict and len(dict["inherits"]) > 1): 00078 yield "multiple inheritance is forbidden" 00079 00080 DEVICE_HAS_ALLOWED = ["ANALOGIN", "ANALOGOUT", "CAN", "ETHERNET", "EMAC", 00081 "FLASH", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", 00082 "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", 00083 "PWMOUT", "RTC", "TRNG","SERIAL", "SERIAL_ASYNCH", 00084 "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", 00085 "STORAGE", "STCLK_OFF_DURING_SLEEP"] 00086 def check_device_has(dict): 00087 for name in dict.get("device_has", []): 00088 if name not in DEVICE_HAS_ALLOWED: 00089 yield "%s is not allowed in device_has" % name 00090 00091 MCU_REQUIRED_KEYS = ["release_versions", "supported_toolchains", 00092 "default_lib", "public", "inherits", "device_has"] 00093 MCU_ALLOWED_KEYS = ["device_has_add", "device_has_remove", "core", 00094 "extra_labels", "features", "features_add", 00095 "features_remove", "bootloader_supported", "device_name", 00096 "post_binary_hook", "default_toolchain", "config", 00097 "extra_labels_add", "extra_labels_remove", 00098 "target_overrides"] + MCU_REQUIRED_KEYS 00099 def check_mcu (mcu_json, strict=False): 00100 """Generate a list of problems with an MCU 00101 00102 :param: mcu_json the MCU's dict to check 00103 :param: strict enforce required keys 00104 """ 00105 errors = list(may_have_keys(MCU_ALLOWED_KEYS, mcu_json)) 00106 if strict: 00107 errors.extend(must_have_keys(MCU_REQUIRED_KEYS, mcu_json)) 00108 errors.extend(check_extra_labels(mcu_json)) 00109 errors.extend(check_release_version(mcu_json)) 00110 errors.extend(check_inherits(mcu_json)) 00111 errors.extend(check_device_has(mcu_json)) 00112 if 'public' in mcu_json and mcu_json['public']: 00113 errors.append("public must be false") 00114 return errors 00115 00116 BOARD_REQUIRED_KEYS = ["inherits"] 00117 BOARD_ALLOWED_KEYS = ["supported_form_factors", "is_disk_virtual", 00118 "detect_code", "extra_labels", "extra_labels_add", 00119 "extra_labels_remove", "public", "config", 00120 "forced_reset_timeout", "target_overrides"] + BOARD_REQUIRED_KEYS 00121 def check_board (board_json, strict=False): 00122 """Generate a list of problems with an board 00123 00124 :param: board_json the mcus dict to check 00125 :param: strict enforce required keys 00126 """ 00127 errors = list(may_have_keys(BOARD_ALLOWED_KEYS, board_json)) 00128 if strict: 00129 errors.extend(must_have_keys(BOARD_REQUIRED_KEYS, board_json)) 00130 errors.extend(check_extra_labels(board_json)) 00131 errors.extend(check_inherits(board_json)) 00132 return errors 00133 00134 def add_if (dict, key, val): 00135 """Add a value to a dict if it's non-empty""" 00136 if val: 00137 dict[key] = val 00138 00139 def _split_boards(resolution_order, tgt): 00140 """Split the resolution order between boards and mcus""" 00141 mcus = [] 00142 boards = [] 00143 iterable = iter(resolution_order) 00144 for name in iterable: 00145 mcu_json = tgt.json_data[name] 00146 if (len(list(check_mcu(mcu_json, True))) > 00147 len(list(check_board(mcu_json, True)))): 00148 boards.append(name) 00149 else: 00150 mcus.append(name) 00151 break 00152 mcus.extend(iterable) 00153 mcus.reverse() 00154 boards.reverse() 00155 return mcus, boards 00156 00157 00158 MCU_FORMAT_STRING = {1: "MCU (%s) ->", 00159 2: "Family (%s) -> MCU (%s) ->", 00160 3: "Family (%s) -> SubFamily (%s) -> MCU (%s) ->"} 00161 BOARD_FORMAT_STRING = {1: "Board (%s)", 00162 2: "Module (%s) -> Board (%s)"} 00163 def _generate_hierarchy_string(mcus, boards): 00164 global_errors = [] 00165 if len(mcus) < 1: 00166 global_errors.append("No MCUS found in heirarchy") 00167 mcus_string = "??? ->" 00168 elif len(mcus) > 3: 00169 global_errors.append("No name for targets %s" % ", ".join(mcus[3:])) 00170 mcus_string = MCU_FORMAT_STRING[3] % tuple(mcus[:3]) 00171 for name in mcus[3:]: 00172 mcus_string += " ??? (%s) ->" % name 00173 else: 00174 mcus_string = MCU_FORMAT_STRING[len(mcus)] % tuple(mcus) 00175 00176 if len(boards) < 1: 00177 global_errors.append("no boards found in heirarchy") 00178 boards_string = "???" 00179 elif len(boards) > 2: 00180 global_errors.append("no name for targets %s" % ", ".join(boards[2:])) 00181 boards_string = BOARD_FORMAT_STRING[2] % tuple(boards[:2]) 00182 for name in boards[2:]: 00183 boards_string += " -> ??? (%s)" % name 00184 else: 00185 boards_string = BOARD_FORMAT_STRING[len(boards)] % tuple(boards) 00186 return mcus_string + " " + boards_string, global_errors 00187 00188 00189 def check_hierarchy (tgt): 00190 """Atempts to assign labels to the heirarchy""" 00191 resolution_order = copy(tgt.resolution_order_names[:-1]) 00192 mcus, boards = _split_boards(resolution_order, tgt) 00193 00194 target_errors = {} 00195 hierachy_string, hierachy_errors = _generate_hierarchy_string(mcus, boards) 00196 to_ret = {"hierarchy": hierachy_string} 00197 add_if(to_ret, "hierarchy errors", hierachy_errors) 00198 00199 for name in mcus[:-1]: 00200 add_if(target_errors, name, list(check_mcu(tgt.json_data[name]))) 00201 if len(mcus) >= 1: 00202 add_if(target_errors, mcus[-1], 00203 list(check_mcu(tgt.json_data[mcus[-1]], True))) 00204 for name in boards: 00205 add_if(target_errors, name, list(check_board(tgt.json_data[name]))) 00206 if len(boards) >= 1: 00207 add_if(target_errors, boards[-1], 00208 list(check_board(tgt.json_data[boards[-1]], True))) 00209 add_if(to_ret, "target errors", target_errors) 00210 return to_ret 00211 00212 PARSER = argparse.ArgumentParser(prog="targets/lint.py") 00213 SUBPARSERS = PARSER.add_subparsers(title="Commands") 00214 00215 def subcommand(name, *args, **kwargs): 00216 def __subcommand(command): 00217 kwargs['description'] = command.__doc__ 00218 subparser = SUBPARSERS.add_parser(name, **kwargs) 00219 for arg in args: 00220 arg = dict(arg) 00221 opt = arg['name'] 00222 del arg['name'] 00223 00224 if isinstance(opt, basestring): 00225 subparser.add_argument(opt, **arg) 00226 else: 00227 subparser.add_argument(*opt, **arg) 00228 00229 def _thunk(parsed_args): 00230 argv = [arg['dest'] if 'dest' in arg else arg['name'] 00231 for arg in args] 00232 argv = [(arg if isinstance(arg, basestring) 00233 else arg[-1]).strip('-').replace('-', '_') 00234 for arg in argv] 00235 argv = {arg: vars(parsed_args)[arg] for arg in argv 00236 if vars(parsed_args)[arg] is not None} 00237 00238 return command(**argv) 00239 00240 subparser.set_defaults(command=_thunk) 00241 return command 00242 return __subcommand 00243 00244 @subcommand("targets", 00245 dict(name="mcus", nargs="+", metavar="MCU", 00246 choices=TARGET_MAP.keys(), type=str.upper)) 00247 def targets_cmd (mcus=[]): 00248 """Find and print errors about specific targets""" 00249 print dump_all([check_hierarchy(TARGET_MAP[m]) for m in mcus], 00250 default_flow_style=False) 00251 00252 @subcommand("all-targets") 00253 def all_targets_cmd (): 00254 """Print all errors about all parts""" 00255 print dump_all([check_hierarchy(m) for m in TARGET_MAP.values()], 00256 default_flow_style=False) 00257 00258 @subcommand("orphans") 00259 def orphans_cmd (): 00260 """Find and print all orphan targets""" 00261 orphans = Target.get_json_target_data().keys() 00262 for tgt in TARGET_MAP.values(): 00263 for name in tgt.resolution_order_names: 00264 if name in orphans: 00265 orphans.remove(name) 00266 if orphans: 00267 print dump_all([orphans], default_flow_style=False) 00268 return len(orphans) 00269 00270 def main (): 00271 """entry point""" 00272 options = PARSER.parse_args() 00273 return options.command(options) 00274 00275 if __name__ == "__main__": 00276 sys.exit(main()) 00277
Generated on Sun Jul 17 2022 08:25:24 by 1.7.2