diff --git a/.gitignore b/.gitignore
index 6ad18a8..a803a46 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
build
buildlogs*
-__pycache__
\ No newline at end of file
+__pycache__
+MaximSDK/Template/.vscode/readme.md
\ No newline at end of file
diff --git a/MaximSDK/Inject/.vscode/flash.gdb b/MaximSDK/Inject/.vscode/flash.gdb
index 2d86f86..fc627ae 100644
--- a/MaximSDK/Inject/.vscode/flash.gdb
+++ b/MaximSDK/Inject/.vscode/flash.gdb
@@ -5,3 +5,11 @@ define flash_m4
compare-sections
monitor reset halt
end
+
+define flash_m4_run
+ set architecture armv7e-m
+ target remote | openocd -c "gdb_port pipe;log_output flash.log" -s $arg0/scripts -f interface/$arg1 -f target/$arg2 -c "init; reset halt"
+ load
+ compare-sections
+ monitor resume
+end
\ No newline at end of file
diff --git a/MaximSDK/Inject/.vscode/tasks.json b/MaximSDK/Inject/.vscode/tasks.json
index 5eef671..3951f35 100644
--- a/MaximSDK/Inject/.vscode/tasks.json
+++ b/MaximSDK/Inject/.vscode/tasks.json
@@ -26,25 +26,56 @@
"label": "flash",
"type": "shell",
"command": "arm-none-eabi-gdb",
+ "args": [
+ "--cd=\"${workspaceFolder}\"",
+ "--se=\"build/${config:program_file}\"",
+ "--symbols=build/${config:symbol_file}",
+ "-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
+ "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--batch"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "dependsOn":["build"]
+ },
+ {
+ "label": "flash & run",
+ "type": "shell",
+ "command": "arm-none-eabi-gdb",
"args": [
"--cd=\"${workspaceFolder}\"",
"--se=\"build/${config:program_file}\"",
"--symbols=build/${config:symbol_file}",
"-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
- "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--ex=\"flash_m4_run ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
"--batch"
],
"group": "build",
"problemMatcher": [],
"dependsOn":["build"]
},
+ {
+ "label": "erase flash",
+ "type": "shell",
+ "command": "openocd",
+ "args": [
+ "-s", "${config:OCD_path}/scripts",
+ "-f", "interface/${config:M4_OCD_interface_file}",
+ "-f", "target/${config:M4_OCD_target_file}",
+ "-c", "\"init; reset halt; max32xxx mass_erase 0;\"",
+ "-c", "exit"
+ ],
+ "group":"build",
+ "problemMatcher": [],
+ "dependsOn":[]
+ },
{
"label": "openocd (m4)",
"type": "shell",
"command": "openocd",
"args": [
"-s",
- "${config:MAXIM_PATH}/Tools/OpenOCD/scripts",
+ "${config:OCD_path}/scripts",
"-f",
"interface/${config:M4_OCD_interface_file}",
"-f",
diff --git a/MaximSDK/New_Project/.vscode/flash.gdb b/MaximSDK/New_Project/.vscode/flash.gdb
index 2d86f86..fc627ae 100644
--- a/MaximSDK/New_Project/.vscode/flash.gdb
+++ b/MaximSDK/New_Project/.vscode/flash.gdb
@@ -5,3 +5,11 @@ define flash_m4
compare-sections
monitor reset halt
end
+
+define flash_m4_run
+ set architecture armv7e-m
+ target remote | openocd -c "gdb_port pipe;log_output flash.log" -s $arg0/scripts -f interface/$arg1 -f target/$arg2 -c "init; reset halt"
+ load
+ compare-sections
+ monitor resume
+end
\ No newline at end of file
diff --git a/MaximSDK/New_Project/.vscode/tasks.json b/MaximSDK/New_Project/.vscode/tasks.json
index 5eef671..3951f35 100644
--- a/MaximSDK/New_Project/.vscode/tasks.json
+++ b/MaximSDK/New_Project/.vscode/tasks.json
@@ -26,25 +26,56 @@
"label": "flash",
"type": "shell",
"command": "arm-none-eabi-gdb",
+ "args": [
+ "--cd=\"${workspaceFolder}\"",
+ "--se=\"build/${config:program_file}\"",
+ "--symbols=build/${config:symbol_file}",
+ "-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
+ "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--batch"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "dependsOn":["build"]
+ },
+ {
+ "label": "flash & run",
+ "type": "shell",
+ "command": "arm-none-eabi-gdb",
"args": [
"--cd=\"${workspaceFolder}\"",
"--se=\"build/${config:program_file}\"",
"--symbols=build/${config:symbol_file}",
"-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
- "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--ex=\"flash_m4_run ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
"--batch"
],
"group": "build",
"problemMatcher": [],
"dependsOn":["build"]
},
+ {
+ "label": "erase flash",
+ "type": "shell",
+ "command": "openocd",
+ "args": [
+ "-s", "${config:OCD_path}/scripts",
+ "-f", "interface/${config:M4_OCD_interface_file}",
+ "-f", "target/${config:M4_OCD_target_file}",
+ "-c", "\"init; reset halt; max32xxx mass_erase 0;\"",
+ "-c", "exit"
+ ],
+ "group":"build",
+ "problemMatcher": [],
+ "dependsOn":[]
+ },
{
"label": "openocd (m4)",
"type": "shell",
"command": "openocd",
"args": [
"-s",
- "${config:MAXIM_PATH}/Tools/OpenOCD/scripts",
+ "${config:OCD_path}/scripts",
"-f",
"interface/${config:M4_OCD_interface_file}",
"-f",
diff --git a/MaximSDK/Template/.vscode/flash.gdb b/MaximSDK/Template/.vscode/flash.gdb
index 2d86f86..fc627ae 100644
--- a/MaximSDK/Template/.vscode/flash.gdb
+++ b/MaximSDK/Template/.vscode/flash.gdb
@@ -5,3 +5,11 @@ define flash_m4
compare-sections
monitor reset halt
end
+
+define flash_m4_run
+ set architecture armv7e-m
+ target remote | openocd -c "gdb_port pipe;log_output flash.log" -s $arg0/scripts -f interface/$arg1 -f target/$arg2 -c "init; reset halt"
+ load
+ compare-sections
+ monitor resume
+end
\ No newline at end of file
diff --git a/MaximSDK/Template/.vscode/tasks.json b/MaximSDK/Template/.vscode/tasks.json
index 5eef671..3951f35 100644
--- a/MaximSDK/Template/.vscode/tasks.json
+++ b/MaximSDK/Template/.vscode/tasks.json
@@ -26,25 +26,56 @@
"label": "flash",
"type": "shell",
"command": "arm-none-eabi-gdb",
+ "args": [
+ "--cd=\"${workspaceFolder}\"",
+ "--se=\"build/${config:program_file}\"",
+ "--symbols=build/${config:symbol_file}",
+ "-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
+ "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--batch"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "dependsOn":["build"]
+ },
+ {
+ "label": "flash & run",
+ "type": "shell",
+ "command": "arm-none-eabi-gdb",
"args": [
"--cd=\"${workspaceFolder}\"",
"--se=\"build/${config:program_file}\"",
"--symbols=build/${config:symbol_file}",
"-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
- "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--ex=\"flash_m4_run ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
"--batch"
],
"group": "build",
"problemMatcher": [],
"dependsOn":["build"]
},
+ {
+ "label": "erase flash",
+ "type": "shell",
+ "command": "openocd",
+ "args": [
+ "-s", "${config:OCD_path}/scripts",
+ "-f", "interface/${config:M4_OCD_interface_file}",
+ "-f", "target/${config:M4_OCD_target_file}",
+ "-c", "\"init; reset halt; max32xxx mass_erase 0;\"",
+ "-c", "exit"
+ ],
+ "group":"build",
+ "problemMatcher": [],
+ "dependsOn":[]
+ },
{
"label": "openocd (m4)",
"type": "shell",
"command": "openocd",
"args": [
"-s",
- "${config:MAXIM_PATH}/Tools/OpenOCD/scripts",
+ "${config:OCD_path}/scripts",
"-f",
"interface/${config:M4_OCD_interface_file}",
"-f",
diff --git a/generate.py b/generate.py
index 5a1db70..57c3e62 100644
--- a/generate.py
+++ b/generate.py
@@ -34,19 +34,22 @@
import os
import shutil
-import argparse
-import platform
-from subprocess import run
-from utils import parse_json
-from sdk import *
+import stat
+from utils import *
+from pathlib import Path
+
+# Get location of this file.
+# Need to use this so that template look-ups are decoupled from the caller's working directory
+here = Path(__file__).parent
# Load default values for template from master "inject" folder so that we don't have to maintain multiple copies of the settings
-defaults = parse_json("MaximSDK/Inject/.vscode/settings.json")
+defaults = parse_json(here.joinpath("MaximSDK/Inject/.vscode/settings.json"))
whitelist = [
"MAX32650",
"MAX32655",
"MAX32660",
+ "MAX32662",
"MAX32665",
"MAX32670",
"MAX32672",
@@ -61,6 +64,7 @@ def create_project(
out_path: str,
target: str,
board: str,
+ overwrite = False,
program_file: str = defaults["PROGRAM_FILE"],
symbol_file: str = defaults["SYMBOL_FILE"],
m4_ocd_interface_file: str = defaults["M4_OCD_INTERFACE_FILE"],
@@ -75,176 +79,122 @@ def create_project(
ocd_path: str = defaults["OCD_PATH"],
arm_gcc_path: str = defaults["ARM_GCC_PATH"],
xpack_gcc_path: str = defaults["XPACK_GCC_PATH"],
- make_path: str = defaults["MAKE_PATH"]
+ make_path: str = defaults["MAKE_PATH"],
):
+ """
+ Generates Visual Studio Code project files from the VSCode-Maxim project.
+ """
+
+ out_path = Path(out_path)
+
+ template_dir = here.joinpath("MaximSDK/Template").resolve()
+ # Where to find the VS Code template directory relative to this script
- template_dir = os.path.abspath(os.path.join("MaximSDK", "Template")) # Where to find the VS Code template directory relative to this script
- template_prefix = "template" # Filenames beginning with this will have substitution
+ template_prefix = "template"
+ # Filenames beginning with this will have substitution
- if not os.path.exists(template_dir):
- raise(Exception(f"Failed to find project template folder '{template_dir}'. Check the location and existence of these files."))
+ if not template_dir.exists():
+ raise Exception(f"Failed to find project template folder '{template_dir}'.")
tmp = [] # Work-horse list, linter be nice
+ # Parse compiler definitions...
if defines != []:
- # Parse defines...
- # ---
tmp = defines
tmp = list(map(lambda s: s.strip("-D"), tmp)) # VS Code doesn't want -D
- tmp = list(map("\"{0}\"".format, tmp)) # Surround with quotes
+ tmp = list(map(lambda s: f"\"{s}\"", tmp)) # Surround with quotes
defines_parsed = ",\n ".join(tmp) # csv, newline, and tab (w/ spaces) alignment
- # ---
else:
- defines_parsed = ",\n ".join(defines)
+ defines_parsed = ""
# Parse include paths...
tmp = i_paths
- tmp = list(map("\"{0}\"".format, tmp)) # Surround with quotes
+ tmp = list(map(lambda s: f"\"{s}\"", tmp)) # Surround with quotes
i_paths_parsed = ",\n ".join(tmp).replace(target, "${config:target}").replace("\\", "/")
-
# Parse browse paths...
tmp = v_paths
- tmp = list(map("\"{0}\"".format, tmp)) # Surround with quotes
- v_paths_parsed = ",\n ".join(tmp).replace(target, "${config:target}").replace("\\", "/") # csv, newline, and tab alignment
+ tmp = list(map(lambda s: f"\"{s}\"", tmp)) # Surround with quotes
+ v_paths_parsed = ",\n ".join(tmp).replace(target, "${config:target}").replace("\\", "/")
+ updated = []
# Create template...
for directory, _, files in sorted(os.walk(template_dir)):
# ^ For each directory in the directory tree rooted at top (including top itself,
# but excluding '.' and '..'), yields a 3-tuple (dirpath, dirnames, filenames)
# Get current directory relative to root
- rel_dir = os.path.relpath(directory, template_dir)
+ rel_dir = Path(directory).relative_to(Path(template_dir))
# Figure out whether we're in a subfolder of the template directory,
# and form output path accordingly.
- if rel_dir != '.':
+ if rel_dir != Path('.'):
# We're in a sub-folder. Replicate this folder in the output directory
- out_path = os.path.join(out_path, rel_dir)
+ out_path = Path(out_path).joinpath(rel_dir)
os.makedirs(out_path, exist_ok=True)
else:
# We're in the root template folder, no need to create a directory.
pass
+
# Any files to copy?
for file in sorted(files):
if file.startswith(template_prefix):
# There is a template file to copy. Perform string substitution in output file.
- out_loc = os.path.join(out_path, file[len(template_prefix):])
- with open(os.path.join(directory, file)) as in_file, \
- open(out_loc, "w+") as out_file:
- for line in in_file.readlines():
- out_file.write(
- line.replace("##__TARGET__##", target.upper()).
- replace("##__BOARD__##", board).
- replace("##__PROGRAM_FILE__##", program_file).
- replace("##__SYMBOL_FILE__##", symbol_file).
- replace("##__M4_OCD_INTERFACE_FILE__##", m4_ocd_interface_file).
- replace("##__M4_OCD_TARGET_FILE__##", m4_ocd_target_file).
- replace("##__RV_OCD_INTERFACE_FILE__##", rv_ocd_interface_file).
- replace("##__RV_OCD_TARGET_FILE__##", rv_ocd_target_file).
- replace("\"##__I_PATHS__##\"", i_paths_parsed). # Next 3 are surrounded in quotes in the template because of the linter
- replace("\"##__DEFINES__##\"", defines_parsed).
- replace("\"##__V_PATHS__##\"", v_paths_parsed).
- replace("##__V_ARM_GCC__##", v_arm_gcc).
- replace("##__V_XPACK_GCC__##", v_xpack_gcc).
- replace("##__OCD_PATH__##", ocd_path).
- replace("##__ARM_GCC_PATH__##", arm_gcc_path).
- replace("##__XPACK_GCC_PATH__##", xpack_gcc_path).
- replace("##__MAKE_PATH__##", make_path)
- )
-
- os.chmod(out_loc, 0o764)
- # print(f"Wrote {os.path.basename(out_loc)}") # Uncomment to debug
+ out_file = Path(out_path).joinpath(file[len(template_prefix):]) # Remove prefix
+ template = Path(directory).joinpath(file)
+
+ content = None
+ with open(template, 'r', encoding="UTF-8") as f:
+ content = f.read()
+ content = content.replace("##__TARGET__##", target.upper()). \
+ replace("##__BOARD__##", board). \
+ replace("##__PROGRAM_FILE__##", program_file). \
+ replace("##__SYMBOL_FILE__##", symbol_file). \
+ replace("##__M4_OCD_INTERFACE_FILE__##", m4_ocd_interface_file). \
+ replace("##__M4_OCD_TARGET_FILE__##", m4_ocd_target_file). \
+ replace("##__RV_OCD_INTERFACE_FILE__##", rv_ocd_interface_file). \
+ replace("##__RV_OCD_TARGET_FILE__##", rv_ocd_target_file). \
+ replace("\"##__I_PATHS__##\"", i_paths_parsed). \
+ replace("\"##__DEFINES__##\"", defines_parsed). \
+ replace("\"##__V_PATHS__##\"", v_paths_parsed). \
+ replace("##__V_ARM_GCC__##", v_arm_gcc). \
+ replace("##__V_XPACK_GCC__##", v_xpack_gcc). \
+ replace("##__OCD_PATH__##", ocd_path). \
+ replace("##__ARM_GCC_PATH__##", arm_gcc_path). \
+ replace("##__XPACK_GCC_PATH__##", xpack_gcc_path). \
+ replace("##__MAKE_PATH__##", make_path)
+
+ write = True
+ if out_file.exists():
+ if not overwrite or compare_content(content, out_file):
+ write = False
+
+ if write:
+ with open(out_file, "w+", encoding="UTF-8") as f:
+ f.write(content)
+ os.chmod(out_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)
+ if out_file not in updated:
+ updated.append(out_file)
+
+ # print(f"Wrote {os.path.basename(out_loc)}") # Uncomment to debug
else:
# There is a non-template file to copy
- shutil.copy(os.path.join(directory, file), out_path)
- os.chmod(out_path, 0o764)
- #print(f"Wrote {os.path.basename(file)}") # Uncomment to debug
-
-@time_me
-def populate_maximsdk(target_os, maxim_path, overwrite=True):
- # Copy readme into template directory
- shutil.copy("readme.md", str(Path("MaximSDK/Template/.vscode/")))
-
- print(f"Scanning {maxim_path}...")
-
- # Check for cache file
- cachefile = Path(maxim_path).joinpath(".cache").joinpath("msdk")
-
- if (cachefile.exists()):
- print("Loading from cache file...")
- sdk = SDK.thaw(cachefile)
- else:
- sdk = SDK.from_search(maxim_path)
- sdk.freeze(cachefile)
-
- count = 0
- for example in sdk.examples:
- #print(f"Generating VSCode-Maxim project for {example.path} ...")
-
- # Common options
- _path = example.path
- _target = example.target.name
- _board = example.target.boards[0].name # Default to first board in list
- for b in example.target.boards:
- # Use EvKit_V1 if possible.
- # Some boards modify EvKit_V1 (ex: QN_EvKit_V1)
- if "EvKit_V1" in b.name: _board = b.name
-
- _program_file="${config:project_name}-combined.elf" if example.riscv else defaults["PROGRAM_FILE"]
- _symbol_file="${config:project_name}.elf" if example.riscv else defaults["SYMBOL_FILE"]
- _ipaths = [] + defaults["C_CPP.DEFAULT.INCLUDEPATH"]
- _vpaths = [] + defaults["C_CPP.DEFAULT.BROWSE.PATH"]
-
- # Add include and browse paths for the libraries that this example uses
- for l in example.libs:
- for ipath in l.get_ipaths(example.target.name):
- _ipaths.append(
- str(ipath.as_posix()).
- replace(sdk.maxim_path.as_posix(), "${config:MAXIM_PATH}").
- replace(example.target.name, "${config:target}")
- )
-
- for vpath in l.get_vpaths(example.target.name):
- _vpaths.append(
- str(vpath.as_posix()).
- replace(sdk.maxim_path.as_posix(), "${config:MAXIM_PATH}").
- replace(example.target.name, "${config:target}")
- )
-
- # Linux OpenOCD .cfg files are case senstive. Need to hard-code a lowercase value.
- _m4_ocd_target_file = f"{str.lower(example.target.name)}.cfg" if target_os == "Linux" else defaults["M4_OCD_TARGET_FILE"]
-
- # RPi Tools
- if target_os == "RPi":
- _arm_gcc_path = "${config:MAXIM_PATH}/Tools/GNUTools/gcc-arm-none-eabi/${config:v_Arm_GCC}"
- _xpack_gcc_path = "${config:MAXIM_PATH}/Tools/xPack/riscv-none-embed-gcc/${config:v_xPack_GCC}"
- _v_arm_gcc = "10.3.1"
- _v_xpack_gcc = "10.2.0-1.2"
- else:
- _arm_gcc_path = defaults["ARM_GCC_PATH"]
- _xpack_gcc_path = defaults["XPACK_GCC_PATH"]
- _v_arm_gcc = defaults["V_ARM_GCC"]
- _v_xpack_gcc = defaults["V_XPACK_GCC"]
-
- create_project(
- _path,
- _target,
- _board,
- program_file=_program_file,
- symbol_file=_symbol_file,
- i_paths=_ipaths,
- v_paths=_vpaths,
- m4_ocd_target_file=_m4_ocd_target_file,
- arm_gcc_path=_arm_gcc_path,
- xpack_gcc_path=_xpack_gcc_path,
- v_arm_gcc=_v_arm_gcc,
- v_xpack_gcc=_v_xpack_gcc
- )
-
- count += 1
-
- print(f"Done! Created {count} projects.")
+ in_file = Path(directory).joinpath(file)
+ out_file = Path(out_path).joinpath(file)
+
+ write = True
+ if out_file.exists():
+ if not overwrite or (hash_file(in_file) == hash_file(out_file)):
+ write = False
+
+ if write:
+ shutil.copy(in_file, out_path)
+ os.chmod(out_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)
+ if out_file not in updated:
+ updated.append(out_file)
+ # print(f"Wrote {os.path.basename(file)}") # Uncomment to debug
+
+ return (len(updated) > 0)
\ No newline at end of file
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/flash.gdb b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/flash.gdb
index 2d86f86..fc627ae 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/flash.gdb
+++ b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/flash.gdb
@@ -5,3 +5,11 @@ define flash_m4
compare-sections
monitor reset halt
end
+
+define flash_m4_run
+ set architecture armv7e-m
+ target remote | openocd -c "gdb_port pipe;log_output flash.log" -s $arg0/scripts -f interface/$arg1 -f target/$arg2 -c "init; reset halt"
+ load
+ compare-sections
+ monitor resume
+end
\ No newline at end of file
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/launch.json b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/launch.json
old mode 100644
new mode 100755
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/tasks.json b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/tasks.json
index 5eef671..3951f35 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/tasks.json
+++ b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/Inject/.vscode/tasks.json
@@ -26,25 +26,56 @@
"label": "flash",
"type": "shell",
"command": "arm-none-eabi-gdb",
+ "args": [
+ "--cd=\"${workspaceFolder}\"",
+ "--se=\"build/${config:program_file}\"",
+ "--symbols=build/${config:symbol_file}",
+ "-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
+ "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--batch"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "dependsOn":["build"]
+ },
+ {
+ "label": "flash & run",
+ "type": "shell",
+ "command": "arm-none-eabi-gdb",
"args": [
"--cd=\"${workspaceFolder}\"",
"--se=\"build/${config:program_file}\"",
"--symbols=build/${config:symbol_file}",
"-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
- "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--ex=\"flash_m4_run ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
"--batch"
],
"group": "build",
"problemMatcher": [],
"dependsOn":["build"]
},
+ {
+ "label": "erase flash",
+ "type": "shell",
+ "command": "openocd",
+ "args": [
+ "-s", "${config:OCD_path}/scripts",
+ "-f", "interface/${config:M4_OCD_interface_file}",
+ "-f", "target/${config:M4_OCD_target_file}",
+ "-c", "\"init; reset halt; max32xxx mass_erase 0;\"",
+ "-c", "exit"
+ ],
+ "group":"build",
+ "problemMatcher": [],
+ "dependsOn":[]
+ },
{
"label": "openocd (m4)",
"type": "shell",
"command": "openocd",
"args": [
"-s",
- "${config:MAXIM_PATH}/Tools/OpenOCD/scripts",
+ "${config:OCD_path}/scripts",
"-f",
"interface/${config:M4_OCD_interface_file}",
"-f",
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/flash.gdb b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/flash.gdb
index 2d86f86..fc627ae 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/flash.gdb
+++ b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/flash.gdb
@@ -5,3 +5,11 @@ define flash_m4
compare-sections
monitor reset halt
end
+
+define flash_m4_run
+ set architecture armv7e-m
+ target remote | openocd -c "gdb_port pipe;log_output flash.log" -s $arg0/scripts -f interface/$arg1 -f target/$arg2 -c "init; reset halt"
+ load
+ compare-sections
+ monitor resume
+end
\ No newline at end of file
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/launch.json b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/launch.json
old mode 100644
new mode 100755
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/tasks.json b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/tasks.json
index 5eef671..3951f35 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/tasks.json
+++ b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/New_Project/.vscode/tasks.json
@@ -26,25 +26,56 @@
"label": "flash",
"type": "shell",
"command": "arm-none-eabi-gdb",
+ "args": [
+ "--cd=\"${workspaceFolder}\"",
+ "--se=\"build/${config:program_file}\"",
+ "--symbols=build/${config:symbol_file}",
+ "-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
+ "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--batch"
+ ],
+ "group": "build",
+ "problemMatcher": [],
+ "dependsOn":["build"]
+ },
+ {
+ "label": "flash & run",
+ "type": "shell",
+ "command": "arm-none-eabi-gdb",
"args": [
"--cd=\"${workspaceFolder}\"",
"--se=\"build/${config:program_file}\"",
"--symbols=build/${config:symbol_file}",
"-x=\"${workspaceFolder}/.vscode/flash.gdb\"",
- "--ex=\"flash_m4 ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
+ "--ex=\"flash_m4_run ${config:OCD_path} ${config:M4_OCD_interface_file} ${config:M4_OCD_target_file}\"",
"--batch"
],
"group": "build",
"problemMatcher": [],
"dependsOn":["build"]
},
+ {
+ "label": "erase flash",
+ "type": "shell",
+ "command": "openocd",
+ "args": [
+ "-s", "${config:OCD_path}/scripts",
+ "-f", "interface/${config:M4_OCD_interface_file}",
+ "-f", "target/${config:M4_OCD_target_file}",
+ "-c", "\"init; reset halt; max32xxx mass_erase 0;\"",
+ "-c", "exit"
+ ],
+ "group":"build",
+ "problemMatcher": [],
+ "dependsOn":[]
+ },
{
"label": "openocd (m4)",
"type": "shell",
"command": "openocd",
"args": [
"-s",
- "${config:MAXIM_PATH}/Tools/OpenOCD/scripts",
+ "${config:OCD_path}/scripts",
"-f",
"interface/${config:M4_OCD_interface_file}",
"-f",
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/readme.md b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/readme.md
index 22f1558..4cce59b 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/readme.md
+++ b/installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim/readme.md
@@ -56,7 +56,7 @@ The project folders in this repo have the following dependencies:
{
// There may be other settings up here...
- "MAXIM_PATH":"C:/MaximSDK",
+ "MAXIM_PATH":"C:/MaximSDK", // Only use forward slahes '/' when setting this path!
"update.mode": "manual",
"extensions.autoUpdate": false,
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/meta/installscript.js b/installer/com.maximintegrated.dist.vscodemaxim/meta/installscript.js
index 8fd3678..0fa69b6 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/meta/installscript.js
+++ b/installer/com.maximintegrated.dist.vscodemaxim/meta/installscript.js
@@ -23,7 +23,7 @@ Component.prototype.createOperations = function()
Component.prototype.installationFinished = function()
{
- var tag = "v1.4.2";
+ var tag = "v1.4.3";
var tag_url = "https://github.com/MaximIntegratedTechSupport/VSCode-Maxim/tree/" + tag;
var release_url = "https://github.com/MaximIntegratedTechSupport/VSCode-Maxim/releases/tag/" + tag;
diff --git a/installer/com.maximintegrated.dist.vscodemaxim/meta/package.xml b/installer/com.maximintegrated.dist.vscodemaxim/meta/package.xml
index 36129e6..afc42dc 100644
--- a/installer/com.maximintegrated.dist.vscodemaxim/meta/package.xml
+++ b/installer/com.maximintegrated.dist.vscodemaxim/meta/package.xml
@@ -1,9 +1,9 @@
Visual Studio Code Support
Project files, templates, and documentation for integrating Visual Studio Code and the MaximSDK. Example projects come pre-populated with .vscode project folders, and this package contains information on how to use them. It installs to "Tools/VSCode-Maxim".
- 2022-05-16
+ 2022-08-01
net.sourceforge.openocd, net.launchpad.gcc.arm.embedded, net.launchpad.gcc.riscv.embedded, com.maximintegrated.libraries.periphdrivers
- 1.4.2
+ 1.4.3
1
\ No newline at end of file
diff --git a/maintain.py b/maintain.py
index 006f1f7..c696bdd 100644
--- a/maintain.py
+++ b/maintain.py
@@ -39,17 +39,15 @@
import shutil
import argparse
from pathlib import Path
-from dataclasses import dataclass
-from utils import time_me
-from generate import populate_maximsdk
from datetime import date
curplatform = platform.system() # Get OS
def log(string, file):
- print(string)
- file.write(f"{string}\n")
- file.flush()
+ with open(file, "a") as f:
+ print(string)
+ f.write(f"{string}\n")
+ f.flush()
def timestamp():
now = time.localtime()
@@ -70,17 +68,9 @@ def wrapper(*args, **kwargs):
return wrapper
-# Run powershell command. On linux, run a shell command
@time_me
-def ps(cmd, env=None):
- if curplatform == 'Linux':
- if env is None: result = run(cmd, capture_output=True, shell=True)
- else: result = run(cmd, env=env, capture_output=True, shell=True)
- elif curplatform == 'Windows':
- if env is None: result = run(["powershell", cmd], capture_output=True)
- else: result = run(["powershell", cmd], env=env, capture_output=True)
-
- return result
+def run_cmd(*args, **kwargs):
+ return run(*args, **kwargs)
def sync():
# Inject .vscode folder into example projects
@@ -118,7 +108,7 @@ def release(version):
# Copy in to installer package
print("Updating installer package...")
- shutil.copytree(Path("./Releases/VSCode-Maxim-v140"), Path("./installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim"), dirs_exist_ok=True)
+ shutil.copytree(r_dir, Path("./installer/com.maximintegrated.dist.vscodemaxim/data/Tools/VSCode-Maxim"), dirs_exist_ok=True)
# Update version # and release date in package.xml
# ---
@@ -159,21 +149,21 @@ def release(version):
# Tests cleaning and compiling example projects for target platforms. If no targets, boards, projects, etc. are specified then it will auto-detect
def test(maxim_path, targets=None, boards=None, projects=None):
- maxim_path = Path(maxim_path).resolve().as_posix()
+ maxim_path = Path(maxim_path).resolve()
env = os.environ.copy()
# Simulate the VS Code terminal by appending to the Path
- if curplatform == 'Linux':
- env["PATH"] = f"{maxim_path}/Tools/GNUTools/10.3/bin:{maxim_path}/Tools/xPack/riscv-none-embed-gcc/10.2.0-1.2/bin:" + env["PATH"]
- elif curplatform == 'Windows':
- env["PATH"] = f"{maxim_path}/Tools/GNUTools/10.3/bin;{maxim_path}/Tools/xPack/riscv-none-embed-gcc/10.2.0-1.2/bin;" + env["PATH"]
+ # if curplatform == 'Linux':
+ # env["PATH"] = f"{maxim_path.as_posix()}/Tools/GNUTools/10.3/bin:{maxim_path.as_posix()}/Tools/xPack/riscv-none-embed-gcc/10.2.0-1.2/bin:" + env["PATH"]
+ # elif curplatform == 'Windows':
+ # env["PATH"] = f"{maxim_path.as_posix()}/Tools/GNUTools/10.3/bin;{maxim_path.as_posix()}/Tools/xPack/riscv-none-embed-gcc/10.2.0-1.2/bin;{maxim_path.as_posix()}/Tools/MSYS2/usr/bin;" + env["PATH"]
- LOG_DIR = os.getcwd()
+ log_dir = Path(os.getcwd()).joinpath("buildlogs")
# Create log file
- try: os.mkdir(f"{LOG_DIR}/buildlogs")
- except FileExistsError: pass
- logfile = open(f"{LOG_DIR}/test.log", 'w')
+ if not log_dir.exists():
+ os.mkdir(log_dir)
+ logfile = log_dir.joinpath("test.log")
# Log system info
log(timestamp(), logfile)
@@ -197,9 +187,10 @@ def test(maxim_path, targets=None, boards=None, projects=None):
targets = sorted(targets)
# Create subfolders for target-specific logfiles
- for t in targets:
- try: os.mkdir(f"{LOG_DIR}/buildlogs/{t}")
- except FileExistsError: pass
+ for t in targets:
+ sub_dir = log_dir.joinpath(t)
+ if not sub_dir.exists():
+ os.mkdir(sub_dir)
# Track failed projects for end summary
failed = []
@@ -212,9 +203,9 @@ def test(maxim_path, targets=None, boards=None, projects=None):
# Get list of supported boards for this target.
if boards is None:
boards = []
- for dirpath, subdirs, items in os.walk(f"{maxim_path}/Libraries/Boards/{target}"):
- if "board.mk" in items and curplatform == 'Linux': boards.append(dirpath.split('/')[-1]) # Linux
- elif "board.mk" in items and curplatform == 'Windows': boards.append(dirpath.split('\\')[-1]) # Board string will be the last folder in the directory path # Windows
+ for dirpath, subdirs, items in os.walk(maxim_path.joinpath("Libraries", "Boards", target)):
+ if "board.mk" in items:
+ boards.append(Path(dirpath).name)
log(f"[BOARDS] Detected {boards}", logfile)
@@ -227,9 +218,9 @@ def test(maxim_path, targets=None, boards=None, projects=None):
# Get list of examples for this target. If a Makefile is in the root directory it's an example.
if projects is None:
projects = []
- for dirpath, subdirs, items in os.walk(f"{maxim_path}/Examples/{target}"):
- if 'Makefile' in items:
- projects.append(dirpath)
+ for dirpath, subdirs, items in os.walk(maxim_path.joinpath("Examples", target)):
+ if 'Makefile' in items and ("main.c" in items or "project.mk" in items):
+ projects.append(Path(dirpath))
log(f"[PROJECTS] Detected {projects}", logfile)
@@ -241,20 +232,19 @@ def test(maxim_path, targets=None, boards=None, projects=None):
# Test each project
for project in projects:
- if curplatform == 'Linux': project_stripped = project.split('/')[-1] # Linux
- elif curplatform == 'Windows': project_stripped = project.split('\\')[-1] # Windows
+ project_name = project.name
+ print(project_name)
log("---------------------", logfile)
- log(f"[{target}]\t[{project_stripped}]", logfile)
- os.chdir(project) # Need to us os.chdir to set working directory of subprocesses
+ log(f"[{target}]\t[{project_name}]", logfile)
for board in boards:
- buildlog = f"{target}_{board}_{project_stripped}.log"
+ buildlog = f"{target}_{board}_{project_name}.log"
success = True
# Test build (make all)
- build_cmd = f"make all TARGET={target} MAXIM_PATH={maxim_path} BOARD={board} MAKE=make"
- res = ps(build_cmd, env=env) # Run build command
+ build_cmd = f"make -r -j 8 all TARGET={target} MAXIM_PATH={maxim_path.as_posix()} BOARD={board} MAKE=make"
+ res = run_cmd(build_cmd, env=env, cwd=project, shell=True, capture_output=True, encoding="utf-8") # Run build command
# Error check build command
if res.returncode != 0:
@@ -263,32 +253,31 @@ def test(maxim_path, targets=None, boards=None, projects=None):
log(f"{timestamp()}[{board}] --- [BUILD]\t[FAILED] Return code {res.returncode}. See buildlogs/{buildlog}", logfile)
# Log detailed output to separate output file
- with open(f"{LOG_DIR}/buildlogs/{target}/{buildlog}", 'w') as f:
+ with open(log_dir.joinpath(target, buildlog), 'w') as f:
f.write("===============\n")
f.write(timestamp() + '\n')
f.write(f"[PROJECT] {project}\n")
f.write(f"[BOARD] {board}\n")
f.write(f"[BUILD COMMAND] {build_cmd}\n")
f.write("===============\n")
- for line in str(res.stdout + res.stderr, encoding="ASCII").splitlines():
- f.write(line + '\n')
+ f.write(res.stdout + res.stderr)
else: log(f"{timestamp()}[{board}] --- [BUILD]\t[SUCCESS] {round(duration, 4)}s", logfile)
# Test clean (make clean)
clean_cmd = f"make distclean TARGET={target} MAXIM_PATH={maxim_path} BOARD={board} MAKE=make"
- res = ps(clean_cmd, env=env) # Run clean command
+ res = run_cmd(clean_cmd, env=env, cwd=project, shell=True, capture_output=True, encoding="utf-8") # Run clean command
# Error check clean command
if res.returncode != 0:
- log(f"{timestamp()}[{board}] --- [CLEAN]\t[SUCCESS] {str(res.stderr, encoding='ASCII')}", logfile)
+ log(f"{timestamp()}[{board}] --- [CLEAN]\t[SUCCESS] {res.stderr}", logfile)
success = False
else: log(f"{timestamp()}[{board}] --- [CLEAN]\t[SUCCESS] {round(duration, 4)}s", logfile)
# Add any failed projects to running list
project_info = {
"target":target,
- "project":project_stripped,
+ "project":project_name,
"board":board,
"path":project,
"logfile":f"buildlogs/{buildlog}"
@@ -314,6 +303,11 @@ def test(maxim_path, targets=None, boards=None, projects=None):
sync_parser = cmd_parser.add_parser("sync", help="Sync all .vscode project folders")
+test_parser = cmd_parser.add_parser("test", help="Run a build test of the SDK.")
+test_parser.add_argument("--targets", type=str, nargs="+", required=False, help="Target microcontrollers to test.")
+test_parser.add_argument("--boards", type=str, nargs="+", required=False, help="Boards to test. Should match the BSP folder-name exactly.")
+test_parser.add_argument("--projects", type=str, nargs="+", required=False, help="Examples to populate. Should match the example's folder name.")
+
if __name__ == "__main__":
args = parser.parse_args()
@@ -330,7 +324,10 @@ def test(maxim_path, targets=None, boards=None, projects=None):
exit()
if args.cmd == "release":
- release(args.version, args.maxim_path)
+ release(args.version)
elif args.cmd == "sync":
- sync()
\ No newline at end of file
+ sync()
+
+ elif args.cmd == "test":
+ test(args.maxim_path, targets=args.targets, boards=args.boards, projects=args.projects)
diff --git a/readme.md b/readme.md
index 22f1558..4cce59b 100644
--- a/readme.md
+++ b/readme.md
@@ -56,7 +56,7 @@ The project folders in this repo have the following dependencies:
{
// There may be other settings up here...
- "MAXIM_PATH":"C:/MaximSDK",
+ "MAXIM_PATH":"C:/MaximSDK", // Only use forward slahes '/' when setting this path!
"update.mode": "manual",
"extensions.autoUpdate": false,
diff --git a/sdk.py b/sdk.py
deleted file mode 100644
index 9aa1c10..0000000
--- a/sdk.py
+++ /dev/null
@@ -1,322 +0,0 @@
-"""
-/*******************************************************************************
-* Copyright (C) 2022 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-"""
-
-from dataclasses import dataclass
-from typing import Generator
-from utils import *
-import json
-import pickle
-import re
-import os
-from copy import *
-
-def get_baseitems(g: Generator):
- """
- Get a list of items inside of a generator. Returns base string names only, ie. "myfile.txt" or "Examples" for a directory.
-
- Used to simplify searching for sub-items so that statements like "if i in get_baseitems(some generator/list of paths): ..." can be written more easily
- """
- return list(map(lambda i: i.name, g))
-
-@dataclass
-class Target():
- name: str
- boards: list
-
-@dataclass
-class Adapter():
- name: str
- cfg_file: Path
-
-@dataclass
-class Board():
- name: str
- target: Target
- adapters: list
-
-@dataclass
-class Library():
- name: str
- path: Path
- ipaths: tuple
- vpaths: tuple
- whitelist: bool
- targets: tuple
-
- def from_libinfo(filepath):
- """
- Returns a Library instance instantiated from a json info file
- """
- filepath = Path(filepath)
- with open(filepath, "r") as f:
- libinfo = json.load(f)
- keys = libinfo.keys()
- assert "name" in keys and "ipaths" in keys and "vpaths" in keys and "whitelist" in keys, f"{filepath} Bad libinfo.json file!"
-
- _name = libinfo["name"]
- _path = filepath.parent
- _ipaths = tuple(i for i in libinfo["ipaths"])
- _vpaths = tuple(i for i in libinfo["vpaths"])
- _whitelist = libinfo["whitelist"]
- _targets = tuple(i for i in libinfo["targets"]) if "targets" in keys else None
-
- return Library(
- _name,
- _path,
- _ipaths,
- _vpaths,
- _whitelist,
- _targets
- )
-
- def get_ipaths(self, target=None):
- """
- Returns a tuple of include paths for the library.
- If "target" is specified, the return generator will include paths specific to that target in addition to the common paths.
- If the library is whitelisted (Library.whitelist is True), "target" is specified, and there is no matching
- entry in the library, this function will return an empty tuple.
- """
- target_info = None
-
- if self.whitelist is True and target is None:
- return () # Return empty tuple
- else:
- _ipaths = list(map(lambda p: self.path.joinpath(p), self.ipaths)) # Common paths
-
- if target is not None and self.targets is not None: # Search for match
- for i in self.targets:
- if ("name" in i.keys() and i["name"] == target):
- target_info = i
-
- if target_info is not None and "ipaths" in target_info.keys():
- _ipaths += list(map(lambda p: self.path.joinpath(p), target_info["ipaths"])) # Target-specific paths
-
- return tuple(_ipaths)
-
- def get_hfiles(self, target=None):
- hfiles = []
- for ipath in self.get_ipaths(target):
- hfiles += ipath.rglob("*.h")
- return tuple(get_baseitems(hfiles))
-
- def get_vpaths(self, target: str):
- """
- Returns a tuple of browse paths for the library.
- If "target" is specified, the return generator will include paths specific to that target in addition to the common paths.
- If the library is whitelisted (Library.whitelist is True), "target" is specified, and there is no matching
- entry in the library, this function will return an empty tuple.
- """
- target_info = None
-
- if self.whitelist is True and target is None:
- return () # Return empty tuple
- else:
- _vpaths = list(map(lambda p: self.path.joinpath(p), self.vpaths)) # Common paths
-
- if target is not None and self.targets is not None: # Search for match
- for i in self.targets:
- if ("name" in i.keys() and i["name"] == target):
- target_info = i
-
- if target_info is not None and "vpaths" in target_info.keys():
- _vpaths += list(map(lambda p: self.path.joinpath(p), target_info["vpaths"])) # Target-specific paths
-
- return tuple(_vpaths)
-
- def get_vfiles(self, target):
- vfiles = []
- for vpath in self.get_vpaths(target):
- vfiles += vpath.rglob("*.c")
- return tuple(get_baseitems(vfiles))
-
-@dataclass
-class Example():
- name: str
- path: Path
- target: Target
- riscv: False
- boards: list
- hfiles: list
- libs: list
-
-class SDK():
- @time_me
- def __init__(self, maxim_path, targets, boards, libs, examples):
- self.maxim_path = Path(maxim_path).absolute()
- self.targets = targets
- self.boards = boards
- self.libs = libs
- self.examples = examples
-
- @time_me
- def from_search(maxim_path):
- # Populate initial info
- maxim_path = Path(maxim_path).absolute()
- (targets, boards) = get_targets_and_boards(maxim_path)
- targets = targets
- boards = boards
- libs = get_libraries(maxim_path)
- examples = get_examples(maxim_path, targets)
-
- # Match examples to libraries
- for e in examples:
- for l in libs:
- lib_hfiles = l.get_hfiles(e.target.name)
- for hfile in e.hfiles:
- if hfile in lib_hfiles and l not in e.libs:
- e.libs.append(l)
-
- return SDK(maxim_path, targets, boards, libs, examples)
-
- @time_me
- def freeze(self, filename):
- if not Path(filename).exists():
- os.mkdir(Path(filename).parent)
-
- with open(filename, "wb") as f:
- pickle.dump(self, f)
-
- @time_me
- def thaw(filename):
- with open(str(filename), "rb") as f:
- tmp = pickle.load(f)
- maxim_path = tmp.maxim_path
- targets = tmp.targets
- boards = tmp.boards
- libs = tmp.libs
- examples = tmp.examples
-
- return SDK(maxim_path, targets, boards, libs, examples)
-
-@time_me
-def get_targets_and_boards(maxim_path):
- maxim_path = Path(maxim_path).absolute()
- boards_dir = maxim_path.joinpath("Libraries", "Boards")
-
- # Detect targets and their supported boards
- targets = []
- boards = []
- for target_dir in boards_dir.iterdir():
- t = Target(target_dir.name, [])
-
- board_dirs = list(target_dir.iterdir())
- if target_dir.joinpath("Include").exists(): board_dirs.remove(target_dir.joinpath("Include"))
- if target_dir.joinpath("Source").exists(): board_dirs.remove(target_dir.joinpath("Source"))
-
- for board_dir in board_dirs:
- b = Board(board_dir.name, t, [])
- adapterinfo_file = board_dir.joinpath("adapterinfo.json")
- if adapterinfo_file.exists():
- with open(adapterinfo_file) as f:
- adapterinfo = json.load(f)
- for a in adapterinfo: b.adapters.append(Adapter(a["name"], a["cfg_file"]))
-
- t.boards.append(b)
- boards.append(b)
-
- targets.append(t)
-
- return (targets, boards)
-
-@time_me
-def get_examples(maxim_path, targets: list):
- maxim_path = Path(maxim_path).absolute()
- examples_dir = maxim_path.joinpath("Examples")
-
- # Locate examples for each target
- examples = []
- for t in targets:
- assert type(t) is Target
- for Makefile in examples_dir.joinpath(t.name).rglob("Makefile"):
- e = Example(
- Makefile.parent.name,
- Makefile.parent,
- t,
- "Makefile.RISCV" in get_baseitems(Makefile.parent.iterdir()),
- [], # Filling these in later...
- [],
- []
- )
-
- exampleinfo_file = Makefile.parent.joinpath("exampleinfo.json")
-
- if exampleinfo_file.exists():
- with open(exampleinfo_file):
- exampleinfo = json.load(exampleinfo_file)
- e.boards = t.boards if exampleinfo["boards"] == "all" else exampleinfo["boards"]
-
- # Get all non-standard header files used in the example source code
- for cfile in e.path.rglob("*.c"):
- hfiles = get_hfiles(cfile)
- for hfile in hfiles:
- if hfile not in e.hfiles:
- e.hfiles.append(hfile)
-
- examples.append(e)
-
- return tuple(examples)
-
-def get_hfiles(filepath):
- hfiles = []
- try:
- with open(filepath, "r") as c:
- lines = c.readlines()
- for l in lines:
- if "#include" in l:
- # Search for non-standard #includes - ie. #include "myheader.h"
- # [\"] means character matching "
- # \S+ is equivalent to %s in scanf
- # Use raw string as recommended by Python docs (r"...")
- m = re.search(r"[\"]\S+.h[\"]", l)
- if m is not None:
- mstring = l[m.start() + 1:m.end() - 1] # strip quotes
- if mstring not in hfiles: hfiles.append(mstring)
- except:
- print(f"Failed to get header files from {filepath}")
-
- return tuple(hfiles)
-
-@time_me
-def get_libraries(maxim_path):
- maxim_path = Path(maxim_path).absolute()
- libs_path = maxim_path.joinpath("Libraries")
-
- libs = []
-
- for lib_path in libs_path.iterdir():
- info_file = lib_path.joinpath("libinfo.json")
- if info_file.exists():
- libs.append(Library.from_libinfo(info_file))
-
- return tuple(libs)
\ No newline at end of file
diff --git a/utils.py b/utils.py
index c595b54..dca96e9 100644
--- a/utils.py
+++ b/utils.py
@@ -32,10 +32,38 @@
*******************************************************************************/
"""
-from dataclasses import dataclass
+from collections.abc import MutableMapping
+from string import Template
import json
-from dataclasses import dataclass
from pathlib import Path
+import hashlib
+import os
+
+class UpperDict(MutableMapping):
+ def __init__(self, *args, **kwargs):
+ self.d = dict()
+ self.update(dict(*args, **kwargs))
+
+ def _parse_key(self, key):
+ return str(key).upper().replace(".", "_")
+
+ def __setitem__(self, key, value) -> None:
+ self.d[self._parse_key(key)] = value
+
+ def __getitem__(self, key):
+ return self.d[self._parse_key(key)]
+
+ def __delitem__(self, key) -> None:
+ del self.d[self._parse_key(key)]
+
+ def __iter__(self):
+ return iter(self.d)
+
+ def __len__(self):
+ return len(self.d)
+
+class MSDKTemplate(Template):
+ delimiter = "##__"
def parse_json(filename):
"""
@@ -43,13 +71,7 @@ def parse_json(filename):
"""
f = open(filename, "r")
d = json.load(f)
-
- # Convert key values to uppercase for easier template parsing
- keys = list(d.keys()) # Keys are changing on the fly, so can't use a view object
- for k in keys:
- d[k.upper()] = d.pop(k)
-
- return d
+ return UpperDict(d)
# Timer wrapper function
import time
@@ -64,4 +86,43 @@ def wrapper(*args, **kwargs):
return res
- return wrapper
\ No newline at end of file
+ return wrapper
+
+def hash(val):
+ if not isinstance(val, bytes):
+ val = bytes(val, encoding="utf-8")
+ return hashlib.sha1(val).digest()
+
+def hash_file(filepath):
+ return hash(open(Path(filepath), 'rb').read())
+
+def hash_folder(folderpath) -> bytes:
+ folderpath = Path(folderpath)
+ result = b''
+ for dir, subdirs, files in os.walk(folderpath):
+ for f in sorted(files):
+ file_path = Path(dir).joinpath(f)
+ relative_path = file_path.relative_to(folderpath)
+
+ result = hash(result + hash_file(file_path) + bytes(str(relative_path), encoding="utf-8"))
+
+ return result
+
+def compare_content(content: str, file: Path) -> bool:
+ """
+ Compare the 'content' string to the existing content in 'file'.
+
+ It seems that when a file gets written there may be some metadata that is affecting
+ the hash functions. As a result, this function writes 'content' to a temporary file,
+ then checks for equality using the temp file.
+ """
+ if not file.exists():
+ return False
+
+ tmp = file.parent.joinpath("tmp")
+ with open(tmp, "w", encoding='utf-8') as f:
+ f.write(content)
+
+ match = (hash_file(file) == hash_file(tmp))
+ os.remove(tmp)
+ return match
\ No newline at end of file
diff --git a/vscmxm.py b/vscmxm.py
deleted file mode 100644
index 38ad7fc..0000000
--- a/vscmxm.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-/*******************************************************************************
-* Copyright (C) 2022 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************/
-"""
-import argparse
-import platform
-import os
-from generate import *
-
-# Set up command-line args
-# ---
-parser = argparse.ArgumentParser(description="VSCode-Maxim command line tool.")
-
-parser.add_argument("--os", type=str, choices=["Windows", "Linux", "RPi"], help="(Optional) Operating system to generate the project files for. If not specified the script will auto-detect.")
-parser.add_argument("--maxim_path", type=str, help="(Optional) Location of the MaximSDK. If this is not specified then the script will attempt to use the MAXIM_PATH environment variable.")
-
-cmd_parser = parser.add_subparsers(dest="cmd", help="sub-command", required=True)
-
-SDK_parser = cmd_parser.add_parser("SDK", help="Populate a MaximSDK installation's example projects with VS Code project files.")
-
-new_parser = cmd_parser.add_parser("new", help="Create a new VSCode-Maxim project")
-new_parser.add_argument("location", help="Root location of the project to create. The project will be created in a new folder located at /.")
-new_parser.add_argument("name", help="Name of the project. The project will be created in a new folder located at /.")
-new_parser.add_argument("target", help="Target microcontroller for the project", choices=whitelist)
-new_parser.add_argument("board", help="Target board to use for the project.")
-# ---
-
-if __name__ == "__main__":
- args = parser.parse_args()
-
- # Auto-detect OS
- if args.os is None:
- current_os = platform.platform()
- if "Windows" in current_os: args.os = "Windows"
- elif "Linux" in current_os: args.os = "Linux"
- else:
- print(f"{current_os} is not supported at this time.")
- exit()
-
- # Auto-detect MAXIM_PATH
- if args.maxim_path is None:
- # Check environment variable
- print("Checking MAXIM_PATH environment variable..")
- if "MAXIM_PATH" in os.environ.keys():
- args.maxim_path = os.environ["MAXIM_PATH"]
- print(f"MaximSDK located at {args.maxim_path}")
-
- else:
- print("Failed to locate the MaximSDK... Please specify --maxim_path manually.")
- exit()
- else:
- # Parse to abs path
- args.maxim_path = os.path.abspath(args.maxim_path)
-
- # Process command
- if args.cmd == "SDK":
- print(f"Generating .vscode projects for all examples in SDK located at {args.maxim_path}")
- populate_maximsdk(target_os=args.os, maxim_path=args.maxim_path)
-
- elif args.cmd == "new":
- pass
- # TODO: new project generator
-
-
-
\ No newline at end of file