#!/bin/bash # ============================================================================== # setup-vscode-macos.sh # # Rend un projet STM32CubeIDE (genere par STM32CubeMX, toolchain GCC/Makefile) # compilable, flashable et debogable depuis VS Code sur macOS. # # Reutilisable tel quel sur un autre projet STM32CubeIDE : copiez ce script a # la racine du projet (a cote du dossier "gcc/") et lancez-le. # # Ce qu'il fait : # 1. Verifie/installe la toolchain (arm-none-eabi-gcc, GNU make 4.x) # 2. Localise STM32CubeIDE et ses outils embarques (ST-LINK_gdbserver, # STM32CubeProgrammer) # 3. Corrige les incompatibilites macOS connues dans les Makefiles/scripts # de lien generes par CubeMX (mot-cle READONLY, rmdir BSD, --specs) # 4. Si le projet utilise TouchGFX : cree des wrappers Wine (via TouchGFX.app, # qui embarque Wine) pour les outils imageconvert/fontconvert, qui n'ont # pas de version macOS # 5. Signe arm-none-eabi-gdb avec les entitlements necessaires au debogage # sur macOS (cree un certificat de signature de code auto-signe si besoin) # 6. Genere .vscode/tasks.json, c_cpp_properties.json et launch.json # 7. Lance une compilation de test pour valider # # Ce que ce script NE PEUT PAS deviner de maniere fiable (a vos yeux de # verifier si la compilation de test echoue) : # - Des fichiers sources ajoutes au projet APRES la derniere generation du # Makefile par CubeMX (ex: un driver BSP ajoute a la main) : le Makefile # genere peut alors ne pas les lister, meme s'ils apparaissent bien dans # le .cproject de STM32CubeIDE. Si la compilation de test echoue avec des # "undefined reference" ou "No such file or directory", il faudra ajouter # ces fichiers/chemins a la main dans gcc/makefile_ (variables # board_c_files += ... et board_include_paths += ...). # - Le point d'acces SWD (access port) et la strategie de reset a utiliser # pour le debogage : ce script utilise des valeurs par defaut modifiables # en tete de script (DEBUG_ACCESS_PORT, DEBUG_RESET_STRATEGY). Pour un # projet different, verifiez ces valeurs dans un fichier .launch existant # de STM32CubeIDE (dossier STM32CubeIDE/**/*.launch), champs # "com.st.stm32cube.ide.mcu.debug.launch.access_port_id" et # "com.st.stm32cube.ide.mcu.debug.stlink.reset_strategy". # # ============================================================================== set -uo pipefail # ------------------------------------------------------------------------------ # Parametres modifiables # ------------------------------------------------------------------------------ DEBUG_GDB_PORT="61234" DEBUG_ACCESS_PORT="0" # "-m " pour ST-LINK_gdbserver. Mettre 1 si le # projet a une architecture boot+appli en memoire # externe (verifier le .launch existant, voir ci-dessus) DEBUG_CONNECT_UNDER_RESET="1" # 1 = ajoute "-k" (connexion sous reset) GDB_SIGN_IDENTITY="gdb-cert" # ------------------------------------------------------------------------------ # Utilitaires # ------------------------------------------------------------------------------ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$SCRIPT_DIR" STEP=0 log() { STEP=$((STEP+1)); echo ""; echo "[$STEP] $*"; } info() { echo " $*"; } warn() { echo " ATTENTION: $*" >&2; } die() { echo "ERREUR: $*" >&2; exit 1; } # ============================================================================== log "Verification de la toolchain ARM" # ============================================================================== if ! command -v arm-none-eabi-gcc >/dev/null 2>&1; then info "arm-none-eabi-gcc introuvable, installation via Homebrew..." command -v brew >/dev/null 2>&1 || die "Homebrew n'est pas installe (https://brew.sh). Installez-le puis relancez ce script." brew install --cask gcc-arm-embedded 2>/dev/null || brew install arm-none-eabi-gcc || die "Echec de l'installation d'arm-none-eabi-gcc" fi ARM_GCC_PATH="$(command -v arm-none-eabi-gcc)" info "arm-none-eabi-gcc : $ARM_GCC_PATH ($(arm-none-eabi-gcc --version | head -1))" ARM_GDB_PATH="$(command -v arm-none-eabi-gdb || true)" [ -z "$ARM_GDB_PATH" ] && die "arm-none-eabi-gdb introuvable (devrait etre installe avec arm-none-eabi-gcc)" info "arm-none-eabi-gdb : $ARM_GDB_PATH" # ============================================================================== log "Verification de GNU Make 4.x (celui d'Apple, 3.81, est trop ancien)" # ============================================================================== GNU_MAKE="" if make --version 2>/dev/null | head -1 | grep -qE "GNU Make (4|5|6|7|8|9)"; then GNU_MAKE="$(command -v make)" else for candidate in /usr/local/opt/make/libexec/gnubin/make /opt/homebrew/opt/make/libexec/gnubin/make; do [ -x "$candidate" ] && GNU_MAKE="$candidate" && break done if [ -z "$GNU_MAKE" ]; then info "GNU Make recent introuvable, installation via Homebrew (sera nomme 'gmake')..." command -v brew >/dev/null 2>&1 || die "Homebrew n'est pas installe (https://brew.sh)." brew install make || die "Echec de l'installation de make" for candidate in /usr/local/opt/make/libexec/gnubin/make /opt/homebrew/opt/make/libexec/gnubin/make; do [ -x "$candidate" ] && GNU_MAKE="$candidate" && break done fi fi [ -z "$GNU_MAKE" ] && die "Impossible de localiser un GNU Make >= 4.0 apres installation" info "GNU Make utilise : $GNU_MAKE ($("$GNU_MAKE" --version | head -1))" # ============================================================================== log "Localisation du dossier de build GCC du projet" # ============================================================================== GCC_DIR="" for d in "$PROJECT_ROOT/gcc" "$PROJECT_ROOT/GCC" "$PROJECT_ROOT/Gcc"; do [ -d "$d" ] && GCC_DIR="$d" && break done [ -z "$GCC_DIR" ] && die "Dossier 'gcc/' introuvable a la racine du projet ($PROJECT_ROOT). Ce script attend un projet CubeMX genere avec la toolchain 'STM32CubeIDE / Makefile'." info "Dossier de build : $GCC_DIR" mapfile -t SUBMAKEFILES < <(find "$GCC_DIR" -maxdepth 1 -type f \( -iname "makefile_*" \) | sort) TOP_MAKEFILE="$GCC_DIR/Makefile" [ -f "$TOP_MAKEFILE" ] || die "Makefile principal introuvable dans $GCC_DIR" if [ "${#SUBMAKEFILES[@]}" -eq 0 ]; then SUBMAKEFILES=("$TOP_MAKEFILE") fi info "Makefile(s) detecte(s) : ${SUBMAKEFILES[*]}" # ============================================================================== log "Localisation de STM32CubeIDE et de ses outils embarques" # ============================================================================== CUBEIDE_APP="" for d in "/Applications/STMicroelectronics/STM32CubeIDE.app" "/Applications/STM32CubeIDE.app"; do [ -d "$d" ] && CUBEIDE_APP="$d" && break done [ -z "$CUBEIDE_APP" ] && CUBEIDE_APP="$(mdfind "kMDItemFSName == 'STM32CubeIDE.app'" 2>/dev/null | head -1)" [ -z "$CUBEIDE_APP" ] && die "STM32CubeIDE.app introuvable dans /Applications. Installez-le depuis st.com (necessaire pour le flash/debug via ST-Link)." info "STM32CubeIDE : $CUBEIDE_APP" GDBSERVER_BIN="$(find "$CUBEIDE_APP/Contents/Eclipse/plugins" -maxdepth 1 -iname "*stlink-gdb-server*" -type d 2>/dev/null | sort -V | tail -1)/tools/bin/ST-LINK_gdbserver" CUBEPROG_BIN_DIR="$(find "$CUBEIDE_APP/Contents/Eclipse/plugins" -maxdepth 1 -iname "*cubeprogrammer*" -type d 2>/dev/null | sort -V | tail -1)/tools/bin" CUBEPROG_CLI="$CUBEPROG_BIN_DIR/STM32_Programmer_CLI" [ -x "$GDBSERVER_BIN" ] || die "ST-LINK_gdbserver introuvable sous $CUBEIDE_APP" [ -x "$CUBEPROG_CLI" ] || die "STM32_Programmer_CLI introuvable sous $CUBEIDE_APP" info "ST-LINK_gdbserver : $GDBSERVER_BIN" info "STM32_Programmer_CLI: $CUBEPROG_CLI" # ============================================================================== log "Recherche d'un chargeur de memoire externe (.stldr), si applicable" # ============================================================================== EXT_LOADER="$(find "$PROJECT_ROOT" -iname "*.stldr" -maxdepth 3 2>/dev/null | head -1)" if [ -n "$EXT_LOADER" ]; then info "External loader trouve : $EXT_LOADER" EXT_LOADER_ARGS_PROG=(-el "$EXT_LOADER") EXT_LOADER_ARGS_GDB="-el \${workspaceFolder}/$(python3 -c "import os,sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))" "$EXT_LOADER" "$PROJECT_ROOT" 2>/dev/null || echo "$EXT_LOADER")" else info "Aucun external loader trouve (normal si le projet n'utilise pas de memoire externe XSPI/QSPI)." EXT_LOADER_ARGS_PROG=() EXT_LOADER_ARGS_GDB="" fi # ============================================================================== log "Correction des incompatibilites macOS dans les scripts de lien (.ld)" # ============================================================================== LD_FILES=$(find "$PROJECT_ROOT" -iname "*.ld" -not -path "*/STM32CubeIDE/*" 2>/dev/null) FIXED_LD=0 for ld in $LD_FILES; do if grep -q "(READONLY)" "$ld" 2>/dev/null; then sed -i '' 's/ (READONLY)//' "$ld" info "Corrige (mot-cle READONLY, GCC11+ uniquement) : $ld" FIXED_LD=$((FIXED_LD+1)) fi done [ "$FIXED_LD" -eq 0 ] && info "Rien a corriger." # ============================================================================== log "Correction des incompatibilites macOS dans les Makefiles" # ============================================================================== for mk in "${SUBMAKEFILES[@]}" "$TOP_MAKEFILE"; do [ -f "$mk" ] || continue # rmdir --ignore-fail-on-non-empty n'existe pas sur macOS (BSD rmdir) if grep -q -- "--ignore-fail-on-non-empty" "$mk" 2>/dev/null; then sed -i '' -E 's/rmdir --ignore-fail-on-non-empty ([^ ]+)/rmdir \1 2>\/dev\/null || true/' "$mk" info "Corrige (rmdir portable) : $mk" fi # --specs=nosys.specs sans --specs=nano.specs cause des symboles # __sf_fake_stdin/stdout/stderr non resolus avec FreeRTOS if grep -q -- "--specs=nosys.specs" "$mk" 2>/dev/null && ! grep -q -- "--specs=nano.specs" "$mk" 2>/dev/null; then sed -i '' 's/--specs=nosys.specs/--specs=nosys.specs \\\n\t--specs=nano.specs/' "$mk" info "Ajoute --specs=nano.specs au linker : $mk" fi # Ajout d'une branche Darwin pour imageconvert/fontconvert si TouchGFX est utilise if grep -q "imageconvert_executable" "$mk" 2>/dev/null && ! grep -q "UNAME), Darwin" "$mk" 2>/dev/null; then TOUCHGFX_WIN_IMG=$(grep -oE '[A-Za-z0-9_/.-]+/win/imageconvert\.out' "$mk" | head -1) TOUCHGFX_WIN_FONT=$(grep -oE '[A-Za-z0-9_/.-]+/win/fontconvert\.out' "$mk" | head -1) if [ -n "$TOUCHGFX_WIN_IMG" ]; then info "TouchGFX detecte dans $mk - mise en place des wrappers Wine macOS" TOUCHGFX_APP="" for d in "/Applications/STMicroelectronics/TouchGFX.app" "/Applications/TouchGFX.app"; do [ -d "$d" ] && TOUCHGFX_APP="$d" && break done [ -z "$TOUCHGFX_APP" ] && TOUCHGFX_APP="$(mdfind "kMDItemFSName == 'TouchGFX.app'" 2>/dev/null | head -1)" if [ -z "$TOUCHGFX_APP" ] || [ ! -x "$TOUCHGFX_APP/Contents/SharedSupport/wine/bin/wine64" ]; then warn "TouchGFX.app (Designer) introuvable ou non-Wineskin sous /Applications - impossible de generer les wrappers automatiquement." warn "Installez TouchGFX Designer pour macOS depuis st.com, puis relancez ce script." else WRAP_DIR="$GCC_DIR/macos_wine_wrappers" mkdir -p "$WRAP_DIR" WINE64="$TOUCHGFX_APP/Contents/SharedSupport/wine/bin/wine64" WINE_LIBS="$TOUCHGFX_APP/Contents/Frameworks:$TOUCHGFX_APP/Contents/SharedSupport/wine/lib" for pair in "imageconvert:$TOUCHGFX_WIN_IMG" "fontconvert:$TOUCHGFX_WIN_FONT"; do name="${pair%%:*}"; relpath="${pair#*:}" [ -z "$relpath" ] && continue cat > "$WRAP_DIR/$name.sh" << EOF #!/bin/sh # Lance $name.out (Windows) via le Wine embarque dans TouchGFX.app export DYLD_FALLBACK_LIBRARY_PATH="$WINE_LIBS" exec "$WINE64" "$PROJECT_ROOT/$relpath" "\$@" 2>/dev/null EOF chmod +x "$WRAP_DIR/$name.sh" info "Wrapper cree : $WRAP_DIR/$name.sh" done # Insere une branche Darwin juste avant le "else" qui gere Windows/Linux MK_REL_GCC=$(basename "$mk") awk -v wrapdir="$(python3 -c "import os,sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))" "$WRAP_DIR" "$PROJECT_ROOT" 2>/dev/null || echo "gcc/macos_wine_wrappers")" ' /ifeq \(\$\(UNAME\), Linux\)/ { print; infile=1; next } infile && /^else$/ && !inserted { print "else ifeq ($(UNAME), Darwin)" print "imageconvert_executable := " wrapdir "/imageconvert.sh" print "fontconvert_executable := " wrapdir "/fontconvert.sh" inserted=1 } { print } ' "$mk" > "$mk.tmp" && mv "$mk.tmp" "$mk" info "Branche Darwin ajoutee dans $mk" fi fi fi done # ============================================================================== log "Compilation de test" # ============================================================================== ( cd "$GCC_DIR" && "$GNU_MAKE" -j"$(sysctl -n hw.ncpu)" ) BUILD_STATUS=$? if [ "$BUILD_STATUS" -ne 0 ]; then warn "La compilation a echoue. Causes frequentes :" warn " - fichiers sources ajoutes au projet apres la derniere generation du" warn " Makefile (comparez avec STM32CubeIDE/*/. cproject) -> a ajouter a la main" warn " dans gcc/makefile_ (board_c_files += / board_include_paths +=)" warn "Les fichiers .vscode/ seront quand meme generes ; relancez juste le build" warn "depuis VS Code une fois les corrections faites." else info "Compilation reussie." fi # ============================================================================== log "Signature de code pour arm-none-eabi-gdb (necessaire pour deboguer sur macOS)" # ============================================================================== if codesign -dv "$ARM_GDB_PATH" 2>&1 | grep -q "com.apple.security.cs.debugger" 2>/dev/null; then info "Deja signe correctement." elif security find-identity -v -p codesigning 2>/dev/null | grep -q "$GDB_SIGN_IDENTITY"; then info "Certificat '$GDB_SIGN_IDENTITY' deja present, signature de gdb..." cat > /tmp/gdb-entitlement.xml << 'EOF' com.apple.security.cs.debugger com.apple.security.get-task-allow EOF codesign --entitlements /tmp/gdb-entitlement.xml -fs "$GDB_SIGN_IDENTITY" "$ARM_GDB_PATH" else info "Creation d'un certificat de signature de code auto-signe '$GDB_SIGN_IDENTITY'..." info "(macOS va probablement demander votre mot de passe pour lui faire confiance)" KEYCHAIN="$HOME/Library/Keychains/login.keychain-db" openssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes \ -keyout /tmp/gdb-cert.key -out /tmp/gdb-cert.crt \ -subj "/CN=$GDB_SIGN_IDENTITY" \ -addext "basicConstraints=critical,CA:true" \ -addext "keyUsage=critical,digitalSignature,keyCertSign" \ -addext "extendedKeyUsage=critical,codeSigning" >/dev/null 2>&1 openssl pkcs12 -export -out /tmp/gdb-cert.p12 -inkey /tmp/gdb-cert.key -in /tmp/gdb-cert.crt \ -passout pass:temp -legacy >/dev/null 2>&1 security import /tmp/gdb-cert.p12 -k "$KEYCHAIN" -P temp -T /usr/bin/codesign -T /usr/bin/security security add-trusted-cert -p codeSign -k "$KEYCHAIN" /tmp/gdb-cert.crt rm -f /tmp/gdb-cert.key /tmp/gdb-cert.crt /tmp/gdb-cert.p12 cat > /tmp/gdb-entitlement.xml << 'EOF' com.apple.security.cs.debugger com.apple.security.get-task-allow EOF codesign --entitlements /tmp/gdb-entitlement.xml -fs "$GDB_SIGN_IDENTITY" "$ARM_GDB_PATH" \ || warn "La signature a echoue - relancez ce script apres avoir accepte la demande de confiance macOS." fi # ============================================================================== log "Extraction des chemins d'include / defines (pour l'auto-completion VS Code)" # ============================================================================== MAIN_APP_MAKEFILE="${SUBMAKEFILES[-1]}" INCLUDE_PATHS_RAW=$("$GNU_MAKE" -f "$MAIN_APP_MAKEFILE" -C "$GCC_DIR" -p 2>/dev/null | grep -m1 "^include_paths " | sed 's/^include_paths[[:space:]]*:=[[:space:]]*//') DEFINES_RAW=$("$GNU_MAKE" -f "$MAIN_APP_MAKEFILE" -C "$GCC_DIR" -p 2>/dev/null | grep -m1 "^c_compiler_options " | grep -oE '\-D[A-Za-z0-9_]+' | sed 's/^-D//') INCLUDE_JSON="" for p in $INCLUDE_PATHS_RAW; do INCLUDE_JSON="$INCLUDE_JSON \"\${workspaceFolder}/$p\",\n" done DEFINES_JSON="" for d in $DEFINES_RAW; do DEFINES_JSON="$DEFINES_JSON \"$d\",\n" done info "$(echo -e "$INCLUDE_JSON" | grep -c workspaceFolder) chemins d'include et $(echo -e "$DEFINES_JSON" | grep -c '\".*\"') defines extraits." # ============================================================================== log "Detection de la structure du projet (mono-projet ou Boot+Appli)" # ============================================================================== BOOT_ELF="" APPLI_ELF="" if [ -d "$PROJECT_ROOT/Boot" ] && [ -d "$PROJECT_ROOT/Appli" ]; then info "Structure Boot + Appli detectee (architecture avec bootloader externe)." BOOT_ELF=$(find "$PROJECT_ROOT/Boot" -iname "target.elf" 2>/dev/null | head -1) APPLI_ELF=$(find "$PROJECT_ROOT/Appli" -iname "target.elf" 2>/dev/null | head -1) else info "Structure mono-projet detectee." APPLI_ELF=$(find "$PROJECT_ROOT" -iname "target.elf" -not -path "*/STM32CubeIDE/*" 2>/dev/null | head -1) fi [ -z "$BOOT_ELF" ] && [ -d "$PROJECT_ROOT/Boot" ] && BOOT_ELF="Boot/TouchGFX/build/bin/target.elf" [ -z "$APPLI_ELF" ] && APPLI_ELF="$(find "$GCC_DIR/.." -iname "target.elf" -not -path "*/STM32CubeIDE/*" 2>/dev/null | head -1)" BOOT_ELF_REL=${BOOT_ELF#"$PROJECT_ROOT/"} APPLI_ELF_REL=${APPLI_ELF#"$PROJECT_ROOT/"} # ============================================================================== log "Generation des fichiers .vscode/" # ============================================================================== mkdir -p "$PROJECT_ROOT/.vscode" GCC_DIR_REL=${GCC_DIR#"$PROJECT_ROOT/"} # --- c_cpp_properties.json --- { echo "{" echo " \"version\": 4," echo " \"configurations\": [" echo " {" echo " \"name\": \"STM32\"," echo " \"compilerPath\": \"$ARM_GCC_PATH\"," echo " \"cStandard\": \"gnu11\"," echo " \"cppStandard\": \"gnu++14\"," echo " \"intelliSenseMode\": \"linux-gcc-arm\"," echo " \"defines\": [" echo -e "$DEFINES_JSON" | sed '$ s/,$//' echo " ]," echo " \"includePath\": [" echo -e "$INCLUDE_JSON" | sed '$ s/,$//' echo " ]" echo " }" echo " ]" echo "}" } > "$PROJECT_ROOT/.vscode/c_cpp_properties.json" info "Genere : .vscode/c_cpp_properties.json" # --- tasks.json --- RESET_FLAG="" [ "$DEBUG_CONNECT_UNDER_RESET" = "1" ] && RESET_FLAG='"-k",' EXT_LOADER_PROG_ARGS="" [ -n "$EXT_LOADER" ] && EXT_LOADER_PROG_ARGS="\"-el\", \"\${workspaceFolder}/${EXT_LOADER#"$PROJECT_ROOT/"}\"," EXT_LOADER_GDB_ARGS="" [ -n "$EXT_LOADER" ] && EXT_LOADER_GDB_ARGS="-el \${workspaceFolder}/${EXT_LOADER#"$PROJECT_ROOT/"} " cat > "$PROJECT_ROOT/.vscode/tasks.json" << EOF { "version": "2.0.0", "tasks": [ { "label": "Build", "type": "shell", "command": "$GNU_MAKE", "args": ["-j8"], "options": { "cwd": "\${workspaceFolder}/$GCC_DIR_REL" }, "group": { "kind": "build", "isDefault": true }, "problemMatcher": ["\$gcc"], "presentation": { "reveal": "always", "panel": "shared", "clear": true } }, { "label": "Clean", "type": "shell", "command": "$GNU_MAKE", "args": ["clean"], "options": { "cwd": "\${workspaceFolder}/$GCC_DIR_REL" }, "group": "build", "problemMatcher": [] }, { "label": "Flash", "type": "shell", "command": "$CUBEPROG_CLI", "args": [ "-c", "port=SWD", $EXT_LOADER_PROG_ARGS "-w", "\${workspaceFolder}/$APPLI_ELF_REL", "-v", "-rst" ], "group": "none", "problemMatcher": [] }, { "label": "Start ST-LINK GDB Server", "type": "shell", "command": "$GDBSERVER_BIN", "args": [ "-p", "$DEBUG_GDB_PORT", "-l", "1", "-d", "-cp", "$CUBEPROG_BIN_DIR", $EXT_LOADER_PROG_ARGS "-m", "$DEBUG_ACCESS_PORT", $RESET_FLAG "-e" ], "isBackground": true, "problemMatcher": { "pattern": { "regexp": "^(x)(x)\$" }, "background": { "activeOnStart": true, "beginsPattern": "^STMicroelectronics ST-LINK GDB server", "endsPattern": "Waiting for debugger connection|Error in initializing ST-LINK device" } }, "presentation": { "reveal": "always", "panel": "dedicated" } }, { "label": "Stop ST-LINK GDB Server", "type": "shell", "command": "pkill -f ST-LINK_gdbserver || true", "problemMatcher": [], "presentation": { "reveal": "silent" } } ] } EOF # Nettoyage des eventuelles virgules trainantes (arguments optionnels vides) sed -i '' -E 's/,([[:space:]]*\])/\1/' "$PROJECT_ROOT/.vscode/tasks.json" info "Genere : .vscode/tasks.json" if [ -n "$BOOT_ELF_REL" ] && [ -d "$PROJECT_ROOT/Boot" ]; then cat >> /dev/null << 'NOTE' Structure Boot+Appli : deux tasks de flash separees ajoutees ci-dessous en plus. NOTE python3 - "$PROJECT_ROOT/.vscode/tasks.json" "$BOOT_ELF_REL" "$APPLI_ELF_REL" "$CUBEPROG_CLI" "$EXT_LOADER" <<'PYEOF' import json, sys path, boot_elf, appli_elf, cli, extloader = sys.argv[1:6] with open(path) as f: data = json.load(f) extra_args = ["-c", "port=SWD"] if extloader: extra_args += ["-el", "${workspaceFolder}/" + extloader.split("/", 1)[-1] if "/" in extloader else extloader] def flash_task(label, elf_rel): hex_rel = elf_rel.rsplit(".elf", 1)[0] + ".hex" return { "label": label, "type": "shell", "command": cli, "args": extra_args + ["-w", "${workspaceFolder}/" + hex_rel, "-v", "-rst"], "group": "none", "problemMatcher": [] } data["tasks"] = [t for t in data["tasks"] if t["label"] != "Flash"] data["tasks"].insert(2, flash_task("Flash Boot", boot_elf)) data["tasks"].insert(3, flash_task("Flash Appli", appli_elf)) data["tasks"].append({"label": "Flash All (Boot + Appli)", "dependsOrder": "sequence", "dependsOn": ["Flash Boot", "Flash Appli"], "problemMatcher": []}) with open(path, "w") as f: json.dump(data, f, indent=2) PYEOF info "tasks.json adapte pour la structure Boot+Appli (Flash Boot / Flash Appli separes)." fi # --- launch.json --- LAUNCH_CMDS_APPLI='"monitor halt", "load", "tbreak main"' LAUNCH_CMDS_SINGLE='"monitor halt", "load", "tbreak main", "monitor reset"' if [ -n "$BOOT_ELF_REL" ] && [ -d "$PROJECT_ROOT/Boot" ]; then cat > "$PROJECT_ROOT/.vscode/launch.json" << EOF { "version": "0.2.0", "configurations": [ { "name": "Debug Boot", "type": "cortex-debug", "request": "launch", "cwd": "\${workspaceFolder}", "executable": "\${workspaceFolder}/$BOOT_ELF_REL", "servertype": "external", "gdbTarget": "localhost:$DEBUG_GDB_PORT", "gdbPath": "$ARM_GDB_PATH", "overrideLaunchCommands": [$LAUNCH_CMDS_SINGLE], "preLaunchTask": "Start ST-LINK GDB Server", "postDebugTask": "Stop ST-LINK GDB Server" }, { "name": "Debug Appli", "type": "cortex-debug", "request": "launch", "cwd": "\${workspaceFolder}", "executable": "\${workspaceFolder}/$APPLI_ELF_REL", "servertype": "external", "gdbTarget": "localhost:$DEBUG_GDB_PORT", "gdbPath": "$ARM_GDB_PATH", "overrideLaunchCommands": [$LAUNCH_CMDS_APPLI], "preLaunchTask": "Start ST-LINK GDB Server", "postDebugTask": "Stop ST-LINK GDB Server" } ] } EOF info "NOTE : structure Boot+Appli detectee. Workflow de debogage :" info " 1) Lancer 'Debug Boot', attendre le flash, arreter la session" info " 2) Lancer 'Debug Appli', attendre l'arret sur main()" info " 3) Appuyer sur le bouton NRST physique de la carte" info " 4) Cliquer Continue" info " (verifiez ce comportement sur votre projet - certains projets mono-image n'en ont pas besoin)" else cat > "$PROJECT_ROOT/.vscode/launch.json" << EOF { "version": "0.2.0", "configurations": [ { "name": "Debug", "type": "cortex-debug", "request": "launch", "cwd": "\${workspaceFolder}", "executable": "\${workspaceFolder}/$APPLI_ELF_REL", "servertype": "external", "gdbTarget": "localhost:$DEBUG_GDB_PORT", "gdbPath": "$ARM_GDB_PATH", "overrideLaunchCommands": [$LAUNCH_CMDS_SINGLE], "preLaunchTask": "Start ST-LINK GDB Server", "postDebugTask": "Stop ST-LINK GDB Server" } ] } EOF fi info "Genere : .vscode/launch.json" # ============================================================================== log "Termine" # ============================================================================== echo "" echo "Recapitulatif :" echo " - Build : Cmd+Shift+B dans VS Code, ou tache 'Build'" echo " - Flash : Terminal > Run Task > Flash (ou 'Flash Boot'/'Flash Appli')" echo " - Debug : panneau Run and Debug de VS Code" echo "" echo "Extensions VS Code requises (a installer manuellement si absentes) :" echo " - C/C++ (ms-vscode.cpptools)" echo " - Cortex-Debug (marus25.cortex-debug)" echo "" if [ "$BUILD_STATUS" -ne 0 ]; then echo "ATTENTION : la compilation de test a echoue - voir les messages ci-dessus" echo "avant de considerer la configuration comme terminee." fi