You can monitor stack and frame for all processes.
In initialization execute this once (adapt constants and structures to your liking):
Code
for i := 1 to NUMBER_OF_PROCESSES do
Runtime.General.Processes[i].Stack.Valid := true;
Runtime.General.Processes[i].Frame.Valid := true;
Runtime.General.Processes[i].Stack.MinFree := $FFFF;
Runtime.General.Processes[i].Frame.MinFree := $FFFF;
endfor;
Put this proc somewhere:
Code
procedure CheckFrameAndStack;
const
BAD_RESULT: integer = -1; //$FFFF
var
i: byte;
begin // Main_Proc, HcpComm and RT_Actions are running processes
if CheckStackValid(Main_Proc) = BAD_RESULT then Runtime.General.Processes[IDX_MAIN ].Stack.Valid := false; endif;
if CheckStackValid(HcpComm) = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM ].Stack.Valid := false; endif;
if CheckStackValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Stack.Valid := false; endif;
if CheckFrameValid(Main_Proc) = BAD_RESULT then Runtime.General.Processes[IDX_MAIN ].Frame.Valid := false; endif;
if CheckFrameValid(HcpComm) = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM ].Frame.Valid := false; endif;
if CheckFrameValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Frame.Valid := false; endif;
for i := 1 to NUMBER_OF_PROCESSES do
Runtime.General.PowerUp.StackFrameCorrupted := Runtime.General.PowerUp.StackFrameCorrupted or (not Runtime.General.Processes[i].Stack.Valid) or (not Runtime.General.Processes[i].Frame.Valid);
endfor;
if Runtime.General.PowerUp.StackFrameCorrupted then // if stack/frame was corrupted at least once since power up
Buzz(1000); // TODO: in production buzzer should not be heard - save event instead
endif;
end;
In each process execute something like this:
Code
process HcpComm(120, 280: iData);
begin
// update local stack and frame consumption statistics:
Lock(Self);
if GetStackFree(HcpComm) < Runtime.General.Processes[IDX_HCP_COMM].Stack.MinFree then
Runtime.General.Processes[IDX_HCP_COMM].Stack.MinFree := GetStackFree(HcpComm);
endif;
if GetFrameFree(HcpComm) < Runtime.General.Processes[IDX_HCP_COMM].Frame.MinFree then
Runtime.General.Processes[IDX_HCP_COMM].Frame.MinFree := GetFrameFree(HcpComm);
endif;
Inc(Runtime.General.Processes[IDX_HCP_COMM].ScanCnt);
UnLock(Self);
// put your process code here
Schedule; // not for Main - goto next process (some processes do not need this)
end;
Unfortunately there is nothing like Self in AvrCo, or at least something like GetCurrentProcessID() so you will have to repeat that code with GetStackFree(PROCESS_NAME) and GetFrameFree(PROCESS_NAME) in each process (even Main). Ugly but so far no other way to achieve this. Because of this problem it is not possible to make library for this, but we have to customize code for each project.
Then you add this to your main loop:
Code
loop // <<< ----------------------- Main RunTime loop ----------------------- >>>
WatchDogTrig;
Lock(Self);
// update global stack and frame corruption diagnostics:
CheckFrameAndStack;
// update local stack and frame consumption statistics:
if GetStackFree(Main_Proc) < Runtime.General.Processes[IDX_MAIN].Stack.MinFree then
Runtime.General.Processes[IDX_MAIN].Stack.MinFree := GetStackFree(Main_Proc);
endif;
if GetFrameFree(Main_Proc) < Runtime.General.Processes[IDX_MAIN].Frame.MinFree then
Runtime.General.Processes[IDX_MAIN].Frame.MinFree := GetFrameFree(Main_Proc);
endif;
Inc(Runtime.General.Processes[IDX_MAIN].ScanCnt);
UnLock(Self);
// your code here
endloop;
When communication requests stack/frame status of each process, you can create resulting strings in a way like this:
Code
for i := 1 to NUMBER_OF_PROCESSES do
StackFreeStr := StackFreeStr + IntToStr(Runtime.General.Processes[i].Stack.MinFree);
FrameFreeStr := FrameFreeStr + IntToStr(Runtime.General.Processes[i].Frame.MinFree);
StackValidStr := StackValidStr + HcpBoolToStr(Runtime.General.Processes[i].Stack.Valid);
FrameValidStr := FrameValidStr + HcpBoolToStr(Runtime.General.Processes[i].Frame.Valid);
//if i <> NUMBER_OF_PROCESSES then
// StackFreeStr := StackFreeStr + ',';
// FrameFreeStr := FrameFreeStr + ',';
// StackValidStr := StackValidStr + ',';
// FrameValidStr := FrameValidStr + ',';
//endif;
endfor;
At the end final communication reply from your AvrCo for command to get stack/frame statistics and other runtime info could be something like this (this example has 7 processes including main):
Quote
Tick=74
Now=20150317T081938Z
PowerUpMoment=20150317T081824Z
TotalDaysRunning=0.0008565
DeviceID=1
FirstPage=646
LastPage=651
CurrentPagePointer=652
OverwriteOldEvents=1
MinLogLevelFilter=255
StackFrameCorrupted=0
StackValid=1,1,1,1,1,1,1
StackMinFree=89,77,7,21,49,93,32
FrameValid=1,1,1,1,1,1,1
FrameMinFree=108,256,34,45,139,200,31
Sim=0,0,0,0
DI=1,1,1,1,1,1
DO=1,1,1,1,1,1
AI=1,1,1,1,1,1,1,1
AO=1,1,1
MCUCSR=3
ProcessScanCounters=129,4,1539,1539,75,14,1539
It is now very easy to see if you need more or less stack and frame in all your processes.
This is not exact copy/paste and you will need to make your own structures, but you get the idea. Of course, this is an overkill for small projects