diff --git a/install.sh b/install.sh index e09d129..fa7fcb3 100644 --- a/install.sh +++ b/install.sh @@ -82,6 +82,7 @@ source "$SCRIPT_DIR/lib/zellij.sh" source "$SCRIPT_DIR/lib/neovim.sh" source "$SCRIPT_DIR/lib/yazi.sh" source "$SCRIPT_DIR/lib/arduino.sh" +source "$SCRIPT_DIR/lib/renode.sh" source "$SCRIPT_DIR/lib/git.sh" source "$SCRIPT_DIR/lib/scaffold.sh" source "$SCRIPT_DIR/lib/shell-config.sh" @@ -104,6 +105,8 @@ echo " arduino-new my-project uno # scaffold a project" echo " adev # launch Arduino workspace" echo " av # compile in Neovim" echo " au # upload in Neovim" +echo " arduino-sim build/fw.elf # simulate with Renode" +echo " ds # attach debugger to Renode" echo " theme # switch colorscheme" echo "" warn "A reboot is recommended to apply all changes (shell, groups, PATH)." diff --git a/lib/arduino.sh b/lib/arduino.sh index 8e7e274..4ddd61d 100644 --- a/lib/arduino.sh +++ b/lib/arduino.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 7: Arduino CLI + board cores -step "9/11 — Installing Arduino CLI + board cores" +step "9/12 — Installing Arduino CLI + board cores" if $IS_ARCH; then $PKG_INSTALL arduino-cli diff --git a/lib/common.sh b/lib/common.sh index e53cd1e..c39b6ae 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -13,7 +13,7 @@ NC='\033[0m' VERBOSE=true LOG_FILE="/tmp/archduino-install.log" CURRENT_STEP=0 -TOTAL_STEPS=12 +TOTAL_STEPS=13 info() { echo -e "${GREEN}[✓]${NC} $1"; } warn() { echo -e "${YELLOW}[!]${NC} $1"; } @@ -39,7 +39,7 @@ draw_progress() { } begin_quiet_mode() { - $IS_WSL && TOTAL_STEPS=13 + $IS_WSL && TOTAL_STEPS=14 : >"$LOG_FILE" # Save real terminal to fd 3/4, redirect everything else to log @@ -82,9 +82,12 @@ BACKUP_DIR="$HOME/.config/archduino/backups/$(date +%Y%m%d_%H%M%S)" backup_config() { local src="$1" [[ ! -e "$src" ]] && return 0 - mkdir -p "$BACKUP_DIR" - cp -a "$src" "$BACKUP_DIR/" - info "Backed up $(basename "$src") → $BACKUP_DIR/" + # Use parent path to avoid collisions when different sources share a basename + # e.g. ~/.config/nvim and ~/.local/share/nvim both have basename "nvim" + local dest="$BACKUP_DIR${src#"$HOME"}" + mkdir -p "$(dirname "$dest")" + cp -a "$src" "$dest" + info "Backed up ${src/#"$HOME"/\~} → ${dest/#"$HOME"/\~}" } # ── TLS workaround ─────────────────────────────────────────────── diff --git a/lib/fonts.sh b/lib/fonts.sh index ffbda87..10e20aa 100644 --- a/lib/fonts.sh +++ b/lib/fonts.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 2: Nerd Font installation -step "2/11 — Installing Nerd Font" +step "2/12 — Installing Nerd Font" FONT_DIR="$HOME/.local/share/fonts/NerdFonts" FONT_NAME="JetBrainsMono" diff --git a/lib/git.sh b/lib/git.sh index e726210..b543d6b 100644 --- a/lib/git.sh +++ b/lib/git.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 8: Git + Lazygit -step "10/11 — Setting up Git + Lazygit" +step "11/12 — Setting up Git + Lazygit" if $IS_ARCH; then $PKG_INSTALL lazygit diff --git a/lib/neovim.sh b/lib/neovim.sh index 2f65213..90398cd 100644 --- a/lib/neovim.sh +++ b/lib/neovim.sh @@ -1,7 +1,7 @@ #!/bin/bash # Steps 5+6: Neovim + NvChad -step "6/11 — Installing Neovim (latest)" +step "6/12 — Installing Neovim (latest)" NVIM_NEEDED=true if command -v nvim &>/dev/null; then @@ -21,7 +21,7 @@ if $NVIM_NEEDED; then info "Neovim installed: $(nvim --version | head -1)" fi -step "7/11 — Setting up NvChad" +step "7/12 — Setting up NvChad" NVIM_CFG="$HOME/.config/nvim" NVCHAD_FRESH=false @@ -29,7 +29,7 @@ MIGRATED_PLUGINS_DIR="/tmp/archduino-migrated-plugins" rm -rf "$MIGRATED_PLUGINS_DIR" # Files managed by Archduino or LazyVim-specific — skip during migration -SKIP_PLUGINS="gruvbox.lua|theme.lua|lsp.lua|arduino.lua|lspconfig.lua" +SKIP_PLUGINS="gruvbox.lua|theme.lua|lsp.lua|arduino.lua|lspconfig.lua|dap.lua" # ── Detect existing config ────────────────────────────────────── if [[ -d "$NVIM_CFG/lua" ]]; then @@ -94,6 +94,11 @@ if $NVCHAD_FRESH; then info "NvChad starter cloned" fi +# ── Strip starter's nvim-lspconfig block (we use native vim.lsp) ─ +# Also remove configs/ dir — we don't use the legacy lspconfig setup +sed -i '/neovim\/nvim-lspconfig/,/},/d' "$NVIM_CFG/lua/plugins/init.lua" +rm -f "$NVIM_CFG/lua/configs/lspconfig.lua" "$NVIM_CFG/lua/configs/conform.lua" + # ── Restore migrated plugins ───────────────────────────────────── if [[ -d "$MIGRATED_PLUGINS_DIR" ]] && ls "$MIGRATED_PLUGINS_DIR"/*.lua &>/dev/null; then mkdir -p "$NVIM_CFG/lua/plugins" @@ -165,8 +170,67 @@ vim.lsp.enable("clangd") return {} LUA -# Clean up legacy configs/lspconfig.lua if present -rm -f "$NVIM_CFG/lua/configs/lspconfig.lua" +# ── DAP (debug adapter) — for Renode GDB remote debugging ────── +cat >"$NVIM_CFG/lua/plugins/dap.lua" <<'LUA' +return { + { + "mfussenegger/nvim-dap", + keys = { "d" }, + config = function() + local dap = require("dap") + + -- GDB remote adapter (connects to Renode's GDB server) + dap.adapters.gdb_remote = { + type = "executable", + command = vim.fn.executable("arm-none-eabi-gdb") == 1 + and "arm-none-eabi-gdb" + or "gdb-multiarch", + args = { "-i", "dap" }, + } + + -- Default debug configurations for Arduino/embedded + dap.configurations.c = { + { + name = "Attach to Renode (GDB :3333)", + type = "gdb_remote", + request = "attach", + target = "localhost:3333", + cwd = "${workspaceFolder}", + program = function() + return vim.fn.input("ELF path: ", vim.fn.getcwd() .. "/build/", "file") + end, + }, + } + dap.configurations.cpp = dap.configurations.c + dap.configurations.arduino = dap.configurations.c + + -- Breakpoint signs + vim.fn.sign_define("DapBreakpoint", { text = "●", texthl = "DiagnosticError" }) + vim.fn.sign_define("DapStopped", { text = "▶", texthl = "DiagnosticOk", linehl = "DiffAdd" }) + end, + }, + { + "rcarriga/nvim-dap-ui", + dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" }, + keys = { "du" }, + config = function() + local dapui = require("dapui") + dapui.setup() + + -- Auto open/close UI on debug sessions + local dap = require("dap") + dap.listeners.after.event_initialized["dapui_config"] = function() dapui.open() end + dap.listeners.before.event_terminated["dapui_config"] = function() dapui.close() end + dap.listeners.before.event_exited["dapui_config"] = function() dapui.close() end + end, + }, + { + "nvim-neotest/nvim-nio", + lazy = true, + }, +} +LUA + # ── Keymaps ───────────────────────────────────────────────────── cat >"$NVIM_CFG/lua/mappings.lua" <<'LUA' @@ -180,6 +244,15 @@ map("n", "av", "ArduinoVerify", { desc = "Arduino Verify (compi map("n", "au", "ArduinoUpload", { desc = "Arduino Upload" }) map("n", "as", "ArduinoSerial", { desc = "Arduino Serial Monitor" }) map("n", "ai", "ArduinoInfo", { desc = "Arduino Board Info" }) + +-- Debug (DAP) +map("n", "ds", function() require("dap").continue() end, { desc = "Debug Start/Continue" }) +map("n", "db", function() require("dap").toggle_breakpoint() end, { desc = "Debug Toggle Breakpoint" }) +map("n", "dn", function() require("dap").step_over() end, { desc = "Debug Step Over" }) +map("n", "di", function() require("dap").step_into() end, { desc = "Debug Step Into" }) +map("n", "do", function() require("dap").step_out() end, { desc = "Debug Step Out" }) +map("n", "dx", function() require("dap").terminate() end, { desc = "Debug Terminate" }) +map("n", "du", function() require("dapui").toggle() end, { desc = "Debug UI Toggle" }) LUA -info "NvChad configured ($THEME_DISPLAY_NAME + Arduino + LSP)" +info "NvChad configured ($THEME_DISPLAY_NAME + Arduino + LSP + DAP)" diff --git a/lib/packages.sh b/lib/packages.sh index 486a42b..5982516 100644 --- a/lib/packages.sh +++ b/lib/packages.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 1: Base packages -step "1/11 — Installing base packages" +step "1/12 — Installing base packages" if $IS_ARCH; then sudo pacman -Syu --noconfirm diff --git a/lib/renode.sh b/lib/renode.sh new file mode 100644 index 0000000..c3c2ac1 --- /dev/null +++ b/lib/renode.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Step 10: Renode emulator for Arduino simulation with USB HID support + +step "10/12 — Installing Renode emulator" + +# gdb-multiarch is needed for nvim-dap to connect to Renode's GDB server +if $IS_ARCH; then + if ! command -v renode &>/dev/null; then + info "Installing Renode from AUR..." + yay -S --needed --noconfirm renode-bin + else + info "Renode already installed" + fi + $PKG_INSTALL arm-none-eabi-gdb +else + if ! command -v renode &>/dev/null; then + info "Installing Renode..." + RENODE_VERSION=$(curl -ks "https://api.github.com/repos/renode/renode/releases/latest" | jq -r '.tag_name' | sed 's/^v//') + curl -ksSLo /tmp/renode.deb "https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/renode_${RENODE_VERSION}_amd64.deb" + sudo apt install -y /tmp/renode.deb + rm -f /tmp/renode.deb + else + info "Renode already installed" + fi + $PKG_INSTALL gdb-multiarch +fi +info "Renode installed: $(renode --version 2>/dev/null | head -1 || echo 'OK')" + +# ── Renode helper script ───────────────────────────────────────── +# Provides a quick way to launch Renode with a GDB server for a firmware ELF +cat >~/.local/bin/arduino-sim <<'SIMSCRIPT' +#!/bin/bash +set -euo pipefail + +usage() { + echo "Usage: arduino-sim [platform]" + echo "" + echo "Launch Renode with a GDB server for debugging firmware." + echo "Connect nvim-dap or gdb to localhost:3333" + echo "" + echo "Platforms:" + echo " stm32f4 STM32F4 Discovery (default)" + echo " rp2040 Raspberry Pi Pico" + echo " nrf52840 nRF52840 (USB HID capable)" + echo "" + echo "Example:" + echo " arduino-sim build/firmware.elf nrf52840" + exit 1 +} + +[[ $# -lt 1 ]] && usage + +ELF="$1" +PLATFORM="${2:-stm32f4}" + +[[ ! -f "$ELF" ]] && echo "Error: $ELF not found" && exit 1 + +# Map platform to Renode machine definition +case "$PLATFORM" in + stm32f4) + RENODE_PLATFORM="platforms/boards/stm32f4_discovery.repl" + MACHINE="STM32F4_Discovery" + ;; + rp2040) + RENODE_PLATFORM="platforms/cpus/rp2040.repl" + MACHINE="RP2040" + ;; + nrf52840) + RENODE_PLATFORM="platforms/cpus/nrf52840.repl" + MACHINE="nRF52840" + ;; + *) + echo "Unknown platform: $PLATFORM" + usage + ;; +esac + +# Generate a temporary Renode script +RESC=$(mktemp /tmp/renode-XXXXXX.resc) +cat >"$RESC" <ds or gdb → target remote :3333" +echo "" + +renode --disable-xwt "$RESC" +rm -f "$RESC" +SIMSCRIPT +chmod +x ~/.local/bin/arduino-sim + +info "Renode simulation helper created (arduino-sim)" diff --git a/lib/scaffold.sh b/lib/scaffold.sh index 0bb53d1..825af5d 100644 --- a/lib/scaffold.sh +++ b/lib/scaffold.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 9: Project scaffolding tool + templates -step "11/11 — Creating project scaffolding tool" +step "12/12 — Creating project scaffolding tool" mkdir -p ~/.local/bin ~/.config/archduino/templates diff --git a/lib/starship.sh b/lib/starship.sh index e8b265c..0361d69 100644 --- a/lib/starship.sh +++ b/lib/starship.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 3: Starship prompt -step "4/11 — Installing Starship" +step "4/12 — Installing Starship" if $IS_ARCH; then $PKG_INSTALL starship diff --git a/lib/yazi.sh b/lib/yazi.sh index 3158f5e..820dc84 100644 --- a/lib/yazi.sh +++ b/lib/yazi.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 8: Yazi file manager -step "8/11 — Installing Yazi" +step "8/12 — Installing Yazi" if $IS_ARCH; then $PKG_INSTALL yazi ffmpegthumbnailer p7zip poppler diff --git a/lib/zellij.sh b/lib/zellij.sh index 93afc02..383ba33 100644 --- a/lib/zellij.sh +++ b/lib/zellij.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 4: Zellij terminal multiplexer -step "5/11 — Installing Zellij" +step "5/12 — Installing Zellij" if $IS_ARCH; then $PKG_INSTALL zellij diff --git a/lib/zsh.sh b/lib/zsh.sh index 4582d27..09179ff 100644 --- a/lib/zsh.sh +++ b/lib/zsh.sh @@ -1,7 +1,7 @@ #!/bin/bash # Step 2: Zsh + Oh My Zsh + plugins -step "3/11 — Setting up Zsh" +step "3/12 — Setting up Zsh" if [[ ! -d "$HOME/.oh-my-zsh" ]]; then RUNZSH=no KEEP_ZSHRC=yes CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended ||