Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/tpip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
run: yarn run tpip:report

- name: Commit changes
if: false
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
Expand Down
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@
"program": "${workspaceFolder}/scripts/download-tools.ts",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["pyocd"]
},
{
"type": "node",
"request": "launch",
"name": "Unit Test Current File",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--collectCoverage",
"false",
"${fileBasenameNoExtension}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
},
"presentation": {
"hidden": false,
"group": "Tests",
"order": 1
}
}
]
}
3 changes: 2 additions & 1 deletion TPIP.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# TPIP Report for vscode-cmsis-debugger

Report prepared at: 03/03/2025, 10:34:00
Report prepared at: 09/04/2025, 19:24:24

| *Package* | *Version* | *Repository* | *License* |
|---|---|---|---|
| pyocd | 0.36.0 | https://github.com/pyocd/pyOCD | https://github.com/pyocd/pyOCD/blob/v0.36.0/LICENSE |
| yaml | 2.7.1 | https://github.com/eemeli/yaml | https://github.com/eemeli/yaml/blob/main/LICENSE |
15 changes: 15 additions & 0 deletions __mocks__/vscode.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

require('domain');
const { URI } = require('vscode-uri');
const path = require('path');
const fs = require('fs');

module.exports = {
EventEmitter: jest.fn(() => {
Expand Down Expand Up @@ -44,6 +46,19 @@ module.exports = {
getConfiguration: jest.fn(() => ({
get: jest.fn(),
})),
fs: {
readFile: jest.fn(uri => {
const buffer = fs.readFileSync(uri.fsPath);
return new Promise(resolve => resolve(new Uint8Array(buffer)));
})
},
workspaceFolders: [
{
uri: URI.file(path.join(__dirname, '..')),
name: 'folderName',
index: 0
}
]
},
extensions: {
getExtension: jest.fn(),
Expand Down
7 changes: 7 additions & 0 deletions docs/third-party-licenses.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@
"spdx": "Apache-2.0",
"url": "https://github.com/pyocd/pyOCD",
"license": "https://github.com/pyocd/pyOCD/blob/v0.36.0/LICENSE"
},
{
"name": "yaml",
"version": "2.7.1",
"spdx": "ISC",
"url": "https://github.com/eemeli/yaml",
"license": "https://github.com/eemeli/yaml/blob/main/LICENSE"
}
]
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const config: Config = {
"src/**/*.{ts,tsx}",
"!**/*.d.ts",
"!**/*.factories.{ts,tsx}",
"!**/__test__/**/*",
"!src/desktop/extension.ts",
],
coverageDirectory: "./coverage",
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@
"yarn": true,
"baseContentUrl": "https://github.com/Open-CMSIS-Pack/vscode-cmsis-debugger/blob/main/README.md"
},
"dependencies": {},
"dependencies": {
"yaml": "^2.7.1"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/node": "^20.17.30",
Expand Down
151 changes: 151 additions & 0 deletions src/cbuild-run/__snapshots__/cbuild-run-reader.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CbuildRunReader Parser successfully parses a *.cbuild-run.yml file 1`] = `
{
"compiler": "AC6",
"debug-sequences": [
{
"blocks": [
{
"execute": "Write32(0x20000000, 0xA5A5A5A5);
",
},
{
"blocks": [
{
"execute": "Read32(0x20000004);
",
},
],
"if": "condition == true",
},
{
"execute": "Write32(0x20000008, 0x5);
",
},
],
"name": "MySequence",
"pname": "Core0",
},
{
"blocks": [
{
"execute": "DAP_Delay(500000); // Delay for 500ms
",
},
],
"name": "DebugDeviceUnlock",
"pname": "Core0",
},
],
"debug-topology": {
"debugports": [
{
"accessports": [
{
"address": 0,
"apid": 0,
},
{
"address": 1048576,
"apid": 1,
},
],
"dpid": 0,
},
],
"processors": [
{
"apid": 0,
"pname": "Core0",
},
{
"apid": 1,
"pname": "Core1",
},
],
},
"debugger": [
{
"clock": 10000000,
"name": "<default>",
"port": "swd",
},
],
"device": "MyVendor::MyDevice",
"device-pack": "MyVendor::[email protected]",
"generated-by": "csolution version 2.8.0",
"output": [
{
"file": "out/MyApp.bin",
"info": "generate by MyApp",
"type": "bin",
},
{
"file": "out/out/MyApp.axf",
"info": "generate by MyApp",
"type": "elf",
},
],
"programming": [
{
"algorithm": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Flash/algorithms/MyAlgorithm_Core0.FLM",
"default": true,
"pname": "Core0",
"ram-size": 131072,
"ram-start": 536870912,
"size": 524288,
"start": 0,
},
{
"algorithm": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Flash/algorithms/MyAlgorithm_Extern.FLM",
"default": true,
"pname": "Core0",
"ram-size": 131072,
"ram-start": 536870912,
"size": 33554432,
"start": 3221225472,
},
],
"solution": "my-test.csolution.yml",
"system-descriptions": [
{
"file": "\${CMSIS_PACK_ROOT}/MyVendor/MyDevice/1.0.0/Debug/SVD/MyDevice_Core0.svd",
"pname": "Core0",
"type": "svd",
},
],
"system-resources": {
"memory": [
{
"access": "rx",
"default": true,
"from-pack": "MyVendor::[email protected]",
"name": "Flash",
"pname": "Core0",
"size": 524288,
"start": 0,
},
{
"access": "rwx",
"default": true,
"from-pack": "MyVendor::[email protected]",
"name": "SRAM0",
"pname": "Core0",
"size": 4194304,
"start": 33554432,
},
{
"access": "rwx",
"default": true,
"from-pack": "MyVendor::[email protected]",
"name": "SRAM1",
"pname": "Core0",
"size": 2621440,
"start": 134217728,
},
],
},
"target-type": "My-Test-Target-Type",
}
`;
68 changes: 68 additions & 0 deletions src/cbuild-run/cbuild-run-reader.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright 2025 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { CbuildRunReader } from './cbuild-run-reader';

const TEST_CBUILD_RUN_FILE = 'test-data/simple.cbuild-run.yml'; // Relative to repo root
const TEST_FILE_PATH = 'test-data/fileReaderTest.txt'; // Relative to repo root

describe('CbuildRunReader', () => {

describe('Parser', () => {
it('successfully parses a *.cbuild-run.yml file', async () => {
const cbuildRunReader = new CbuildRunReader();
await expect(cbuildRunReader.parse(TEST_CBUILD_RUN_FILE)).resolves.not.toThrow();
expect(cbuildRunReader.hasContents()).toBe(true);
const contents = cbuildRunReader.getContents();
expect(contents).toBeDefined();
expect(contents).toMatchSnapshot();
});

it('throws if it parses something other than a *.cbuild-run.yml file and correctly responds to raw contents calls', async () => {
const expectedError = /Invalid '\*\.cbuild-run\.yml' file: .*test-data\/fileReaderTest\.txt/;
const cbuildRunReader = new CbuildRunReader();
await expect(cbuildRunReader.parse(TEST_FILE_PATH)).rejects.toThrow(expectedError);
expect(cbuildRunReader.hasContents()).toBe(false);
expect(cbuildRunReader.getContents()).toBeUndefined();
});

it('correctly responds to raw contents calls if nothing is parsed', () => {
const cbuildRunReader = new CbuildRunReader();
expect(cbuildRunReader.hasContents()).toBe(false);
expect(cbuildRunReader.getContents()).toBeUndefined();
});
});

describe('Extract Values', () => {
let cbuildRunReader: CbuildRunReader;

beforeEach(() => {
cbuildRunReader = new CbuildRunReader();
});

it('returns SVD file path', async () => {
const expectedSvdFilePaths = ['/my/pack/root/MyVendor/MyDevice/1.0.0/Debug/SVD/MyDevice_Core0.svd'];
await cbuildRunReader.parse(TEST_CBUILD_RUN_FILE);
const svdFilePaths = cbuildRunReader.getSvdFilePaths('/my/pack/root');
expect(svdFilePaths).toEqual(expectedSvdFilePaths);
});

it('returns empty SVD file path list if nothing is parsed', () => {
const svdFilePaths = cbuildRunReader.getSvdFilePaths('/my/pack/root');
expect(svdFilePaths.length).toEqual(0);
});
});
});
66 changes: 66 additions & 0 deletions src/cbuild-run/cbuild-run-reader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Copyright 2025 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as yaml from 'yaml';
import { CbuildRunType } from './cbuild-run-types';
import { FileReader, VscodeFileReader } from '../desktop/file-reader';
import { getCmsisPackRootPath } from '../utils';

const ROOT_NODE = 'cbuild-run';
const CMSIS_PACK_ROOT_ENVVAR = '${CMSIS_PACK_ROOT}';

export class CbuildRunReader {
private cbuildRun?: CbuildRunType;

constructor(private reader: FileReader = new VscodeFileReader()) {}

public hasContents(): boolean {
return !!this.cbuildRun;
}

public getContents(): CbuildRunType|undefined {
return this.cbuildRun;
}

public async parse(filePath: string): Promise<void> {
const fileContents = await this.reader.readFileToString(filePath);
const fileRoot = yaml.parse(fileContents);
this.cbuildRun = fileRoot ? fileRoot[ROOT_NODE] : undefined;
if (!this.cbuildRun) {
throw new Error(`Invalid '*.cbuild-run.yml' file: ${filePath}`);
}
}

public getSvdFilePaths(cmsisPackRoot?: string): string[] {
if (!this.cbuildRun) {
return [];
}
// Get SVD file descriptors
const systemDescriptions = this.cbuildRun['system-descriptions'];
const svdFileDescriptors = systemDescriptions?.filter(descriptor => descriptor.type === 'svd') ?? [];
if (svdFileDescriptors.length === 0) {
return [];
}
// Replace potential ${CMSIS_PACK_ROOT} placeholder
const effectiveCmsisPackRoot = cmsisPackRoot ?? getCmsisPackRootPath();
// Map to copies, leave originals untouched
const svdFilePaths = svdFileDescriptors.map(descriptor => `${effectiveCmsisPackRoot
? descriptor.file.replaceAll(CMSIS_PACK_ROOT_ENVVAR, effectiveCmsisPackRoot)
: descriptor.file}`);
return svdFilePaths;
}

}
Loading
Loading