Skip to content

Commit 52aa604

Browse files
committed
Fixed rust support
Signed-off-by: paulober <[email protected]>
1 parent fd566f6 commit 52aa604

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,
@@ -28,9 +28,6 @@ import { getSupportedToolchains } from "../utils/toolchainUtil.mjs";
2828
import VersionBundlesLoader from "../utils/versionBundles.mjs";
2929
import State from "../state.mjs";
3030
import { unknownErrorToString } from "../utils/errorHelper.mjs";
31-
import { writeFile } from "fs/promises";
32-
import { parse as parseToml } from "toml";
33-
import { writeTomlFile } from "../utils/projectGeneration/tomlUtil.mjs";
3431

3532
export default class SwitchBoardCommand extends Command {
3633
private _logger: Logger = new Logger("SwitchBoardCommand");
@@ -152,108 +149,58 @@ export default class SwitchBoardCommand extends Command {
152149
// check it has a CMakeLists.txt
153150
if (
154151
workspaceFolder === undefined ||
155-
!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) ||
156-
isRustProject
152+
(!existsSync(join(workspaceFolder.uri.fsPath, "CMakeLists.txt")) &&
153+
!isRustProject)
157154
) {
158155
return;
159156
}
160157

161158
if (isRustProject) {
162159
const board = await window.showQuickPick(
163-
["rp2040", "rp2350", "rp2350-RISCV"],
160+
["RP2040", "RP2350", "RP2350-RISCV"],
164161
{
165162
placeHolder: "Select chip",
166163
canPickMany: false,
167164
ignoreFocusOut: false,
168-
title: "Select chip",
165+
title: "Switch project target chip",
169166
}
170167
);
171168

172169
if (board === undefined) {
173170
return undefined;
174171
}
175172

176-
const target =
177-
board === "rp2350-RISCV"
178-
? "riscv32imac-unknown-none-elf"
179-
: board === "rp2350"
180-
? "thumbv8m.main-none-eabihf"
181-
: "thumbv6m-none-eabi";
182-
183-
// check if .cargo/config.toml already contains a line starting with
184-
// target = "${target}" and if no replace target = "..." with it with the new target
185-
186173
try {
187-
const cargoConfigPath = join(
188-
workspaceFolder.uri.fsPath,
189-
".cargo",
190-
"config.toml"
191-
);
192-
193-
const contents = readFileSync(cargoConfigPath, "utf-8");
194-
195-
const newContents = contents.replace(
196-
/target = ".*"/,
197-
`target = "${target}"`
174+
writeFileSync(
175+
join(workspaceFolder.uri.fsPath, ".pico-rs"),
176+
board.toLowerCase(),
177+
"utf8"
198178
);
199-
200-
if (newContents === contents) {
201-
return;
202-
}
203-
204-
// write new contents to file
205-
await writeFile(cargoConfigPath, newContents);
206-
207-
const cargoToml = (await parseToml(contents)) as {
208-
features?: { default?: string[] };
209-
};
210-
211-
let features = cargoToml.features?.default ?? [];
212-
213-
switch (board) {
214-
case "rp2040":
215-
features.push("rp2040");
216-
// remove all other features rp2350 and rp2350-riscv
217-
features = features.filter(
218-
f => f !== "rp2350" && f !== "rp2350-riscv"
219-
);
220-
break;
221-
case "rp2350":
222-
features.push("rp2350");
223-
// remove all other features rp2040 and rp2350-riscv
224-
features = features.filter(
225-
f => f !== "rp2040" && f !== "rp2350-riscv"
226-
);
227-
break;
228-
case "rp2350-RISCV":
229-
features.push("rp2350-riscv");
230-
// remove all other features rp2040 and rp2350
231-
features = features.filter(f => f !== "rp2040" && f !== "rp2350");
232-
break;
233-
}
234-
235-
if (cargoToml.features) {
236-
cargoToml.features.default = features;
237-
} else {
238-
// not necessary becuase your project is broken at this point
239-
cargoToml.features = { default: features };
240-
}
241-
242-
await writeTomlFile(cargoConfigPath, cargoToml);
243179
} catch (error) {
244180
this._logger.error(
245-
"Failed to update .cargo/config.toml",
246-
unknownErrorToString(error)
181+
`Failed to write .pico-rs file: ${unknownErrorToString(error)}`
247182
);
248183

249184
void window.showErrorMessage(
250-
"Failed to update Cargo.toml and " +
251-
".cargo/config.toml - cannot update chip"
185+
"Failed to write .pico-rs file. " +
186+
"Please check the logs for more information."
252187
);
253188

254189
return;
255190
}
256191

192+
this._ui.updateBoard(board.toUpperCase());
193+
const toolchain =
194+
board === "RP2040"
195+
? "thumbv6m-none-eabi"
196+
: board === "RP2350"
197+
? "thumbv8m.main-none-eabi"
198+
: "riscv32imac-unknown-none-elf";
199+
200+
await workspace
201+
.getConfiguration("rust-analyzer")
202+
.update("cargo.target", toolchain, null);
203+
257204
return;
258205
}
259206

0 commit comments

Comments
 (0)