Skip to content

Commit 64d27cb

Browse files
committed
Fixed rust support
Signed-off-by: paulober <[email protected]>
1 parent 6b3f029 commit 64d27cb

File tree

11 files changed

+584
-252
lines changed

11 files changed

+584
-252
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@
154154
"category": "Raspberry Pi Pico",
155155
"enablement": "false"
156156
},
157+
{
158+
"command": "raspberry-pi-pico.getSVDPath",
159+
"title": "Get SVD Path (rust only)",
160+
"category": "Raspberry Pi Pico",
161+
"enablement": "false"
162+
},
157163
{
158164
"command": "raspberry-pi-pico.compileProject",
159165
"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")) {
@@ -154,6 +196,8 @@ export class GetCompilerPathCommand extends CommandWithResult<string> {
154196
}
155197

156198
export class GetChipCommand extends CommandWithResult<string> {
199+
private readonly _logger = new Logger("GetChipCommand");
200+
157201
constructor() {
158202
super("getChip");
159203
}
@@ -167,6 +211,19 @@ export class GetChipCommand extends CommandWithResult<string> {
167211
}
168212

169213
const workspaceFolder = workspace.workspaceFolders?.[0];
214+
const isRustProject = State.getInstance().isRustProject;
215+
216+
if (isRustProject) {
217+
// read .pico-rs
218+
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);
219+
if (chip === null) {
220+
this._logger.error("Failed to read .pico-rs");
221+
222+
return "";
223+
}
224+
225+
return chip;
226+
}
170227

171228
const settings = Settings.getInstance();
172229
let buildDir = join(workspaceFolder.uri.fsPath, "build");
@@ -227,6 +284,13 @@ export class GetTargetCommand extends CommandWithResult<string> {
227284
}
228285

229286
const workspaceFolder = workspace.workspaceFolders?.[0];
287+
const isRustProject = State.getInstance().isRustProject;
288+
289+
if (isRustProject) {
290+
const chip = rustProjectGetSelectedChip(workspaceFolder.uri.fsPath);
291+
292+
return chip === null ? "rp2040" : chip.toLowerCase();
293+
}
230294

231295
const settings = Settings.getInstance();
232296
let buildDir = join(workspaceFolder.uri.fsPath, "build");
@@ -343,3 +407,50 @@ export class GetOpenOCDRootCommand extends CommandWithResult<
343407
return buildOpenOCDPath(openOCDVersion);
344408
}
345409
}
410+
411+
/**
412+
* Currently rust only!
413+
*/
414+
export class GetSVDPathCommand extends CommandWithResult<string | undefined> {
415+
public static readonly id = "getSVDPath";
416+
417+
constructor(private readonly _extensionUri: Uri) {
418+
super(GetSVDPathCommand.id);
419+
}
420+
421+
async execute(): Promise<string | undefined> {
422+
if (
423+
workspace.workspaceFolders === undefined ||
424+
workspace.workspaceFolders.length === 0
425+
) {
426+
return "";
427+
}
428+
429+
const isRustProject = State.getInstance().isRustProject;
430+
if (!isRustProject) {
431+
return;
432+
}
433+
434+
const vs = new VersionBundlesLoader(this._extensionUri);
435+
const latestSDK = await vs.getLatestSDK();
436+
if (!latestSDK) {
437+
return;
438+
}
439+
440+
const chip = rustProjectGetSelectedChip(
441+
workspace.workspaceFolders[0].uri.fsPath
442+
);
443+
444+
if (!chip) {
445+
return;
446+
}
447+
448+
return joinPosix(
449+
buildSDKPath(latestSDK),
450+
"src",
451+
chip,
452+
"hardware_regs",
453+
`${chip.toUpperCase()}.svd`
454+
);
455+
}
456+
}

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");
@@ -93,108 +90,58 @@ export default class SwitchBoardCommand extends Command {
9390
// check it has a CMakeLists.txt
9491
if (
9592
workspaceFolder === undefined ||
96-
!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) ||
97-
isRustProject
93+
(!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) &&
94+
!isRustProject)
9895
) {
9996
return;
10097
}
10198

10299
if (isRustProject) {
103100
const board = await window.showQuickPick(
104-
["rp2040", "rp2350", "rp2350-RISCV"],
101+
["RP2040", "RP2350", "RP2350-RISCV"],
105102
{
106103
placeHolder: "Select chip",
107104
canPickMany: false,
108105
ignoreFocusOut: false,
109-
title: "Select chip",
106+
title: "Switch project target chip",
110107
}
111108
);
112109

113110
if (board === undefined) {
114111
return undefined;
115112
}
116113

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

190125
void window.showErrorMessage(
191-
"Failed to update Cargo.toml and " +
192-
".cargo/config.toml - cannot update chip"
126+
"Failed to write .pico-rs file. " +
127+
"Please check the logs for more information."
193128
);
194129

195130
return;
196131
}
197132

133+
this._ui.updateBoard(board.toUpperCase());
134+
const toolchain =
135+
board === "RP2040"
136+
? "thumbv6m-none-eabi"
137+
: board === "RP2350"
138+
? "thumbv8m.main-none-eabi"
139+
: "riscv32imac-unknown-none-elf";
140+
141+
await workspace
142+
.getConfiguration("rust-analyzer")
143+
.update("cargo.target", toolchain, null);
144+
198145
return;
199146
}
200147

0 commit comments

Comments
 (0)