1import os
2import sys
3import json
4
5def create_need_files(targetId, packpath):
6    """
7    Generate pyocd.yaml files
8    """
9    yaml_file = open('pyocd.yaml', 'w')
10    if yaml_file:
11        yaml_file.write('\npack:\n')
12        yaml_file.write('  - ' + packpath + '\n')
13        yaml_file.close()
14
15    """
16    Generate .vscode/launch.json files
17    """
18    vsc_launch_file = open('.vscode/launch.json', 'w')
19    if vsc_launch_file:
20        config_obj = {}
21        config_obj['name'] = 'Cortex Debug'
22        config_obj['cwd'] = '${workspaceFolder}'
23        config_obj['executable'] = 'rt-thread.elf'
24        config_obj['request'] = 'launch'
25        config_obj['type'] = 'cortex-debug'
26        config_obj['runToEntryPoint'] = 'Reset_Handler'
27        config_obj['servertype'] = 'pyocd'
28        if os.getenv('RTT_EXEC_PATH'):
29            config_obj['armToolchainPath'] = os.getenv('RTT_EXEC_PATH').replace('\\', '/')
30        else:
31            print('env <RTT_EXEC_PATH> not set!')
32        config_obj['toolchainPrefix'] = 'arm-none-eabi'
33        config_obj['targetId'] = targetId
34
35        json_obj = {}
36        json_obj['version'] = '0.2.0'
37        json_obj['configurations'] = [config_obj]
38        vsc_launch_file.write(json.dumps(json_obj, ensure_ascii=False, indent=4))
39        vsc_launch_file.close()
40
41    """
42    Generate .vscode/tasks.json files
43    """
44    vsc_tasks_file = open('.vscode/tasks.json', 'w')
45    if vsc_tasks_file:
46        task_build_obj = {}
47        task_build_obj['type'] = 'shell'
48        task_build_obj['label'] = 'Build target files'
49        task_build_obj['command'] = 'scons'
50        task_build_obj['args'] = ['-j12']
51        task_build_obj['problemMatcher'] = ['$gcc']
52        task_build_obj['group'] = 'build'
53
54        task_download_obj = {}
55        task_download_obj['type'] = 'shell'
56        task_download_obj['label'] = 'Download code to flash memory'
57        task_download_obj['command'] = 'python'
58        task_download_obj['args'] = ['-m', 'pyocd', 'flash', '--erase', 'chip', '--target', \
59                                    targetId, 'rt-thread.elf']
60        task_download_obj['problemMatcher'] = ['$gcc']
61        task_download_obj['group'] = 'build'
62
63        task_build_download_obj = task_download_obj.copy()
64        task_build_download_obj['label'] = 'Build and Download'
65        task_build_download_obj['dependsOn'] = 'Build target files'
66
67        json_obj = {}
68        json_obj['version'] = '2.0.0'
69        json_obj['tasks'] = [task_build_obj, task_download_obj, task_build_download_obj]
70        vsc_tasks_file.write(json.dumps(json_obj, ensure_ascii=False, indent=4))
71        vsc_tasks_file.close()
72
73def similar_char_num(str1, str2):
74    lstr1 = len(str1)
75    lstr2 = len(str2)
76    record = [[0 for i in range(lstr2+1)] for j in range(lstr1+1)]
77    similar_num = 0
78
79    for i in range(lstr1):
80        for j in range(lstr2):
81            if str1[i] == str2[j]:
82                record[i+1][j+1] = record[i][j] + 1
83                if record[i+1][j+1] > similar_num:
84                    similar_num = record[i+1][j+1]
85    return similar_num
86
87def get_socName_from_rtconfig():
88    socName = None
89    rtconfig_file = open('rtconfig.h', 'r')
90    if rtconfig_file:
91        for line in rtconfig_file.readlines():
92            if 'SOC' in line and 'FAMILY' not in line and 'SERIES' not in line:
93                socName = line.strip().split('_')[-1]
94        rtconfig_file.close()
95        return socName
96
97def get_pack_from_env():
98    if os.environ.get('ENV_ROOT') == None:
99        if sys.platform == 'win32':
100            home_dir = os.environ['USERPROFILE']
101            env_dir  = os.path.join(home_dir, '.env')
102        else:
103            home_dir = os.environ['HOME']
104            env_dir  = os.path.join(home_dir, '.env')
105    else:
106        env_dir =  os.environ.get('ENV_ROOT')
107
108    pack_dir = env_dir.replace('\\', '/') + '/tools/cmsisPacks/'
109
110    if not os.path.exists(pack_dir):
111        print('<%s> does not exist, please create.' % pack_dir)
112        return
113
114    # get soc name from <rtconfig.h> file
115    socName = get_socName_from_rtconfig()
116    if socName == None:
117        return
118
119    # Find the pack that best matches soc name
120    max_similar_num = 0
121    max_similar_pack = None
122    for file in os.listdir(pack_dir):
123        if str(file).endswith('.pack'):
124            similar_num = similar_char_num(socName, file)
125            if(similar_num > max_similar_num):
126                max_similar_num = similar_num
127                max_similar_pack = file
128    print('SOC<%s> match the pack is <%s>' % (socName, max_similar_pack))
129    if max_similar_pack == None:
130        return
131
132    return pack_dir + max_similar_pack
133
134def get_trgetId_from_pack(pack):
135    # get soc name from <rtconfig.h> file
136    socName = get_socName_from_rtconfig()
137    if socName == None:
138        return
139
140    # View the soc supported by the most similar cmsisPack
141    result = os.popen('python -m pyocd json --target --pack ' + pack)
142    pyocd_json = json.loads(result.read())
143    if pyocd_json['status'] != 0:
144        return
145
146    # Find the targetId that best matches soc name
147    max_similar_num = 0
148    max_similar_targetId = None
149    for target in pyocd_json['targets']:
150        if (target['source'] == 'pack'):
151            similar_num = similar_char_num(socName.lower(), target['name'])
152            if(similar_num > max_similar_num):
153                max_similar_num = similar_num
154                max_similar_targetId = target['name']
155    print('SOC<%s> match the targetId is <%s>' % (socName, max_similar_targetId))
156    if max_similar_targetId == None:
157        return
158    if max_similar_num < len(socName):
159        print('<%s> not match the <%s>' % (socName, pack))
160        return
161
162    return max_similar_targetId
163
164def GenerateVSCodePyocdConfig(pack):
165    if pack == 'env':
166        pack = get_pack_from_env()
167        if pack == None:
168            return
169    else:
170        # Check is exist
171        if not os.path.exists(pack):
172            return
173        # Check is file
174        if not os.path.isfile(pack):
175            return
176        # Check is pack
177        if not str(pack).endswith('.pack'):
178            return
179
180    pack = pack.replace('\\', '/')
181
182    targetId = get_trgetId_from_pack(pack)
183    if targetId ==None:
184        return
185
186    create_need_files(targetId, pack)
187    print('Pyocd Config Done!')
188
189    return
190
191