From c318d54995c586a928a51bc051b965326f9b9ee0 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Sat, 17 Oct 2020 16:34:16 +0300 Subject: [PATCH] Debug: freertos gdb plugin. --- debug/FreeRTOS/FreeRTOS.py | 107 ++++++ debug/FreeRTOS/FreeRTOSgdb/EventGroup.py | 31 ++ debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py | 139 ++++++++ debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py | 84 +++++ debug/FreeRTOS/FreeRTOSgdb/List.py | 103 ++++++ debug/FreeRTOS/FreeRTOSgdb/QueueTools.py | 110 ++++++ debug/FreeRTOS/FreeRTOSgdb/Task.py | 63 ++++ debug/FreeRTOS/FreeRTOSgdb/Types.py | 14 + debug/FreeRTOS/FreeRTOSgdb/__init__.py | 0 debug/FreeRTOS/LICENSE | 340 +++++++++++++++++++ debug/FreeRTOS/README.md | 120 +++++++ make/rules.mk | 1 + 12 files changed, 1112 insertions(+) create mode 100644 debug/FreeRTOS/FreeRTOS.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/EventGroup.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/List.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/QueueTools.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/Task.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/Types.py create mode 100644 debug/FreeRTOS/FreeRTOSgdb/__init__.py create mode 100644 debug/FreeRTOS/LICENSE create mode 100644 debug/FreeRTOS/README.md diff --git a/debug/FreeRTOS/FreeRTOS.py b/debug/FreeRTOS/FreeRTOS.py new file mode 100644 index 00000000..036e18f3 --- /dev/null +++ b/debug/FreeRTOS/FreeRTOS.py @@ -0,0 +1,107 @@ +# File: FreeRTOS.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains some python code that utilizes the GDB API +# to inspect information about the FreeRTOS internal state. The +# idea is to provide the user with the ability to inspect information +# about the tasks, queues, mutexs, etc. +# + +from os import path +import sys + +directory, file = path.split(__file__) +directory = path.expanduser(directory) +directory = path.abspath(directory) + +sys.path.append(directory) + +import gdb +import pprint + +from FreeRTOSgdb.Types import StdTypes +from FreeRTOSgdb.List import ListInspector +from FreeRTOSgdb.GDBCommands import ShowHandleName, ShowRegistry, ShowList +from FreeRTOSgdb.GDBCommands import ShowQueueInfo + + +class Scheduler: + def __init__(self): + + self._blocked = ListInspector("xSuspendedTaskList") + self._delayed1 = ListInspector("xDelayedTaskList1") + self._delayed2 = ListInspector("xDelayedTaskList2") + self._readyLists = [] + readyTasksListsStr = "pxReadyTasksLists" + readyListsSym, methodType = gdb.lookup_symbol(readyTasksListsStr) + if readyListsSym != None: + readyLists = readyListsSym.value() + minIndex, maxIndex = readyLists.type.range() + for i in range(minIndex, maxIndex + 1): + readyList = readyLists[i] + FRReadyList = ListInspector(readyList) + self._readyLists.append(FRReadyList) + else: + print("Failed to Find Symbol: %s" % readyTasksListsStr) + raise ValueError("Invalid Symbol!") + + def ShowTaskList(self): + self.PrintTableHeader() + for i, rlist in enumerate(self._readyLists): + if i == 0: + items = rlist.GetElements("TCB_t", 0) + else: + items = rlist.GetElements("TCB_t", 1) + if len(items) > 0: + print("Ready List {%d}: Num Tasks: %d" % (i, len(items))) + for tcb, val in items: + self.PrintTaskFormatted(tcb) + + items = self._blocked.GetElements("TCB_t") + print("Blocked List: Num Tasks: %d" % len(items)) + for tcb, val in items: + self.PrintTaskFormatted(tcb) + + items = self._delayed1.GetElements("TCB_t") + print("Delayed {1}: Num Tasks: %d" % len(items)) + for tcb, val in items: + self.PrintTaskFormatted(tcb, val) + + items = self._delayed2.GetElements("TCB_t") + print("Delayed {2}: Num Tasks: %d" % len(items)) + for tcb, val in items: + self.PrintTaskFormatted(tcb, val) + + def PrintTableHeader(self): + print("%16s %3s %4s" % ("Name", "PRI", "STCK")) + + def PrintTaskFormatted(self, task, itemVal=None): + topStack = task["pxTopOfStack"] + stackBase = task["pxStack"] + highWater = topStack - stackBase + taskName = task["pcTaskName"].string() + taskPriority = task["uxPriority"] + if itemVal != None: + print("%16s %3s %4s %5s" % (taskName, taskPriority, highWater, itemVal)) + else: + print("%16s %3s %4s" % (taskName, taskPriority, highWater)) + + +class ShowTaskList(gdb.Command): + """Generate a print out of the current tasks and their states.""" + + def __init__(self): + super(ShowTaskList, self).__init__("show Task-List", gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + sched = Scheduler() + sched.ShowTaskList() + + +ShowRegistry() +ShowList() +ShowTaskList() +ShowHandleName() +ShowQueueInfo() diff --git a/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py b/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py new file mode 100644 index 00000000..3fa4922b --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py @@ -0,0 +1,31 @@ +# File: EventGroup.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the implementation of a Event Group Inspector + + +import gdb +from .List import ListInspector +from .Task import TaskInspector + + +class EventGroupInspector: + EvtGrpType = gdb.lookup_type("EventGroup_t") + + def __init__(self, handle): + """""" + self._evtgrp = gdb.Value(handle).cast(EventGroupInspector.EvtGrpType) + + def GetTasksWaiting(self): + """""" + taskListObj = self._evtgrp["xTasksWaitingForBits"] + taskList = ListInspector(taskListObj) + return taskList.GetElements(TaskInspector.TCBType) + + def GetEventBits(self): + """Get the Event Flag Bits + @return L{gdb.Value} of EventBits_t + """ + return self._evtgrp["uxEventBits"] diff --git a/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py b/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py new file mode 100644 index 00000000..ba811e3e --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py @@ -0,0 +1,139 @@ +# File: GDBCommands.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the implementation of some custom +# GDB commands for Inspecting the FreeRTOS state + + +import gdb +from .List import ListInspector +from .Task import TaskInspector +from .HandleRegistry import HandleRegistry +from .QueueTools import * + + +class ShowQueueInfo(gdb.Command): + """Generate a print out of info about a particular + set of queues. + """ + + def __init__(self): + super(ShowQueueInfo, self).__init__("show Queue-Info", gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + + qTypes = [] + if len(argv) > 0: + for a in argv: + try: + qType = QueueMode.Map[a] + qTypes.append(qType) + except KeyError: + print("Arg %s does not map to a Queue Type!" % a) + + reg = HandleRegistry() + qToShow = [] + if len(qTypes) > 0: + # We will only print info about queues + for qType in qTypes: + qObjs = reg.FilterBy(qType) + qToShow.extend(qObjs) + else: + qToShow = reg.FilterBy(None) + + print("Num Queues: %d" % len(qToShow)) + print("%20s %4s %16s %16s" % ("NAME", "CNT", "SEND", "RECEIVE")) + for q in qToShow: + self.PrintQueueInfo(q) + + def PrintQueueInfo(self, q): + """Print Info about the Queue""" + sendList = q.GetTasksWaitingToSend() + rxList = q.GetTasksWaitingToReceive() + + # print("TxLen: %d, RxLen: %d" % (len(sendList), len(rxList))) + + maxCount = max(len(sendList), len(rxList)) + outputFmt = "%20s %4s %16s %16s" + if maxCount == 0: + print(outputFmt % (q.GetName(), q.GetQueueMessagesWaiting(), "", "")) + else: + + for i in range(0, maxCount): + txName = "" + if i < len(sendList): + tcbRef, val = sendList[i] + tcb = TaskInspector(tcbRef) + txName = tcb.GetName() + rxName = "" + if i < len(rxList): + tcbRef, val = rxList[i] + tcb = TaskInspector(tcbRef) + rxName = tcb.GetName() + + if i == 0: + print( + outputFmt + % (q.GetName(), q.GetQueueMessagesWaiting(), txName, rxName) + ) + else: + print(outputFmt % ("", "", txName, rxName)) + + +class ShowHandleName(gdb.Command): + """Generate a print out of the handle by name""" + + def __init__(self): + super(ShowHandleName, self).__init__("show Handle-Name", gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + if len(argv) != 1: + print("Invalid Argument: Requires one handle arg") + handle = int(argv[0], 0) + reg = HandleRegistry() + name = reg.GetName(handle) + print("Handle 0x%08x: %s" % (handle, name)) + + +class ShowRegistry(gdb.Command): + """Generate a print out of the queue handle registry""" + + def __init__(self): + super(ShowRegistry, self).__init__("show Handle-Registry", gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + reg = HandleRegistry() + reg.PrintRegistry() + + +class ShowList(gdb.Command): + """Generate a print out of the elements in a list + passed to this command. User must pass a symbol that + will be looked up. + """ + + def __init__(self): + super(ShowList, self).__init__( + "show List-Handle", gdb.COMMAND_SUPPORT, gdb.COMPLETE_SYMBOL + ) + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + + CastTypeStr = None + if len(argv) > 0: + symbolArg = argv[0] + + if len(argv) > 1: + CastTypeStr = argv[1] + + listVal = ListInspector(symbolArg) + + elems = listVal.GetElements(CastTypeStr) + + for elem in elems: + print("Elem: %s" % str(elem)) diff --git a/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py b/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py new file mode 100644 index 00000000..1682c917 --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py @@ -0,0 +1,84 @@ +# File: HandleRegistry.py +# Author: Carl Allendorph +# Date: 06NOV2014 +# +# Description: +# THis file contains the implementation of a class for accessing the +# handle registry. This contains a mapping of queue handles to +# strings for labeling purposes. + +import gdb +from .Types import StdTypes +from .QueueTools import * + + +class HandleRegistry: + """The FreeRTOS system can be configured with a table that + associates a name with a QueueHandle_t. + This class can be used to access this table and + label queue/mutex/semaphore/event groups + """ + + def __init__(self, regSymbol="xQueueRegistry"): + symbol, methodObj = gdb.lookup_symbol(regSymbol) + self._registry = symbol.value() + self._minIndex = 0 + self._maxIndex = 0 + self._minIndex, self._maxIndex = self._registry.type.range() + + def GetName(self, handle): + """Find the string name associated with a queue + handle if it exists in the registry + """ + for i in range(self._minIndex, self._maxIndex): + elem = self._registry[i] + h = elem["xHandle"] + val = h.cast(StdTypes.uint32_t) + if handle == val: + print("Found Entry for: %x" % handle) + name = elem["pcQueueName"].string() + return name + + def PrintRegistry(self): + for i in range(self._minIndex, self._maxIndex): + elem = self._registry[i] + h = elem["xHandle"] + if h != 0: + name = elem["pcQueueName"].string() + print("%d: %3s %16s" % (i, h, name)) + + def FilterBy(self, qMode): + + """Retrieve a List of Mutex Queue Handles""" + resp = [] + for i in range(self._minIndex, self._maxIndex): + elem = self._registry[i] + h = elem["xHandle"] + if h != 0: + name = elem["pcQueueName"].string() + q = QueueInspector(h) + q.SetName(name) + if qMode != None: + qType = q.GetQueueType() + if qType != None: + if qType == qMode: + resp.append(q) + + else: + print("qType == None") + else: + resp.append(q) + + return resp + + def GetMutexes(self): + """Retrieve all the Mutex Objects in the Handle Registry""" + return self.FilterBy(QueueMode.MUTEX) + + def GetSemaphores(self): + """Retrieve all the Semaphore Objects in the Handle Registry""" + return self.FilterBy(QueueMode.BINARY) + + def GetQueues(self): + """Retrieve all the Queue Objects in the Handle Registry""" + return self.FilterBy(QueueMode.QUEUE) diff --git a/debug/FreeRTOS/FreeRTOSgdb/List.py b/debug/FreeRTOS/FreeRTOSgdb/List.py new file mode 100644 index 00000000..332993f3 --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/List.py @@ -0,0 +1,103 @@ +# File: List.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the class for inspecting +# a FreeRTOS List Object +# + + +import gdb + +from .Types import StdTypes + + +class ListInspector: + """FreeRTOS List Inspector Object""" + + ListType = gdb.lookup_type("List_t") + + def __init__(self, handle): + """""" + self._list = None + # print("List: Handle: %s" % handle) + self.Assign(handle) + + def Assign(self, listObj): + try: + if listObj.type == ListInspector.ListType: + self._list = listObj + return + else: + raise TypeError("Invalid List Object Type!") + except Exception as exc: + # print(" Failed to assign from List object: %s" % str(exc)) + pass + + symbol, methodObj = gdb.lookup_symbol(listObj) + if symbol != None: + self._list = symbol.value() + else: + addrInt = int(listObj, 0) + listObjPtr = gdb.Value(addrInt).cast(ListInspector.ListType.pointer()) + self._list = listObjPtr.dereference() + + def GetElements(self, CastTypeStr=None, startElem=1): + """Get the Elements of the list as an array of + gdb.Value type objects. + @param CastTypeStr string name of the type of object that + we will cast the void *pvOwner elements of the list to. + User can also pass a L{gdb.Type} object as the type + If None, we will simply cast to uint32_t and print these + as hex values. + @param startElem This is a flag to indicate whether + we will start getting elements starting at 0 or 1. Note + that this is to deal with some non-consistent behavior + of some of the TCB Task lists. + """ + if self._list != None: + + CastType = None + if CastTypeStr != None: + if type(CastTypeStr) == str: + try: + CastType = gdb.lookup_type(CastTypeStr).pointer() + except: + print("Failed to find type: %s" % CastTypeStr) + elif type(CastTypeStr) == gdb.Type: + CastType = CastTypeStr.pointer() + + resp = [] + numElems = self._list["uxNumberOfItems"] + # print("List Elements: %d" % numElems) + index = self._list["pxIndex"] + + if numElems > 0 and numElems < 200: + + if startElem == 0: + curr = index + else: + curr = index["pxPrevious"] + + for i in range(0, numElems): + owner = curr["pvOwner"] + + ownerObj = None + if CastType != None: + castObjPtr = owner.cast(CastType) + castObj = castObjPtr.dereference() + ownerObj = castObj + else: + ownerUInt = owner.cast(StdTypes.uint32_t) + ownerObj = ownerUInt + + itemVal = curr["xItemValue"] + resp.append((ownerObj, itemVal.cast(StdTypes.uint32_t))) + + curr = curr["pxPrevious"] + + return resp + + else: + raise ValueError("Invalid List Object - Possibly Failed to Initialize!") diff --git a/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py b/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py new file mode 100644 index 00000000..b7ac9601 --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py @@ -0,0 +1,110 @@ +# File: Queue.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the implementation of a Queue Inspector +# class. +# + +import gdb +from .List import ListInspector +from .Task import TaskInspector + + +class QueueMode: + QUEUE = 0 + MUTEX = 1 + COUNTING = 2 + BINARY = 3 + RECURSIVE = 4 + + Map = None + + @staticmethod + def IsValid(qType): + if ( + qType == QueueMode.QUEUE + or qType == QueueMode.MUTEX + or qType == QueueMode.COUNTING + or qType == QueueMode.BINARY + or qType == QueueMode.RECURSIVE + ): + return True + else: + return False + + +QueueMap = { + "mutex": QueueMode.MUTEX, + "queue": QueueMode.QUEUE, + "semaphore": QueueMode.BINARY, + "counting": QueueMode.COUNTING, + "recursive": QueueMode.RECURSIVE, +} + +QueueMode.Map = QueueMap + + +class QueueInspector: + + QueueType = gdb.lookup_type("Queue_t") + + def __init__(self, handle): + """""" + # print("Queue: Handle: %s" % handle) + self.name = None + queueObjPtr = None + if type(handle) == gdb.Value: + queueObjPtr = handle.cast(QueueInspector.QueueType.pointer()) + self._queue = queueObjPtr.dereference() + else: + queueObjPtr = gdb.Value(handle).cast(QueueInspector.QueueType.pointer()) + self._queue = queueObjPtr.dereference() + + def GetName(self): + return self.name + + def SetName(self, name): + self.name = name + + def GetTasksWaitingToSend(self): + """Retrieve a list of gdb.Value objects of type + TCB that are the tasks that are currently waiting to + send data on this queue object. + """ + sendList = ListInspector(self._queue["xTasksWaitingToSend"]) + + return sendList.GetElements(TaskInspector.TCBType) + + def GetTasksWaitingToReceive(self): + """Retrieve a list of gdb.Value objects of Type + TCB that are the tasks that are currently waiting to + receive data on this queue object. + """ + rxList = ListInspector(self._queue["xTasksWaitingToReceive"]) + return rxList.GetElements(TaskInspector.TCBType) + + def GetQueueMessagesWaiting(self): + """Return the number of messages waiting as a + L{gdb.Value} object + """ + return self._queue["uxMessagesWaiting"] + + def GetQueueType(self): + """Return the Type of the Queue as a enumerated number""" + try: + qType = self._queue["ucQueueType"] + if QueueMode.IsValid(int(qType)): + return qType + else: + raise ValueError( + "Invalid Queue Type In Queue Object! Are you sure this is a Queue Handle?" + ) + + except Exception as exc: + # If the TRACE functionality of the RTOS is not enabled, + # then the queue type will not be availabe in the queue + # handle - so we return None + print("Failed to get Type: %s" % str(exc)) + return None diff --git a/debug/FreeRTOS/FreeRTOSgdb/Task.py b/debug/FreeRTOS/FreeRTOSgdb/Task.py new file mode 100644 index 00000000..04da3bbc --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/Task.py @@ -0,0 +1,63 @@ +# File: Task.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the implementation of a class to use for +# inspecting the state of a FreeRTOS Task in GDB +# + +import gdb + + +class TaskInspector: + + TCBType = gdb.lookup_type("TCB_t") + + def __init__(self, handle): + self._tcb = None + # print("Task: Pass Handle: %s" % str(handle)) + + try: + if handle.type == TaskInspector.TCBType: + self._tcb = handle + return + else: + print("Handle Type: %s" % str(handle.type)) + + except AttributeError as aexc: + print("Attribute Error: %s" % str(aexc)) + pass + except Exception as exc: + print("Error Initializing Task Inspector: %s" % str(exc)) + raise + + try: + tcbPtr = gdb.Value(handle).cast(TaskInspector.TCBType.pointer()) + self._tcb = tcbPtr.dereference() + return + except Exception as exc: + print("Failed to convert Handle Pointer: %s" % str(handle)) + + self._tcb = handle + + def GetName(self): + if self._tcb != None: + return self._tcb["pcTaskName"].string() + else: + raise ValueError("Invalid TCB") + + def GetPriority(self): + if self._tcb != None: + return self._tcb["uxPriority"] + else: + raise ValueError("Invalid TCB") + + def GetStackMargin(self): + if self._tcb != None: + topStack = self._tcb["pxTopOfStack"] + stackBase = self._tcb["pxStack"] + highWater = topStack - stackBase + return highWater + else: + raise ValueError("Invalid TCB") diff --git a/debug/FreeRTOS/FreeRTOSgdb/Types.py b/debug/FreeRTOS/FreeRTOSgdb/Types.py new file mode 100644 index 00000000..d598d50a --- /dev/null +++ b/debug/FreeRTOS/FreeRTOSgdb/Types.py @@ -0,0 +1,14 @@ +# File: Types.py +# Author: Carl Allendorph +# Date: 05NOV2014 +# +# Description: +# This file contains the implementation of some +# standard types + +import gdb + + +class StdTypes: + uint32_t = gdb.lookup_type("uint32_t") + uint16_t = gdb.lookup_type("uint16_t") diff --git a/debug/FreeRTOS/FreeRTOSgdb/__init__.py b/debug/FreeRTOS/FreeRTOSgdb/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/debug/FreeRTOS/LICENSE b/debug/FreeRTOS/LICENSE new file mode 100644 index 00000000..d6a93266 --- /dev/null +++ b/debug/FreeRTOS/LICENSE @@ -0,0 +1,340 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff --git a/debug/FreeRTOS/README.md b/debug/FreeRTOS/README.md new file mode 100644 index 00000000..f5d2b85e --- /dev/null +++ b/debug/FreeRTOS/README.md @@ -0,0 +1,120 @@ +FreeRTOS-GDB +============ + +Python API Library for inspecting FreeRTOS Objects in GDB + +Basically, the FreeRTOS internal state is kind of hard to inspect +when working with GDB. This project provides some scripts for GDB's +Python API that make accessing some of these internals a little easier +to inspect. + +##Requirements: + +1. You need to have the python API enabled in your version of GDB. This is a + compile time option when building GDB. You should be able to do something + like this: +``` + gdb> python print "Hello World" +``` + +and get predictable results. If it throws an error - then you don't have +python compiled in your version of GDB. + +2. Need to be using FreeRTOS 8.0+. This code could probably be used with FreeRTOS + version 7.0 or previous versions, but the current code doesn't support it. + +3. You need to use the Handle Registry for Queue info to be any use. + Note that this only works for Queue based objects and not + for EventGroups + +4. You need to put the FreeRTOS-GDB/src directory on your python path: +``` + $> export PYTHONPATH=~/src/FreeRTOS-GDB/src/ +``` + +How To Use: +``` +$> gdb ./bin/program.elf +(gdb) c +Program runs on embedded device, sets up tasks, and queues + +(gdb) source ~/FreeRTOS-GDB/src/FreeRTOS.py +(gdb) show Task-List + Name PRI STCK +Ready List {0}: Num Tasks: 1 + IDLE 0 107 +Blocked List: Num Tasks: 11 + EMAC Task 1 239 + AFEC0 Task 1 295 + LDSENS Task 1 195 + AFEC1 Task 1 295 + LineSample Task 1 281 + DMAUART0 1 225 + Log Task 1 273 + BAT Task 1 169 + Rx Task 1 421 + Mng Task 2 551 + Cell Task 1 275 +Delayed {1}: Num Tasks: 5 + Tmr Svc 3 355 62254 + WLAN Task 1 205 13817 + Init Task 1 445 10015 + LED Task 1 179 7105 + DMACOM1 1 265 7065 +Delayed {2}: Num Tasks: 0 + +(gdb) show Queue-Info mutex +Num Queues: 6 + NAME CNT SEND RECEIVE + LOG:LOCK 1 NONE NONE + STREAM:LOCK 1 NONE NONE + TWI:MUTEX 1 NONE NONE + CC3000:LOCK 1 NONE NONE + WLAN:LOCK 0 NONE NONE + SPI:LOCK 1 NONE NONE + +(gdb) show Queue-Info queue +Num Queues: 14 + NAME CNT SEND RECEIVE + TmrQ 0 Tmr Svc + LOG:MSGPOOL 12 NONE NONE + LOG:MSGQ 0 Log Task + TWI:QUEUE 0 NONE NONE + SPI:QUEUE 0 NONE NONE + DMAAFEC:POOL 1 NONE NONE + DMAAFEC:QUEUE 0 AFEC0 Task + DMAAFEC:POOL 1 NONE NONE + DMAAFEC:QUEUE 0 AFEC1 Task + COM:TXPOOL 3 NONE NONE + COM:TXQ 0 NONE NONE + COM:RXPOOL 5 NONE NONE + COM:RXQ 0 NONE NONE + FATFS:MUTEX 0 NONE NONE + +``` + +@note - the NONE's above may just be empty strings. + +This code adds the following custom GDB commands: + +* show List-Handle (symbol|address) [CastType] + CastType is an optional argument that will cast all of the + handles in a list to a particular type. +* show Task-List +* show Handle-Registry +* show Handle-Name (symbole|address) +* show Queue-Info [filter] + filter can be "queue","mutex","semaphore", "counting", "recursive" + + + +@TODO +===== + +* With GDB's Python API - it doesn't seem to handle code is separate + files very well. + +* Currently, the EventGroup objects don't have an inspector. + Work in progress - ideal solution would likely modify the struct + of the Event Group to provide a similar piece of info that the + Queue handle does so that we could use the same registry. diff --git a/make/rules.mk b/make/rules.mk index 44ab372b..4ac0b2d9 100644 --- a/make/rules.mk +++ b/make/rules.mk @@ -71,6 +71,7 @@ debug: flash arm-none-eabi-gdb-py \ -ex "target extended-remote 127.0.0.1:4242" \ -ex "set confirm off" \ + -ex "source ../debug/FreeRTOS/FreeRTOS.py" \ $(OBJ_DIR)/$(PROJECT).elf; \ kill `cat $(OBJ_DIR)/st-util.PID`; \ rm $(OBJ_DIR)/st-util.PID