/********************************************************************* * SEGGER MICROCONTROLLER GmbH * * Solutions for real time microcontroller applications * ********************************************************************** * * * (c) 1995 - 2019 SEGGER Microcontroller GmbH * * * * www.segger.com Support: support@segger.com * * * ********************************************************************** * * * Please note: * * * * Knowledge of this file may under no circumstances * * be used to write a similar product * * * * Thank you for your fairness ! * * * ********************************************************************** * * * Current version number will be inserted here * * when shipment is built. * * * ********************************************************************** ---------------------------------------------------------------------- File : FreeRTOSPlugin_CM4.js Purpose : Ozone FreeRTOS-awareness JavaScript Plugin for Cortex-M4 ---------------------------END-OF-HEADER------------------------------ */ /********************************************************************* * * Local Functions * ********************************************************************** */ /********************************************************************* * * GetTaskStackGrowDir * * Function description * Indicates if the task stack grows in positive (1) or negative (-1) memory direction * * Notes * (1) The stack grow direction depends on the FreeRTOS-port. * Currently, a positive grow direction is only used on the PIC architecture. */ function GetTaskStackGrowDir() { return -1; } /********************************************************************* * * GetTaskPrioName * * Function description * Returns the display text of a task priority * * Parameters * Priority: task priority (integer) */ function GetTaskPrioName(Priority) { var sName; if (Priority == 0) { sName = "Idle" } else if (Priority == 1) { sName = "Low" } else if (Priority == 2) { sName = "Normal"; } else if (Priority == 3) { sName = "High"; } else if (Priority == 4) { sName = "Highest"; } else { return Priority.toString(); } sName = sName + " (" + Priority + ")"; return sName; } /********************************************************************* * * GetTaskName * * Function description * Returns the display text of a task name * * Parameters * tcb: task control block (type tskTCB) * Addr: control block memory location */ function GetTaskName(tcb, Addr) { var sTaskName; sTaskName = Debug.evaluate("(char*)(*(tskTCB*)" + Addr + ").pcTaskName"); if (sTaskName == undefined) { sTaskName = Debug.evaluate("(char*)(*(TCB_t*)" + Addr + ").pcTaskName"); } if (tcb.uxTCBNumber != undefined) { sTaskName = "#" + tcb.uxTCBNumber + " \"" + sTaskName + "\""; } return sTaskName; } /********************************************************************* * * GetTaskID * * Function description * Returns the display text of a task ID * * Parameters * tcb: task control block (type tskTCB) * Addr: control block memory location */ function GetTaskID(tcb, Addr) { return "0x" + (tcb.uxTCBNumber == undefined ? Addr.toString(16) : tcb.uxTCBNumber.toString(16)); } /********************************************************************* * * GetTCB * * Function description * Returns the task control block of a task * * Parameters * Addr: control block memory location */ function GetTCB(Addr) { var tcb; tcb = Debug.evaluate("*(tskTCB*)" + Addr); if (tcb == undefined) { tcb = Debug.evaluate("*(TCB_t*)" + Addr); } return tcb; } /********************************************************************* * * GetTaskNotifyStateStr * * Function description * Returns the display string of a task notify state * * Parameters * tcb: task control block (type tskTCB) */ function GetTaskNotifyStateStr(tcb) { if (tcb.ucNotifyState == undefined) { return tcb.eNotifyState == undefined ? "N/A" : tcb.eNotifyState.toString(); } else { return tcb.ucNotifyState.toString() } } /********************************************************************* * * GetTaskStackInfoStr * * Function description * Returns a display text of the format " / " * * Parameters * tcb: task control block (type tskTCB) * * Notes * (1) pxEndOfStack is only available when FreeRTOS was compiled with * configRECORD_STACK_HIGH_ADDRESS == 1 */ function GetTaskStackInfoStr(tcb) { var FreeSpace; var UsedSpace; var Size; // GrowDir == 0 GrowDir == 1 // // pxStack | Low Addr | Stack Top | Stack Base | // | | | | // pxTopOfStack | | Stack Pointer | Stack Pointer | // | | | | // pxEndOfStack | High Addr | Stack Base | Stack Top | // if (GetTaskStackGrowDir() == 1) { // stack grows in positive address direction if (tcb.pxEndOfStack == undefined) { UsedSpace = tcb.pxTopOfStack - tcb.pxStack; FreeSpace = undefined; Size = undefined; } else { FreeSpace = tcb.pxEndOfStack - tcb.pxTopOfStack; UsedSpace = tcb.pxTopOfStack - tcb.pxStack; Size = FreeSpace + UsedSpace; } } else { // stack grows in negative address direction if (tcb.pxEndOfStack == undefined) { FreeSpace = tcb.pxTopOfStack - tcb.pxStack; UsedSpace = undefined; Size = undefined; } else { FreeSpace = tcb.pxTopOfStack - tcb.pxStack; UsedSpace = tcb.pxEndOfStack - tcb.pxTopOfStack; Size = FreeSpace + UsedSpace; } } return FreeSpace + " / " + (Size == undefined ? "N/A" : Size); } /********************************************************************* * * AddTask * * Function description * Adds a task to the task window * * Parameters * Addr: memory location of the task's control block (TCB) * CurrTaskAddr: memory location of the executing task's control block (TCB) * sState: state of the task (e.g. "executing") */ function AddTask(Addr, CurrTaskAddr, sState) { var tcb; var sTaskName; var sPriority; var sRunCnt; var sMutexCnt; var sTimeout; var sStackInfo; var sID; var sNotifiedValue; var sNotifyState; tcb = GetTCB(Addr); sTaskName = GetTaskName(tcb, Addr); sID = GetTaskID(tcb, Addr); sStackInfo = GetTaskStackInfoStr(tcb); sPriority = GetTaskPrioName(tcb.uxPriority); sNotifyState = GetTaskNotifyStateStr(tcb); sTimeout = (tcb.Timeout == undefined ? "N/A" : tcb.Timeout.toString()); sRunCnt = (tcb.ulRunTimeCounter == undefined ? "N/A" : tcb.ulRunTimeCounter.toString()); sNotifiedValue = (tcb.ulNotifiedValue == undefined ? "N/A" : tcb.ulNotifiedValue.toString()); sMutexCnt = (tcb.uxMutexesHeld == undefined ? "N/A" : tcb.uxMutexesHeld.toString()); if (Addr == CurrTaskAddr) { sState = "executing"; } Threads.add(sTaskName, sRunCnt, sPriority, sState, sTimeout, sStackInfo, sID, sMutexCnt, sNotifiedValue, sNotifyState, (Addr == CurrTaskAddr) ? undefined : Addr); } /********************************************************************* * * AddList * * Function description * Adds all tasks of a task list to the task window * * Parameters * List: task list (type xLIST) * CurrTaskAddr: memory location of the executing task's control block (TCB) * sState: common state of all tasks within 'list' */ function AddList(List, CurrTaskAddr, sState) { var i; var Index; var Item; var TaskAddr; if ((List != undefined) && (List.uxNumberOfItems > 0)) { Index = List.xListEnd.pxNext; for (i = 0; i < List.uxNumberOfItems; i++) { Item = Debug.evaluate("*(xLIST_ITEM *)" + Index); TaskAddr = Item != 0 ? Item.pvOwner : 0; if (TaskAddr != 0) { AddTask(TaskAddr, CurrTaskAddr, sState); } Index = Item.pxNext; if (i > 1000) { // infinite loop guard break; } } } } /********************************************************************* * * API Functions * ********************************************************************** */ /********************************************************************* * * init * * Function description * Initializes the task window */ function init() { Threads.clear(); Threads.newqueue("Task List"); Threads.setColumns("Name", "Run Count", "Priority", "Status", "Timeout", "Stack Info", "ID", "Mutex Count", "Notified Value", "Notify State"); Threads.setColor("Status", "ready", "executing", "blocked"); } /********************************************************************* * * update * * Function description * Updates the task window */ function update() { var i; var pList; var List; var MaxPriority; var CurrTaskAddr; Threads.clear(); if((Debug.evaluate("pxCurrentTCB") == 0) || (Debug.evaluate("pxCurrentTCB") == undefined)) { return; } MaxPriority = Debug.evaluate("uxTopReadyPriority"); CurrTaskAddr = Debug.evaluate("pxCurrentTCB"); for (i = MaxPriority; i >= 0; i--) { List = Debug.evaluate("pxReadyTasksLists[" + i + "]"); AddList(List, CurrTaskAddr, "ready"); } pList = Debug.evaluate("pxDelayedTaskList"); if (pList != 0) { List = Debug.evaluate("*(xLIST *)" + pList); AddList(List, CurrTaskAddr, "blocked"); } pList = Debug.evaluate("pxOverflowDelayedTaskList"); if (pList != 0) { List = Debug.evaluate("*(xLIST*)" + pList); AddList(List, CurrTaskAddr, "blocked"); } List = Debug.evaluate("xSuspendedTaskList"); if (List != 0) { AddList(List, CurrTaskAddr, "suspended"); } } /********************************************************************* * * getregs * * Function description * Returns the register set of a task. * For ARM cores, this function is expected to return the values * of registers R0 to R15 and PSR. * * Parameters * hTask: integer number identifiying the task. * Identical to the last parameter supplied to method Threads.add. * For convenience, this should be the address of the TCB. * * Return Values * An array of unsigned integers containing the tasks register values. * The array must be sorted according to the logical indexes of the regs. * The logical register indexing scheme is defined by the ELF-DWARF ABI. * ********************************************************************** */ function getregs(hTask) { var i; var SP; var LR; var Addr; var tcb; var aRegs = new Array(17); tcb = GetTCB(hTask); SP = tcb.pxTopOfStack; Addr = SP; /* the following registers are pushed by the FreeRTOS-scheduler */ // // R4...R11 // for (i = 4; i < 12; i++) { aRegs[i] = TargetInterface.peekWord(Addr); Addr += 4; } // // EXEC_RET // LR = TargetInterface.peekWord(Addr); Addr += 4; // // S16...S31 // if ((LR & 0x10) != 0x10) { // FP context has been saved? Addr += 4*16; // skip S16..S31 } /* the following registers are pushed by the ARM core */ // // R0...R3 // for (i = 0; i < 4; i++) { aRegs[i] = TargetInterface.peekWord(Addr); Addr += 4; } // // R12, LR, PC, PSR // aRegs[12] = TargetInterface.peekWord(Addr); Addr += 4; aRegs[14] = TargetInterface.peekWord(Addr); Addr += 4; aRegs[15] = TargetInterface.peekWord(Addr); Addr += 4; aRegs[16] = TargetInterface.peekWord(Addr); Addr += 4; // // S0..S15 // if ((LR & 0x10) != 0x10) { // FP context has been saved? Addr += 4*18; // skip S0...S15 } if (aRegs[16] & (1<<9)) { // Stack has been 8-byte aligned Addr += 4; } // // SP // aRegs[13] = Addr; return aRegs; } /********************************************************************* * * getContextSwitchAddrs * * Functions description * Returns an unsigned integer array containing the base addresses * of all functions that complete a task switch when executed. */ function getContextSwitchAddrs() { var aAddrs; var Addr; Addr = Debug.evaluate("&vTaskSwitchContext"); if (Addr != undefined) { aAddrs = new Array(1); aAddrs[0] = Addr; return aAddrs; } return []; } /********************************************************************* * * getOSName() * * Functions description: * Returns the name of the RTOS this script supplies support for */ function getOSName() { return "FreeRTOS"; }