Skip to content

Commit bb52cc9

Browse files
committed
Fixed rust support
Signed-off-by: paulober <[email protected]>
1 parent 2f487fb commit bb52cc9

File tree

11 files changed

+583
-288
lines changed

11 files changed

+583
-288
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@
160160
"category": "Raspberry Pi Pico",
161161
"enablement": "false"
162162
},
163+
{
164+
"command": "raspberry-pi-pico.getSVDPath",
165+
"title": "Get SVD Path (rust only)",
166+
"category": "Raspberry Pi Pico",
167+
"enablement": "false"
168+
},
163169
{
164170
"command": "raspberry-pi-pico.compileProject",
165171
"title": "Compile Pico Project",

src/commands/getPaths.mts

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { CommandWithResult } from "./command.mjs";
2-
import { commands, workspace } from "vscode";
2+
import { commands, type Uri, window, workspace } from "vscode";
33
import {
44
getPythonPath,
55
getPath,
66
cmakeGetSelectedToolchainAndSDKVersions,
77
cmakeGetPicoVar,
88
} from "../utils/cmakeUtil.mjs";
99
import { join } from "path";
10+
import { join as joinPosix } from "path/posix";
1011
import {
1112
buildOpenOCDPath,
1213
buildPicotoolPath,
14+
buildSDKPath,
1315
buildToolchainPath,
1416
downloadAndInstallOpenOCD,
1517
downloadAndInstallPicotool,
@@ -19,6 +21,11 @@ import which from "which";
1921
import { execSync } from "child_process";
2022
import { getPicotoolReleases } from "../utils/githubREST.mjs";
2123
import { openOCDVersion } from "../webview/newProjectPanel.mjs";
24+
import State from "../state.mjs";
25+
import VersionBundlesLoader from "../utils/versionBundles.mjs";
26+
import { getSupportedToolchains } from "../utils/toolchainUtil.mjs";
27+
import Logger from "../logger.mjs";
28+
import { rustProjectGetSelectedChip } from "../utils/rustUtil.mjs";
2229

2330
export class GetPythonPathCommand extends CommandWithResult<string> {
2431
constructor() {
@@ -59,7 +66,7 @@ export class GetEnvPathCommand extends CommandWithResult<string> {
5966
}
6067

6168
export class GetGDBPathCommand extends CommandWithResult<string> {
62-
constructor() {
69+
constructor(private readonly _extensionUri: Uri) {
6370
super("getGDBPath");
6471
}
6572

@@ -72,13 +79,48 @@ export class GetGDBPathCommand extends CommandWithResult<string> {
7279
}
7380

7481
const workspaceFolder = workspace.workspaceFolders?.[0];
82+
const isRustProject = State.getInstance().isRustProject;
83+
let toolchainVersion = "";
7584

76-
const selectedToolchainAndSDKVersions =
77-
await cmakeGetSelectedToolchainAndSDKVersions(workspaceFolder.uri);
78-
if (selectedToolchainAndSDKVersions === null) {
79-
return "";
85+
if (isRustProject) {
86+
// check if latest toolchain is installed
87+
const vbl = new VersionBundlesLoader(this._extensionUri);
88+
const latestVb = await vbl.getLatest();
89+
90+
if (!latestVb) {
91+
void window.showErrorMessage("No version bundles found.");
92+
93+
return "";
94+
}
95+
96+
const supportedToolchains = await getSupportedToolchains();
97+
const latestSupportedToolchain = supportedToolchains.find(
98+
t => t.version === latestVb.toolchain
99+
);
100+
if (!latestSupportedToolchain) {
101+
void window.showErrorMessage(
102+
"No supported toolchain found for the latest version."
103+
);
104+
105+
return "";
106+
}
107+
108+
const useRISCV = rustProjectGetSelectedChip(
109+
workspaceFolder.uri.fsPath
110+
)?.includes("riscv");
111+
112+
toolchainVersion = useRISCV
113+
? latestVb.riscvToolchain
114+
: latestVb.toolchain;
115+
} else {
116+
const selectedToolchainAndSDKVersions =
117+
await cmakeGetSelectedToolchainAndSDKVersions(workspaceFolder.uri);
118+
if (selectedToolchainAndSDKVersions === null) {
119+
return "";
120+
}
121+
122+
toolchainVersion = selectedToolchainAndSDKVersions[1];
80123
}
81-
const toolchainVersion = selectedToolchainAndSDKVersions[1];
82124

83125
let triple = "arm-none-eabi";
84126
if (toolchainVersion.includes("RISCV")) {
@@ -192,6 +234,8 @@ export class GetCxxCompilerPathCommand extends CommandWithResult<string> {
192234
}
193235

194236
export class GetChipCommand extends CommandWithResult<string> {
237+
private readonly _logger = new Logger("GetChipCommand");
238+
195239
constructor() {
196240
super("getChip");
197241
}
@@ -205,6 +249,19 @@ export class GetChipCommand extends CommandWithResult<string> {
205249
}
206250

207251
const workspaceFolder = workspace.workspaceFolders?.[0];
252+
const isRustProject = State.getInstance().isRustProject;
253+
254+
if (isRustProject) {
255+
// read .pico-rs
256+
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);
257+
if (chip === null) {
258+
this._logger.error("Failed to read .pico-rs");
259+
260+
return "";
261+
}
262+
263+
return chip;
264+
}
208265

209266
const settings = Settings.getInstance();
210267
let buildDir = join(workspaceFolder.uri.fsPath, "build");
@@ -265,6 +322,13 @@ export class GetTargetCommand extends CommandWithResult<string> {
265322
}
266323

267324
const workspaceFolder = workspace.workspaceFolders?.[0];
325+
const isRustProject = State.getInstance().isRustProject;
326+
327+
if (isRustProject) {
328+
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);
329+
330+
return chip === null ? "rp2040" : chip.toLowerCase();
331+
}
268332

269333
const settings = Settings.getInstance();
270334
let buildDir = join(workspaceFolder.uri.fsPath, "build");
@@ -381,3 +445,50 @@ export class GetOpenOCDRootCommand extends CommandWithResult<
381445
return buildOpenOCDPath(openOCDVersion);
382446
}
383447
}
448+
449+
/**
450+
* Currently rust only!
451+
*/
452+
export class GetSVDPathCommand extends CommandWithResult<string | undefined> {
453+
public static readonly id = "getSVDPath";
454+
455+
constructor(private readonly _extensionUri: Uri) {
456+
super(GetSVDPathCommand.id);
457+
}
458+
459+
async execute(): Promise<string | undefined> {
460+
if (
461+
workspace.workspaceFolders === undefined ||
462+
workspace.workspaceFolders.length === 0
463+
) {
464+
return "";
465+
}
466+
467+
const isRustProject = State.getInstance().isRustProject;
468+
if (!isRustProject) {
469+
return;
470+
}
471+
472+
const vs = new VersionBundlesLoader(this._extensionUri);
473+
const latestSDK = await vs.getLatestSDK();
474+
if (!latestSDK) {
475+
return;
476+
}
477+
478+
const chip = rustProjectGetSelectedChip(
479+
workspace.workspaceFolders[0].uri.fsPath
480+
);
481+
482+
if (!chip) {
483+
return;
484+
}
485+
486+
return joinPosix(
487+
buildSDKPath(latestSDK),
488+
"src",
489+
chip,
490+
"hardware_regs",
491+
`${chip.toUpperCase()}.svd`
492+
);
493+
}
494+
}

src/commands/launchTargetPath.mts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Settings, { SettingsKey } from "../settings.mjs";
66
import State from "../state.mjs";
77
import { parse as parseToml } from "toml";
88
import { join as joinPosix } from "path/posix";
9+
import { rustProjectGetSelectedChip } from "../utils/rustUtil.mjs";
910

1011
export default class LaunchTargetPathCommand extends CommandWithResult<string> {
1112
public static readonly id = "launchTargetPath";
@@ -81,10 +82,20 @@ export default class LaunchTargetPathCommand extends CommandWithResult<string> {
8182
| undefined;
8283

8384
if (cargoToml?.package?.name) {
85+
const chip = rustProjectGetSelectedChip(
86+
workspace.workspaceFolders[0].uri.fsPath
87+
);
88+
const toolchain =
89+
chip === "rp2040"
90+
? "thumbv6m-none-eabi"
91+
: chip === "rp2350"
92+
? "thumbv8m.main-none-eabi"
93+
: "riscv32imac-unknown-none-elf";
94+
8495
return joinPosix(
8596
workspace.workspaceFolders[0].uri.fsPath.replaceAll("\\", "/"),
8697
"target",
87-
"thumbv6m-none-eabi",
98+
toolchain,
8899
"debug",
89100
cargoToml.package.name
90101
);

src/commands/switchBoard.mts

Lines changed: 24 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
workspace,
88
type Uri,
99
} from "vscode";
10-
import { existsSync, readdirSync, readFileSync } from "fs";
10+
import { existsSync, readdirSync, readFileSync, writeFileSync } from "fs";
1111
import {
1212
buildSDKPath,
1313
downloadAndInstallToolchain,
@@ -25,9 +25,6 @@ import { getSupportedToolchains } from "../utils/toolchainUtil.mjs";
2525
import VersionBundlesLoader from "../utils/versionBundles.mjs";
2626
import State from "../state.mjs";
2727
import { unknownErrorToString } from "../utils/errorHelper.mjs";
28-
import { writeFile } from "fs/promises";
29-
import { parse as parseToml } from "toml";
30-
import { writeTomlFile } from "../utils/projectGeneration/tomlUtil.mjs";
3128

3229
export default class SwitchBoardCommand extends Command {
3330
private _logger: Logger = new Logger("SwitchBoardCommand");
@@ -97,108 +94,58 @@ export default class SwitchBoardCommand extends Command {
9794
// check it has a CMakeLists.txt
9895
if (
9996
workspaceFolder === undefined ||
100-
!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) ||
101-
isRustProject
97+
(!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) &&
98+
!isRustProject)
10299
) {
103100
return;
104101
}
105102

106103
if (isRustProject) {
107104
const board = await window.showQuickPick(
108-
["rp2040", "rp2350", "rp2350-RISCV"],
105+
["RP2040", "RP2350", "RP2350-RISCV"],
109106
{
110107
placeHolder: "Select chip",
111108
canPickMany: false,
112109
ignoreFocusOut: false,
113-
title: "Select chip",
110+
title: "Switch project target chip",
114111
}
115112
);
116113

117114
if (board === undefined) {
118115
return undefined;
119116
}
120117

121-
const target =
122-
board === "rp2350-RISCV"
123-
? "riscv32imac-unknown-none-elf"
124-
: board === "rp2350"
125-
? "thumbv8m.main-none-eabihf"
126-
: "thumbv6m-none-eabi";
127-
128-
// check if .cargo/config.toml already contains a line starting with
129-
// target = "${target}" and if no replace target = "..." with it with the new target
130-
131118
try {
132-
const cargoConfigPath = join(
133-
workspaceFolder.uri.fsPath,
134-
".cargo",
135-
"config.toml"
136-
);
137-
138-
const contents = readFileSync(cargoConfigPath, "utf-8");
139-
140-
const newContents = contents.replace(
141-
/target = ".*"/,
142-
`target = "${target}"`
119+
writeFileSync(
120+
join(workspaceFolder.uri.fsPath, ".pico-rs"),
121+
board.toLowerCase(),
122+
"utf8"
143123
);
144-
145-
if (newContents === contents) {
146-
return;
147-
}
148-
149-
// write new contents to file
150-
await writeFile(cargoConfigPath, newContents);
151-
152-
const cargoToml = (await parseToml(contents)) as {
153-
features?: { default?: string[] };
154-
};
155-
156-
let features = cargoToml.features?.default ?? [];
157-
158-
switch (board) {
159-
case "rp2040":
160-
features.push("rp2040");
161-
// remove all other features rp2350 and rp2350-riscv
162-
features = features.filter(
163-
f => f !== "rp2350" && f !== "rp2350-riscv"
164-
);
165-
break;
166-
case "rp2350":
167-
features.push("rp2350");
168-
// remove all other features rp2040 and rp2350-riscv
169-
features = features.filter(
170-
f => f !== "rp2040" && f !== "rp2350-riscv"
171-
);
172-
break;
173-
case "rp2350-RISCV":
174-
features.push("rp2350-riscv");
175-
// remove all other features rp2040 and rp2350
176-
features = features.filter(f => f !== "rp2040" && f !== "rp2350");
177-
break;
178-
}
179-
180-
if (cargoToml.features) {
181-
cargoToml.features.default = features;
182-
} else {
183-
// not necessary becuase your project is broken at this point
184-
cargoToml.features = { default: features };
185-
}
186-
187-
await writeTomlFile(cargoConfigPath, cargoToml);
188124
} catch (error) {
189125
this._logger.error(
190-
"Failed to update .cargo/config.toml",
191-
unknownErrorToString(error)
126+
`Failed to write .pico-rs file: ${unknownErrorToString(error)}`
192127
);
193128

194129
void window.showErrorMessage(
195-
"Failed to update Cargo.toml and " +
196-
".cargo/config.toml - cannot update chip"
130+
"Failed to write .pico-rs file. " +
131+
"Please check the logs for more information."
197132
);
198133

199134
return;
200135
}
201136

137+
this._ui.updateBoard(board.toUpperCase());
138+
const toolchain =
139+
board === "RP2040"
140+
? "thumbv6m-none-eabi"
141+
: board === "RP2350"
142+
? "thumbv8m.main-none-eabi"
143+
: "riscv32imac-unknown-none-elf";
144+
145+
await workspace
146+
.getConfiguration("rust-analyzer")
147+
.update("cargo.target", toolchain, null);
148+
202149
return;
203150
}
204151

0 commit comments

Comments
 (0)