116 lines
3.4 KiB
XML
116 lines
3.4 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<TcPlcObject Version="1.1.0.1">
|
|
<POU Name="FB_JobQueue" Id="{b05c10aa-a132-426c-9adb-9c3d92e348cd}" SpecialFunc="None">
|
|
<Declaration><![CDATA[FUNCTION_BLOCK FB_JobQueue
|
|
VAR_INPUT
|
|
xEnableAging : BOOL := FALSE;
|
|
END_VAR
|
|
VAR_OUTPUT
|
|
END_VAR
|
|
VAR
|
|
_astJobQueue : ARRAY[0..(GVL_Scheduler.MAX_JOBS_IN_QUEUE - 1)] OF ST_TransJob;
|
|
_uiJobCount : UINT := 0;
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// If aging is enable recalculate priorities
|
|
IF xEnableAging THEN
|
|
M_CalcAgingPrio();
|
|
END_IF
|
|
]]></ST>
|
|
</Implementation>
|
|
<Method Name="FB_Init" Id="{59b2fc0f-4c7e-4fd5-97a2-d54f83d37be4}">
|
|
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
|
//The return value is not evaluated. For a specific influence, you can also declare the
|
|
//methods explicitly and provide additional code there with the standard initialization
|
|
//code. You can evaluate the return value.
|
|
METHOD FB_Init: BOOL
|
|
VAR_INPUT
|
|
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
|
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
|
END_VAR
|
|
VAR
|
|
_uiCnt : UINT;
|
|
END_VAR]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// No jobs in queue
|
|
_uiJobCount := 0;]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
<Method Name="M_AddJob" Id="{c7959fb9-7c57-4429-b989-c0befdd4ac38}">
|
|
<Declaration><![CDATA[METHOD M_AddJob : BOOL
|
|
VAR_INPUT
|
|
stJob : ST_TransJob;
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// Check if queue is full
|
|
IF _uiJobCount >= GVL_Scheduler.MAX_JOBS_IN_QUEUE THEN
|
|
M_AddJob := FALSE;
|
|
RETURN;
|
|
END_IF
|
|
|
|
_astJobQueue[_uiJobCount] := stJob;
|
|
_uiJobCount := _uiJobCount + 1;
|
|
M_AddJob := TRUE;]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
<Method Name="M_CalcAgingPrio" Id="{7ee1cc23-b7ac-4255-862a-74b0b696f2cb}">
|
|
<Declaration><![CDATA[METHOD PRIVATE M_CalcAgingPrio
|
|
VAR
|
|
i : UINT;
|
|
END_VAR]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// Calculate ageing priority with overflow check
|
|
FOR i := 0 TO _uiJobCount DO
|
|
IF _astJobQueue[i].uiPrio < GVL_Scheduler.MAX_PRIORITY THEN
|
|
IF _astJobQueue[i].uiPrio > (GVL_Scheduler.MAX_PRIORITY - GVL_Scheduler.AGING_STEP) THEN
|
|
_astJobQueue[i].uiPrio := GVL_Scheduler.MAX_PRIORITY;
|
|
ELSE
|
|
_astJobQueue[i].uiPrio := _astJobQueue[i].uiPrio + GVL_Scheduler.AGING_STEP;
|
|
END_IF
|
|
END_IF
|
|
END_FOR]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
<Method Name="M_GetHighest" Id="{26fa0379-d921-41a3-a15c-b3ff597c1d37}">
|
|
<Declaration><![CDATA[METHOD M_GetHighest : BOOL
|
|
VAR_OUTPUT
|
|
stJob : ST_TransJob;
|
|
END_VAR
|
|
VAR
|
|
_uiIndex : UINT := 0;
|
|
_rDynPrio : REAL;
|
|
|
|
_uiCnt : UINT;
|
|
END_VAR]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// No jobs to return
|
|
IF _uiJobCount = 0 THEN
|
|
M_GetHighest := FALSE;
|
|
RETURN;
|
|
END_IF
|
|
|
|
// Find job with highest priority also update dyn prio
|
|
FOR _uiCnt := 0 TO (_uiJobCount-1) DO
|
|
// Check for highest priority
|
|
IF _astJobQueue[_uiCnt].uiPrio > _astJobQueue[_uiIndex].uiPrio THEN
|
|
_uiIndex := _uiCnt;
|
|
END_IF
|
|
END_FOR
|
|
|
|
// Output job
|
|
stJob := _astJobQueue[_uiIndex];
|
|
|
|
// Close gap with last element
|
|
_astJobQueue[_uiIndex] := _astJobQueue[_uiJobCount - 1];
|
|
|
|
// Adjust job number in queue
|
|
_uiJobCount := _uiJobCount - 1;
|
|
|
|
// Repost success
|
|
M_GetHighest := TRUE;]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
</POU>
|
|
</TcPlcObject> |