Skip to content

Commit 80cb7dd

Browse files
jreineckearmGitHub Action
andauthored
Extract SVD file path from *.cbuild-run.yml and set definitionPath for Peripheral Inspector (#151)
* resolve svd filepath (single debugger node) * add new TPIP * deactivate tpip commit, runs every push and breaks CI Signed-off-by: Jens Reinecke <[email protected]> --------- Signed-off-by: Jens Reinecke <[email protected]> Co-authored-by: GitHub Action <[email protected]>
1 parent 15efe9e commit 80cb7dd

26 files changed

+815
-38
lines changed

.github/workflows/tpip.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
run: yarn run tpip:report
3434

3535
- name: Commit changes
36+
if: false
3637
run: |
3738
git config --local user.email "[email protected]"
3839
git config --local user.name "GitHub Action"

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,27 @@
2727
"program": "${workspaceFolder}/scripts/download-tools.ts",
2828
"runtimeArgs": ["-r", "ts-node/register"],
2929
"args": ["pyocd"]
30+
},
31+
{
32+
"type": "node",
33+
"request": "launch",
34+
"name": "Unit Test Current File",
35+
"program": "${workspaceFolder}/node_modules/.bin/jest",
36+
"args": [
37+
"--collectCoverage",
38+
"false",
39+
"${fileBasenameNoExtension}"
40+
],
41+
"console": "integratedTerminal",
42+
"internalConsoleOptions": "neverOpen",
43+
"windows": {
44+
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
45+
},
46+
"presentation": {
47+
"hidden": false,
48+
"group": "Tests",
49+
"order": 1
50+
}
3051
}
3152
]
3253
}

TPIP.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# TPIP Report for vscode-cmsis-debugger
22

3-
Report prepared at: 03/03/2025, 10:34:00
3+
Report prepared at: 09/04/2025, 19:24:24
44

55
| *Package* | *Version* | *Repository* | *License* |
66
|---|---|---|---|
77
| pyocd | 0.36.0 | https://github.com/pyocd/pyOCD | https://github.com/pyocd/pyOCD/blob/v0.36.0/LICENSE |
8+
| yaml | 2.7.1 | https://github.com/eemeli/yaml | https://github.com/eemeli/yaml/blob/main/LICENSE |

__mocks__/vscode.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
require('domain');
1818
const { URI } = require('vscode-uri');
19+
const path = require('path');
20+
const fs = require('fs');
1921

2022
module.exports = {
2123
EventEmitter: jest.fn(() => {
@@ -44,6 +46,19 @@ module.exports = {
4446
getConfiguration: jest.fn(() => ({
4547
get: jest.fn(),
4648
})),
49+
fs: {
50+
readFile: jest.fn(uri => {
51+
const buffer = fs.readFileSync(uri.fsPath);
52+
return new Promise(resolve => resolve(new Uint8Array(buffer)));
53+
})
54+
},
55+
workspaceFolders: [
56+
{
57+
uri: URI.file(path.join(__dirname, '..')),
58+
name: 'folderName',
59+
index: 0
60+
}
61+
]
4762
},
4863
extensions: {
4964
getExtension: jest.fn(),

docs/third-party-licenses.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,12 @@
55
"spdx": "Apache-2.0",
66
"url": "https://github.com/pyocd/pyOCD",
77
"license": "https://github.com/pyocd/pyOCD/blob/v0.36.0/LICENSE"
8+
},
9+
{
10+
"name": "yaml",
11+
"version": "2.7.1",
12+
"spdx": "ISC",
13+
"url": "https://github.com/eemeli/yaml",
14+
"license": "https://github.com/eemeli/yaml/blob/main/LICENSE"
815
}
916
]

jest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const config: Config = {
3232
"src/**/*.{ts,tsx}",
3333
"!**/*.d.ts",
3434
"!**/*.factories.{ts,tsx}",
35+
"!**/__test__/**/*",
3536
"!src/desktop/extension.ts",
3637
],
3738
coverageDirectory: "./coverage",

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@
220220
"yarn": true,
221221
"baseContentUrl": "https://github.com/Open-CMSIS-Pack/vscode-cmsis-debugger/blob/main/README.md"
222222
},
223-
"dependencies": {},
223+
"dependencies": {
224+
"yaml": "^2.7.1"
225+
},
224226
"devDependencies": {
225227
"@types/jest": "^29.5.14",
226228
"@types/node": "^20.17.30",
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CbuildRunReader Parser successfully parses a *.cbuild-run.yml file 1`] = `
4+
{
5+
"compiler": "AC6",
6+
"debug-sequences": [
7+
{
8+
"blocks": [
9+
{
10+
"execute": "Write32(0x20000000, 0xA5A5A5A5);
11+
",
12+
},
13+
{
14+
"blocks": [
15+
{
16+
"execute": "Read32(0x20000004);
17+
",
18+
},
19+
],
20+
"if": "condition == true",
21+
},
22+
{
23+
"execute": "Write32(0x20000008, 0x5);
24+
",
25+
},
26+
],
27+
"name": "MySequence",
28+
"pname": "Core0",
29+
},
30+
{
31+
"blocks": [
32+
{
33+
"execute": "DAP_Delay(500000); // Delay for 500ms
34+
",
35+
},
36+
],
37+
"name": "DebugDeviceUnlock",
38+
"pname": "Core0",
39+
},
40+
],
41+
"debug-topology": {
42+
"debugports": [
43+
{
44+
"accessports": [
45+
{
46+
"address": 0,
47+
"apid": 0,
48+
},
49+
{
50+
"address": 1048576,
51+
"apid": 1,
52+
},
53+
],
54+
"dpid": 0,
55+
},
56+
],
57+
"processors": [
58+
{
59+
"apid": 0,
60+
"pname": "Core0",
61+
},
62+
{
63+
"apid": 1,
64+
"pname": "Core1",
65+
},
66+
],
67+
},
68+
"debugger": [
69+
{
70+
"clock": 10000000,
71+
"name": "<default>",
72+
"port": "swd",
73+
},
74+
],
75+
"device": "MyVendor::MyDevice",
76+
"device-pack": "MyVendor::[email protected]",
77+
"generated-by": "csolution version 2.8.0",
78+
"output": [
79+
{
80+
"file": "out/MyApp.bin",
81+
"info": "generate by MyApp",
82+
"type": "bin",
83+
},
84+
{
85+
"file": "out/out/MyApp.axf",
86+
"info": "generate by MyApp",
87+
"type": "elf",
88+
},
89+
],
90+
"programming": [
91+
{
92+
"algorithm": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Flash/algorithms/MyAlgorithm_Core0.FLM",
93+
"default": true,
94+
"pname": "Core0",
95+
"ram-size": 131072,
96+
"ram-start": 536870912,
97+
"size": 524288,
98+
"start": 0,
99+
},
100+
{
101+
"algorithm": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Flash/algorithms/MyAlgorithm_Extern.FLM",
102+
"default": true,
103+
"pname": "Core0",
104+
"ram-size": 131072,
105+
"ram-start": 536870912,
106+
"size": 33554432,
107+
"start": 3221225472,
108+
},
109+
],
110+
"solution": "my-test.csolution.yml",
111+
"system-descriptions": [
112+
{
113+
"file": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Debug/SVD/MyDevice_Core0.svd",
114+
"pname": "Core0",
115+
"type": "svd",
116+
},
117+
],
118+
"system-resources": {
119+
"memory": [
120+
{
121+
"access": "rx",
122+
"default": true,
123+
"from-pack": "MyVendor::[email protected]",
124+
"name": "Flash",
125+
"pname": "Core0",
126+
"size": 524288,
127+
"start": 0,
128+
},
129+
{
130+
"access": "rwx",
131+
"default": true,
132+
"from-pack": "MyVendor::[email protected]",
133+
"name": "SRAM0",
134+
"pname": "Core0",
135+
"size": 4194304,
136+
"start": 33554432,
137+
},
138+
{
139+
"access": "rwx",
140+
"default": true,
141+
"from-pack": "MyVendor::[email protected]",
142+
"name": "SRAM1",
143+
"pname": "Core0",
144+
"size": 2621440,
145+
"start": 134217728,
146+
},
147+
],
148+
},
149+
"target-type": "My-Test-Target-Type",
150+
}
151+
`;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright 2025 Arm Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { CbuildRunReader } from './cbuild-run-reader';
18+
19+
const TEST_CBUILD_RUN_FILE = 'test-data/simple.cbuild-run.yml'; // Relative to repo root
20+
const TEST_FILE_PATH = 'test-data/fileReaderTest.txt'; // Relative to repo root
21+
22+
describe('CbuildRunReader', () => {
23+
24+
describe('Parser', () => {
25+
it('successfully parses a *.cbuild-run.yml file', async () => {
26+
const cbuildRunReader = new CbuildRunReader();
27+
await expect(cbuildRunReader.parse(TEST_CBUILD_RUN_FILE)).resolves.not.toThrow();
28+
expect(cbuildRunReader.hasContents()).toBe(true);
29+
const contents = cbuildRunReader.getContents();
30+
expect(contents).toBeDefined();
31+
expect(contents).toMatchSnapshot();
32+
});
33+
34+
it('throws if it parses something other than a *.cbuild-run.yml file and correctly responds to raw contents calls', async () => {
35+
const expectedError = /Invalid '\*\.cbuild-run\.yml' file: .*test-data\/fileReaderTest\.txt/;
36+
const cbuildRunReader = new CbuildRunReader();
37+
await expect(cbuildRunReader.parse(TEST_FILE_PATH)).rejects.toThrow(expectedError);
38+
expect(cbuildRunReader.hasContents()).toBe(false);
39+
expect(cbuildRunReader.getContents()).toBeUndefined();
40+
});
41+
42+
it('correctly responds to raw contents calls if nothing is parsed', () => {
43+
const cbuildRunReader = new CbuildRunReader();
44+
expect(cbuildRunReader.hasContents()).toBe(false);
45+
expect(cbuildRunReader.getContents()).toBeUndefined();
46+
});
47+
});
48+
49+
describe('Extract Values', () => {
50+
let cbuildRunReader: CbuildRunReader;
51+
52+
beforeEach(() => {
53+
cbuildRunReader = new CbuildRunReader();
54+
});
55+
56+
it('returns SVD file path', async () => {
57+
const expectedSvdFilePaths = ['/my/pack/root/MyVendor/MyDevice/1.0.0/Debug/SVD/MyDevice_Core0.svd'];
58+
await cbuildRunReader.parse(TEST_CBUILD_RUN_FILE);
59+
const svdFilePaths = cbuildRunReader.getSvdFilePaths('/my/pack/root');
60+
expect(svdFilePaths).toEqual(expectedSvdFilePaths);
61+
});
62+
63+
it('returns empty SVD file path list if nothing is parsed', () => {
64+
const svdFilePaths = cbuildRunReader.getSvdFilePaths('/my/pack/root');
65+
expect(svdFilePaths.length).toEqual(0);
66+
});
67+
});
68+
});
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Copyright 2025 Arm Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as yaml from 'yaml';
18+
import { CbuildRunType } from './cbuild-run-types';
19+
import { FileReader, VscodeFileReader } from '../desktop/file-reader';
20+
import { getCmsisPackRootPath } from '../utils';
21+
22+
const ROOT_NODE = 'cbuild-run';
23+
const CMSIS_PACK_ROOT_ENVVAR = '${CMSIS_PACK_ROOT}';
24+
25+
export class CbuildRunReader {
26+
private cbuildRun?: CbuildRunType;
27+
28+
constructor(private reader: FileReader = new VscodeFileReader()) {}
29+
30+
public hasContents(): boolean {
31+
return !!this.cbuildRun;
32+
}
33+
34+
public getContents(): CbuildRunType|undefined {
35+
return this.cbuildRun;
36+
}
37+
38+
public async parse(filePath: string): Promise<void> {
39+
const fileContents = await this.reader.readFileToString(filePath);
40+
const fileRoot = yaml.parse(fileContents);
41+
this.cbuildRun = fileRoot ? fileRoot[ROOT_NODE] : undefined;
42+
if (!this.cbuildRun) {
43+
throw new Error(`Invalid '*.cbuild-run.yml' file: ${filePath}`);
44+
}
45+
}
46+
47+
public getSvdFilePaths(cmsisPackRoot?: string): string[] {
48+
if (!this.cbuildRun) {
49+
return [];
50+
}
51+
// Get SVD file descriptors
52+
const systemDescriptions = this.cbuildRun['system-descriptions'];
53+
const svdFileDescriptors = systemDescriptions?.filter(descriptor => descriptor.type === 'svd') ?? [];
54+
if (svdFileDescriptors.length === 0) {
55+
return [];
56+
}
57+
// Replace potential ${CMSIS_PACK_ROOT} placeholder
58+
const effectiveCmsisPackRoot = cmsisPackRoot ?? getCmsisPackRootPath();
59+
// Map to copies, leave originals untouched
60+
const svdFilePaths = svdFileDescriptors.map(descriptor => `${effectiveCmsisPackRoot
61+
? descriptor.file.replaceAll(CMSIS_PACK_ROOT_ENVVAR, effectiveCmsisPackRoot)
62+
: descriptor.file}`);
63+
return svdFilePaths;
64+
}
65+
66+
}

0 commit comments

Comments
 (0)