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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Change Log

- FreeRTOS: Fix the issue where hints are not showing at all when Thread ID is missing.
- zephyr: display stack peak usage.

## 0.0.15 - Mar 28, 2026

Expand Down
56 changes: 56 additions & 0 deletions src/rtos/rtos-zephyr.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import * as vscode from 'vscode';
import * as RTOSCommon from './rtos-common';
import { DebugProtocol } from '@vscode/debugprotocol';

// We will have two rows of headers for Zephyr and the table below describes
// the columns headers for the two rows and the width of each column as a fraction
Expand All @@ -11,6 +12,7 @@ enum DisplayFields {
Status,
Priority,
StackPercent,
StackPeak,
}

const RTOSZEPHYRItems: { [key: string]: RTOSCommon.DisplayColumnItem } = {};
Expand Down Expand Up @@ -45,6 +47,12 @@ RTOSZEPHYRItems[DisplayFields[DisplayFields.StackPercent]] = {
headerRow2: '% (Used B / Size B)',
colType: RTOSCommon.ColTypeEnum.colTypePercentage,
};
RTOSZEPHYRItems[DisplayFields[DisplayFields.StackPeak]] = {
width: 4,
headerRow1: 'Stack Peak Usage',
headerRow2: '% (Peak B / Size B)',
colType: RTOSCommon.ColTypeEnum.colTypePercentage,
};

const DisplayFieldNames: string[] = Object.keys(RTOSZEPHYRItems);

Expand Down Expand Up @@ -239,8 +247,19 @@ export class RTOSZEPHYR extends RTOSCommon.RTOSBase {
const stackPercentVal = Math.round((stackInfo.stackUsed / stackInfo.stackSize) * 100);
const stackPercentText = `${stackPercentVal} % (${stackInfo.stackUsed} / ${stackInfo.stackSize})`;
mySetter(DisplayFields.StackPercent, stackPercentText, stackPercentVal);

if (RTOSCommon.RTOSBase.disableStackPeaks) {
mySetter(DisplayFields.StackPeak, '----');
} else if (stackInfo.stackPeak !== undefined) {
const stackPeakPercentVal = Math.round((stackInfo.stackPeak / stackInfo.stackSize) * 100);
const stackPeakPercentText = `${stackPeakPercentVal} % (${stackInfo.stackPeak} / ${stackInfo.stackSize})`;
mySetter(DisplayFields.StackPeak, stackPeakPercentText, stackPeakPercentVal);
} else {
mySetter(DisplayFields.StackPeak, '?? %');
}
} else {
mySetter(DisplayFields.StackPercent, '?? %');
mySetter(DisplayFields.StackPeak, '?? %');
}

const thread: RTOSCommon.RTOSThreadInfo = {
Expand Down Expand Up @@ -344,6 +363,35 @@ export class RTOSZEPHYR extends RTOSCommon.RTOSBase {
}
}

protected async calculateStackPeak(stackInfo: RTOSCommon.RTOSStackInfo): Promise<number | undefined> {
try {
if (stackInfo.stackStart === undefined || stackInfo.stackEnd === undefined || stackInfo.stackSize === undefined) {
return undefined;
}
const memArg: DebugProtocol.ReadMemoryArguments = {
memoryReference: RTOSCommon.hexFormat(Math.min(stackInfo.stackStart, stackInfo.stackEnd)),
count: stackInfo.stackSize,
};
const stackData = await this.session.customRequest('readMemory', memArg);
const buf = Buffer.from(stackData.data, 'base64');
stackInfo.bytes = new Uint8Array(buf);
let maxUsedBytes = stackInfo.stackSize;

for (let i = 0; i < stackInfo.bytes.length; i++) {
if (stackInfo.bytes[i] !== 0xaa) {
break;
}

maxUsedBytes--;
}

return maxUsedBytes;
} catch (error) {
console.error('failed to read zephyr stack memory:', error);
return undefined;
}
}

protected async getStackInfo(thInfo: RTOSCommon.RTOSStrToValueMap | null) {
const stackInfo: RTOSCommon.RTOSStackInfo = {
stackStart: 0,
Expand Down Expand Up @@ -396,6 +444,14 @@ export class RTOSZEPHYR extends RTOSCommon.RTOSBase {
stackInfo.stackFree = stackDelta;
stackInfo.stackUsed = stackInfo.stackSize - stackDelta;
}

if (!RTOSCommon.RTOSBase.disableStackPeaks) {
const maxStack = await this.calculateStackPeak(stackInfo);

if (maxStack !== undefined ) {
stackInfo.stackPeak = maxStack;
}
}
}
}
} else {
Expand Down
Loading