Python script for decoding padconf rd1 to csv
authorBrad Griffis <bgriffis@ti.com>
Wed, 9 Jan 2019 17:39:05 +0000 (11:39 -0600)
committerBrad Griffis <bgriffis@ti.com>
Wed, 9 Jan 2019 17:39:05 +0000 (11:39 -0600)
padconf/am57xx-padconf-decoder.py [new file with mode: 0755]

diff --git a/padconf/am57xx-padconf-decoder.py b/padconf/am57xx-padconf-decoder.py
new file mode 100755 (executable)
index 0000000..1c9e21c
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2019, Texas Instruments Incorporated
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# *  Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# *  Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# *  Neither the name of Texas Instruments Incorporated nor the names of
+#    its contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+import xml.etree.ElementTree as ET
+import re
+import sys
+
+if len(sys.argv) != 2:
+    print  # Empty line
+    print sys.argv[0], "help:\n"
+    print "Please pass the rd1 file to this script, e.g.:"
+    print "", sys.argv[0], "am57xx-padconf_yyyy-mm-dd_hhmmss.rd1\n"
+    print("Output file will have same base name as input, "
+          "but csv file type.\n")
+    sys.exit(1)
+
+try:
+    rd1 = open(sys.argv[1], "rt")
+except IOError:
+    print "Error: input file", sys.argv[1], "not accessible."
+    sys.exit(1)
+
+try:
+    csv_filename = sys.argv[1]
+    csv_filename = csv_filename.replace(".rd1", ".csv")
+    csv = open(csv_filename, "w+")
+except IOError:
+    print "Error creating file", csv_filename
+
+# CSV files must use \r\n for all line endings
+# Create header row
+csv.write("Reg Name, Reg Address, Reg Value, Slew, InputEnable, Pull Config, "
+          "Mode Select, Delay Mode, Muxmode, Mux Description, Comments\r\n")
+csv_string = "%s, 0x%08X, 0x%08X, %s, %s, %s, %s, %s, %d, %s, %s\r\n"
+
+# Determine device family based on header
+header = rd1.readline()
+m = re.match(r'.*AM(57[0-4])x.*', header, 0);
+if m:
+    family = int(m.group(1))
+else:
+    print "Unrecognized device family in header:"
+    print header
+    sys.exit(1)
+
+if family == 570:
+    tree = ET.parse('CTRL_MODULE_CORE_am571x.xml')
+elif family == 571:
+    tree = ET.parse('CTRL_MODULE_CORE_am571x.xml')
+elif family == 572:
+    tree = ET.parse('CTRL_MODULE_CORE_am572x.xml')
+elif family == 574:
+    tree = ET.parse('CTRL_MODULE_CORE_am574x.xml')
+else:
+    print "Didn't recognize device family AM%d" % family
+    print header
+    sys.exit(1)
+
+root = tree.getroot()
+
+mySearchExpression = "./register[@offset=\'0x%X\']"
+mySearchExpression2 = "./bitenum[@value=\'%d\']"
+
+for lines in rd1:
+    # Use regular expression to extract address and data from rd1
+    m = re.match(r'(0x[0-9a-fA-F]{8})\s+(0x[0-9a-fA-F]{8})', lines, 0)
+    if m:
+        alphanum1 = m.group(1)  # address (string)
+        alphanum2 = m.group(2)  # data (string)
+        address = int(alphanum1, 16)  # convert from string to number
+        offset = address - 0x4A002000
+        register_value = int(alphanum2, 16)  # convert from string
+        comments = ""  # Start new for each line
+
+        # Extract slewcontrol field
+        if (register_value & 0x00080000) == 0x00080000:
+            slewstring = "slow"
+            slew = 1
+        else:
+            slewstring = "fast"
+            slew = 0
+
+        # Extract inputenable and pullup/pulldown info
+        if (register_value & 0x00040000) == 0x00040000:
+            inputenable_string = "input enabled"
+        else:
+            inputenable_string = "output-only"
+        if (register_value & 0x00010000) == 0x00010000:
+            pullstring = "no pull"
+        else:
+            if (register_value & 0x00020000) == 0x00020000:
+                pullstring = "pullup"
+            else:
+                pullstring = "pulldown"
+        myregister = root.find(mySearchExpression % offset)
+        myregister_name = myregister.get("id")
+
+        # Extract muxmode and associated description
+        muxmode = register_value & 0xf
+        mymux = myregister.find("./bitfield[@begin='3']")
+        if mymux is not None:
+            myselection = mymux.find(mySearchExpression2 % muxmode)
+            muxmode_description = myselection.get('description')
+        else:
+            muxmode_description = "-"
+
+        # Parse modeselect and delaymode fields
+        mymodeselect = myregister.find("./bitfield[@begin='8']")
+        if mymodeselect is not None:
+            if (register_value & 0x100) == 0x100:
+                modeselect_description = "Virtual/Manual"
+                delaymode = (register_value & 0xF0) >> 4
+                delaymode_format_string = "%d"
+                delaymode_string = delaymode_format_string % delaymode
+            else:
+                modeselect_description = "Default"
+                delaymode_string = "-"
+        else:
+            modeselect_description = "-"
+            delaymode_string = "-"
+
+        # For vout pins, recommend slow slew
+        # For all other pins, use the default value
+        if "vout" in muxmode_description:
+            if slew == 0:
+                comments += "Slow slew recommended for vout pins. "
+        else:
+            myslew = myregister.find("./bitfield[@begin='19']")
+            if myslew is not None:
+                default_slew = int(myslew.get('resetval'), 16)
+                if default_slew != slew:
+                    comments += "Slew rate should be left at default value. "
+
+        # Write a line of the CSV file
+        csv.write(csv_string % (myregister_name, address,
+                  register_value, slewstring, inputenable_string,
+                  pullstring, modeselect_description,
+                  delaymode_string, muxmode, muxmode_description,
+                  comments))
+
+rd1.close()
+csv.close()
+