diff --git a/data/fault_list.csv b/data/fault_list.csv new file mode 100644 index 0000000000000000000000000000000000000000..aff4f3d879cf4618d98f3174d8edcd44bb5d33f6 --- /dev/null +++ b/data/fault_list.csv @@ -0,0 +1,2 @@ +"Category","Name (letters,numbers,underscores,NO SPACES, all caps!)","Description","Generated Name(autogenerated column!)" +"ANAKIN","TEST_FAULT","This fault is for testing","F_ANAKIN_TEST_FAULT" diff --git a/sbs b/sbs index 246b5796d250c74aa841d3833fa3184698f2c7f3..1bb6f735a51497241c419d1149ef134b740e980e 100755 --- a/sbs +++ b/sbs @@ -63,8 +63,7 @@ parser.add_option("-c", "--clean", help="Run a 'make clean'", dest="clean", parser.add_option("-b", "--board", help="Build a specific board", dest="board") parser.add_option("-l", "--list", help="List all build configurations", dest="list", default=False, action='store_true') - - +parser.add_option("-g", "--gen-faults", help="Generate fault list header files and exit", dest="genhdr", default=False, action='store_true') parser.add_option("-v", "--verbose", help="Print a verbose output", dest="log", action="store_true") parser.add_option("-j", "--jobs", @@ -75,6 +74,12 @@ parser.add_option("-j", "--jobs", banner() +if options.genhdr == True: + d1 = "data/fault_list.csv" + d2 = "src/shared/diagnostic/FaultCounterData.h" + os.system("/usr/bin/python scripts/gen_fault_headers.py %s %s" %(d1,d2)) + exit(0) + conf = cp.RawConfigParser() conf.read("sbs.conf") diff --git a/scripts/gen_fault_headers.py b/scripts/gen_fault_headers.py new file mode 100755 index 0000000000000000000000000000000000000000..c697b19e4241511b4dad2ec9479f8ef275403835 --- /dev/null +++ b/scripts/gen_fault_headers.py @@ -0,0 +1,241 @@ +#!/usr/bin/python + +# Copyright (c) 2017 Skyward Experimental Rocketry +# Authors: Alain Carlucci +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +import csv,string,hashlib,datetime,sys + +if len(sys.argv) != 3: + print("Usage: %s <CSV File> <Output header file>" % (sys.argv[0])) + exit(-1) + +headerLine = None + +newLines = [] + +lineCtr = 0 +curCatId = 0 +categories={} +enums={} + +import hashlib + +def fileHash(filename): + h = hashlib.sha1() + with open(filename, 'rb', buffering=0) as f: + for b in iter(lambda : f.read(128*1024), b''): + h.update(b) + return h.hexdigest() + +def genEnum(name, s, inc): + a = ('''enum class %s +{ +''') % (name,); + cnt = 0 + for i in s: + if inc: + a += " " + i + " = " + str(cnt) + ",\n" + else: + a += " " + i + " = " + str(s[i]) + ",\n" + cnt += 1 + a += "};\n" + return a + +def genHeaderFile(fileName,csvFile): + print("[*] Generating header file (%s)" %(fileName,)) + content = ('''/* Copyright (c) 2017 Skyward Experimental Rocketry + * Authors: Alain Carlucci + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + ****************************************************************************** + * THIS FILE IS AUTOGENERATED. DO NOT EDIT. * + ****************************************************************************** + */ + +// CSV File: %s +// SHA1 of CSV File: %s +// Autogen date: %s + +#include <cstdint> + +#ifndef SKYWARD_FAULT_CTRL_LIST_H +#define SKYWARD_FAULT_CTRL_LIST_H + +namespace FaultCounter +{ + +''') % (csvFile, fileHash(csvFile), datetime.datetime.now()) + content += genEnum("FaultCategory", categories, False) + content += "\n" + content += genEnum("Fault", enums, True) + content += ''' + +// Usage: categoryID = FaultCounter::FaultToCategory[faultID]; +static const uint32_t FaultToCategory[] = +{ + ''' + colCnt = 0 + for i in enums: + content += "%d, " % (categories[enums[i]], ) + colCnt += 1 + if colCnt == 20: + content += "\n " + colCnt = 0 + content += ''' +}; /* CategoryMapping */ + +} /* FaultCounter */ + +#endif /* SKYWARD_FAULT_CTRL_LIST_H */ + +''' + try: + with open(fileName, "w") as f: + f.write(content) + print("[+] Written %d lines in %s" % (len(content.split("\n")), fileName)) + except: + print("[!] Cannot open %s for writing.", fileName) + exit(-1) + + +def checkForGoodName(n): + if len(n) == 0: + return False + + if n[0] not in string.ascii_uppercase: + return False + + for x in n: + if x not in string.ascii_uppercase + string.digits + '_': + return False + + if n[-1] not in string.ascii_uppercase + string.digits: + return False + + return True + +def genEnumName(cat,name): + ctr = 2 + + genBName = "F_" + cat + "_" + name + genName = genBName + + while genName in enums: + genName = genBName + "_" + str(ctr) + ctr += 1 + + return genName + +# return False: csv file is ok +# return True: csv file must be updated +def handleLine(r): + global lineCtr,categories,newLines,enums,curCatId + + if len(r) != 4: + print("[!] Parsing error at line %d. I'm expecting 4 fields" % (lineCtr,)) + exit(-1) + + curCat = r[0].strip().upper() + curName = r[1].strip().upper() + curDesc = r[2].strip() + curEnum = r[3].strip().upper() + + if checkForGoodName(curCat) == False: + print("[!] Invalid category at line %d." % (lineCtr,)) + exit(-1) + + if checkForGoodName(curName) == False: + print("[!] Invalid name at line %d." % (lineCtr,)) + exit(-1) + + if len(curEnum) > 0 and (checkForGoodName(curEnum) == False or curEnum in enums): + print("[!] Invalid generated name at line %d." % (lineCtr,)) + exit(-1) + + retVal = False + if len(curEnum) == 0: + curEnum = genEnumName(curCat, curName) + retVal = True + + if curCat not in categories: + print("[+] Added category '%s'" % (curCat,)) + categories[curCat] = curCatId + curCatId += 1 + + print("[+] Added %s in category %s" %(curEnum,curCat)) + enums[curEnum] = curCat + + newLines.append([curCat, curName, curDesc, curEnum]) + return retVal + +mustUpdate = False +print("[*] Opening %s..." % (sys.argv[1],)) +try: + with open(sys.argv[1], "r") as csvfile: + r = csv.reader(csvfile, delimiter=',', quotechar='"') + for row in r: + lineCtr += 1 + if headerLine is None: + headerLine = row + continue + if handleLine(row): + mustUpdate = True +except Exception as e: + print("[!] Cannot open %s for reading: %s!" %(sys.argv[1],str(e))) + exit(-1) + +if not mustUpdate: + print("[+] No need to update the csv file.") +else: + print("[*] Updating %s..." % (sys.argv[1],)) + + try: + with open(sys.argv[1], "w") as csvfile: + r = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL) + r.writerow(headerLine) + for row in newLines: + r.writerow(row) + print("[+] Successfully updated csv file") + except: + print("[!] Cannot open %s for writing!" %(sys.argv[1],)) + exit(-1) + +genHeaderFile(sys.argv[2], sys.argv[1]) diff --git a/src/shared/diagnostic/FaultCounterData.h b/src/shared/diagnostic/FaultCounterData.h new file mode 100644 index 0000000000000000000000000000000000000000..73d0f02590ca6000b86d80402e4e9ee25f3b04ab --- /dev/null +++ b/src/shared/diagnostic/FaultCounterData.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2017 Skyward Experimental Rocketry + * Authors: Alain Carlucci + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + ****************************************************************************** + * THIS FILE IS AUTOGENERATED. DO NOT EDIT. * + ****************************************************************************** + */ + +// CSV File: data/fault_list.csv +// SHA1 of CSV File: e9a518af53ac91c2e57142fda140689918338c66 +// Autogen date: 2017-09-16 19:03:30.061175 + +#include <cstdint> + +#ifndef SKYWARD_FAULT_CTRL_LIST_H +#define SKYWARD_FAULT_CTRL_LIST_H + +namespace FaultCounter +{ + +enum class FaultCategory +{ + ANAKIN = 0, +}; + +enum class Fault +{ + F_ANAKIN_TEST_FAULT = 0, +}; + + +// Usage: categoryID = FaultCounter::FaultToCategory[faultID]; +static const uint32_t FaultToCategory[] = +{ + 0, +}; /* CategoryMapping */ + +} /* FaultCounter */ + +#endif /* SKYWARD_FAULT_CTRL_LIST_H */ +