vos/ambiq-hal-sys/ambiq-sparkfun-sdk/tools/bsp_generator/pinconfig.py
2022-10-23 23:45:43 -07:00

671 lines
24 KiB
Python

#!/usr/bin/env python3
# *****************************************************************************
#
# pinconfig.py
#
# @brief Script for generating a BSP pin file.
# *****************************************************************************
# *****************************************************************************
#
# Copyright (c) 2020, Ambiq Micro
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# Third party software included in this distribution is subject to the
# additional license terms as defined in the /docs/licenses directory.
#
# 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 HOLDER 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.
#
# This is part of revision 2.4.2 of the AmbiqSuite Development Package.
#
# *****************************************************************************
# *****************************************************************************
# Imported modules
# *****************************************************************************
import argparse
import textwrap
import os.path
import rsonlite
# *****************************************************************************
# Templates
# *****************************************************************************
filetemplateC = '''
//*****************************************************************************
//
// {filename}
//! @file
//!
//! @brief BSP pin configuration definitions.
//!
//! @addtogroup BSP Board Support Package (BSP)
//! @ingroup BSP
//! @{{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. 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.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// 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 HOLDER 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.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include "am_bsp.h"
{pin_defs}
//*****************************************************************************
//
// End Doxygen group.
//! @}}
//
//*****************************************************************************
'''.strip()
filetemplateH = '''
//*****************************************************************************
//
// {filename}
//! @file
//!
//! @brief BSP pin configuration definitions.
//!
//! @addtogroup BSP Board Support Package (BSP)
//! @addtogroup apollo3_bsp BSP for the Apollo3 EVB.
//! @ingroup BSP
//! @{{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. 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.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// 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 HOLDER 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.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#ifndef {headerdef}
#define {headerdef}
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
#ifdef __cplusplus
extern "C"
{{
#endif
{pin_defs}
#ifdef __cplusplus
}}
#endif
#endif // {headerdef}
//*****************************************************************************
//
// End Doxygen group.
//! @}}
//
//*****************************************************************************
'''.strip()
sectiontemplate = '''
//*****************************************************************************
//
// {pin_descr}
//
//*****************************************************************************
'''.strip()
# *****************************************************************************
#
# Globals
#
# *****************************************************************************
# *****************************************************************************
#
# Command line support.
#
# *****************************************************************************
def read_arguments():
parser = argparse.ArgumentParser()
parser.add_argument('input', help='input src file name')
parser.add_argument('CorH', help='C to create C file, H to create H file',
choices=['C','H','c','h'])
return parser.parse_args()
# *****************************************************************************
# parse_input()
# *****************************************************************************
def parse_input(filename):
'''
Simple wrapper to pull an rsonlite list from given file.
'''
with open(filename) as f:
data = f.read()
return rsonlite.loads(data)
# *****************************************************************************
# list_to_dict()
# *****************************************************************************
def list_to_dict(L):
'''
rsonlite loads data from the rson files as a very-nested list. This
function converts that list to a set of nested dictionaries. At each level,
the dictionary keys correspond to the "headings", and the dictionary values
are a list of the items under that "heading". Values assigned by
equals-sign statements are (unfortunately) also converted to (key, list)
pairs, the same way that subheadings are.
'''
if len(L) == 1:
return L[0]
else:
D = dict()
for x in L:
if x[0] in D:
D[x[0]] = D[x[0]] + [list_to_dict(x[1])]
else:
D[x[0]] = [list_to_dict(x[1])]
return D
# *****************************************************************************
# get_val()
# *****************************************************************************
def get_val(name, D):
'''
get_val is just a helper to make it more obvious when you are trying to get
at an equals-sign-assigned value from the rson file dictionary.
'''
if name not in D:
return "ERROR: {} VALUE MISSING".format(name)
else:
return D[name][0]
# *****************************************************************************
# get_version()
# *****************************************************************************
def get_version(filename):
'''
Given the filename of an 'src' file, this function will return a 'pin'
object corresponding to the fields described in the src file.
'''
# Read in the contents of the src file, and use the rsonlite library to
# parse them into a list.
rson_data = parse_input(filename)
# Convert the list to a dictionary.
rson_dict = list_to_dict(rson_data)
if 'pinsrc_ver' in rson_dict:
# Convert rson list object to int
ssrcver = rson_dict["pinsrc_ver"][0]
if ssrcver[0:2].lower() == "0x":
source_version = int(ssrcver, 16)
else:
source_version = int(ssrcver, 10)
else:
# If no src file version given, assume version for Apollo3
source_version = 0x0003
return source_version
# *****************************************************************************
# get_pinobj()
# *****************************************************************************
def get_pinobj(filename):
'''
Given the filename of an 'src' file, this function will return a 'pin'
object corresponding to the fields described in the src file.
'''
# Set the location for the supplementary files (infoblock, base addresses, etc.)
srcdir = os.path.dirname(filename)
# Read in the contents of the src file, and use the rsonlite library to
# parse them into a list.
rson_data = parse_input(filename)
# Convert the list to a dictionary.
rson_dict = list_to_dict(rson_data)
# Convert the dictionary to a block object, which will create field
# objects as necessary. Return this object to the caller.
return pinobj(rson_dict)
# *****************************************************************************
# pinfields
# *****************************************************************************
class pinfields:
def __init__(self, pindict):
self.name = ''
self.desc = ''
self.pinnum = 0
self.powersw = ''
self.pullup = ''
self.func_sel = ''
self.drvstrength = 0
self.intdir = 0
self.GPOutcfg = ''
self.GPinput = ''
self.GPRdZero = ''
self.IOMnum = ''
self.CEnum = ''
self.CEpol = ''
self.bIomMSPIn = ''
intnotgiven = 65535
strnotgiven = 'none_given'
if 'name' in pindict:
self.name = get_val('name', pindict)
else:
self.name = strnotgiven
if 'desc' in pindict:
self.desc = get_val('desc', pindict)
else:
self.desc = strnotgiven
if 'pinnum' in pindict:
self.pinnum = int(get_val('pinnum', pindict))
else:
self.pinnum = intnotgiven
if 'powersw' in pindict:
self.powersw = get_val('powersw', pindict)
else:
self.powersw = strnotgiven
if 'pullup' in pindict:
self.pullup = get_val('pullup', pindict)
else:
self.pullup = strnotgiven
if 'func_sel' in pindict:
self.func_sel = get_val('func_sel', pindict)
else:
self.func_sel = strnotgiven
if 'drvstrength' in pindict:
self.drvstrength = int(get_val('drvstrength', pindict))
else:
self.drvstrength = intnotgiven
if 'intdir' in pindict:
self.intdir = get_val('intdir', pindict)
else:
self.intdir = strnotgiven
if 'GPOutcfg' in pindict:
self.GPOutcfg = get_val('GPOutcfg', pindict)
else:
self.GPOutcfg = strnotgiven
if 'GPinput' in pindict:
self.GPinput = get_val('GPinput', pindict)
else:
self.GPinput = strnotgiven
if 'GPRdZero' in pindict:
self.GPRdZero = get_val('GPRdZero', pindict)
else:
self.GPRdZero = strnotgiven
if 'IOMnum' in pindict:
self.IOMnum = get_val('IOMnum', pindict)
elif 'MSPInum' in pindict:
self.IOMnum = get_val('MSPInum', pindict)
else:
self.IOMnum = strnotgiven
if 'CEnum' in pindict:
self.CEnum = get_val('CEnum', pindict)
else:
self.CEnum = strnotgiven
if 'CEpol' in pindict:
self.CEpol = get_val('CEpol', pindict)
else:
self.CEpol = strnotgiven
if 'bIomMSPIn' in pindict:
self.bIomMSPIn = get_val('bIomMSPIn', pindict)
else:
self.bIomMSPIn = strnotgiven
#
# Check for an invalid field in the src file. If so, report it.
#
for fld in pindict:
if fld != 'name' and \
fld != 'desc' and \
fld != 'pinnum' and \
fld != 'powersw' and \
fld != 'pullup' and \
fld != 'func_sel' and \
fld != 'drvstrength' and \
fld != 'intdir' and \
fld != 'GPOutcfg' and \
fld != 'GPinput' and \
fld != 'GPRdZero' and \
fld != 'IOMnum' and \
fld != 'MSPInum' and \
fld != 'CEnum' and \
fld != 'CEpol' and \
fld != 'bIomMSPIn':
print("Invalid field: '%s.%s'" % (self.name, fld))
# *****************************************************************************
# pinobj
# *****************************************************************************
class pinobj:
def __init__(self, pindict):
self.name = 'name'
self.srcver=0x0000
self.pins = []
if 'pinsrc_ver' in pindict:
# Convert rson list object to int
ssrcver = pindict["pinsrc_ver"][0]
if ssrcver[0:2].lower() == "0x":
self.srcver = int(ssrcver,16)
else:
self.srcver = int(ssrcver,10)
else:
# If no src file version given, assume version for Apollo3
self.srcver = 0x0003
# Run through all the pins given in the src file
if 'pin' in pindict:
#
# Run through the 'pin' list.
#
for pin in pindict['pin']:
self.pins.append(pinfields(pin))
# *****************************************************************************
# write_Cfiles()
# *****************************************************************************
def write_Cfiles(pinobj, bCreateC):
#
# Initializations
#
intnotgiven = 65535
strnotgiven = 'none_given'
strCfile = ''
strHfile = ''
for pin in pinobj.pins:
sectiondesc = pin.name.strip() + ' pin'
if pin.desc == strnotgiven:
sectiondesc += '.'
else:
sectiondesc += ': ' + pin.desc.strip()
if sectiondesc[-1] != '.':
sectiondesc += '.'
strCfile += '\n'
strCfile += sectiontemplate.format(pin_descr=sectiondesc)
strCfile += '\n'
strHfile += '\n'
strHfile += sectiontemplate.format(pin_descr=sectiondesc)
strHfile += '\n'
if pin.pinnum != intnotgiven:
strHfile += '#define AM_BSP_GPIO_%-20s' % pin.name + '%d\n' % pin.pinnum
strHfile += 'extern const am_hal_gpio_pincfg_t g_AM_BSP_GPIO_%s;\n' % pin.name
#strHfile += '\n'
strCfile += 'const am_hal_gpio_pincfg_t g_AM_BSP_GPIO_%s =\n' % pin.name
strCfile += '{\n'
strCfile += '%-25s' % ' .uFuncSel' + '= %s,\n' % pin.func_sel
if pin.powersw != strnotgiven:
if (pin.powersw.lower() == "vdd") or \
(pin.powersw.lower() == "vss") or \
(pin.powersw.lower() == "none"):
strCfile += '%-25s' % ' .ePowerSw' + '= AM_HAL_GPIO_PIN_POWERSW_%s,\n' % pin.powersw.upper()
else:
strCfile += '%-25s' % ' .ePowerSw' + '= %s,\n' % pin.powersw
if pin.pullup != strnotgiven:
if (pin.pullup.lower() == "none") or \
(pin.pullup.lower() == "weak") or \
(pin.pullup.lower() == "pulldown") or \
(pin.pullup.lower() == "1_5k") or \
(pin.pullup.lower() == "6k") or \
(pin.pullup.lower() == "12k") or \
(pin.pullup.lower() == "24k"):
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%s,\n' % pin.pullup.upper()
elif (pin.pullup == "1_5") or \
(pin.pullup == "6") or \
(pin.pullup == "12") or \
(pin.pullup == "24"):
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%sK,\n' % pin.pullup
else:
strCfile += '%-25s' % ' .ePullup' + '= %s,\n' % pin.pullup
if pin.drvstrength != intnotgiven:
if (pin.drvstrength != 2) and (pin.drvstrength != 4) and \
(pin.drvstrength != 8) and (pin.drvstrength != 12):
pin.drvstrength = 2
strCfile += '%-25s' % ' .eDriveStrength' + '= AM_HAL_GPIO_PIN_DRIVESTRENGTH_%dMA,\n' % pin.drvstrength
if pin.GPOutcfg != strnotgiven:
if (pin.GPOutcfg.lower() == "disable") or \
(pin.GPOutcfg.lower() == "pushpull") or \
(pin.GPOutcfg.lower() == "opendrain") or \
(pin.GPOutcfg.lower() == "tristate"):
strCfile += '%-25s' % ' .eGPOutcfg' + '= AM_HAL_GPIO_PIN_OUTCFG_%s,\n' % pin.GPOutcfg.upper()
else:
strCfile += '%-25s' % ' .eGPOutcfg' + '= %s,\n' % pin.GPOutcfg
if pin.GPinput != strnotgiven:
if (pin.GPinput.lower() == "true"):
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_ENABLE,\n'
elif (pin.GPinput.lower() == "false"):
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_NONE,\n'
else:
strCfile += '%-25s' % ' .eGPInput' + '= %s,\n' % pin.GPinput
if pin.GPRdZero != strnotgiven:
if (pin.GPRdZero.lower() == "true") or \
(pin.GPRdZero.lower() == "zero"):
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_ZERO,\n'
elif (pin.GPRdZero.lower() == "false") or \
(pin.GPRdZero.lower() == "readpin"):
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_READPIN,\n'
else:
strCfile += '%-25s' % ' .eGPRdZero' + '= %s,\n' % pin.GPRdZero
if pin.intdir != strnotgiven:
if (pin.intdir.lower() == "none") or \
(pin.intdir.lower() == "lo2hi") or \
(pin.intdir.lower() == "hi2lo") or \
(pin.intdir.lower() == "either"):
strCfile += '%-25s' % ' .eIntDir' + '= AM_HAL_GPIO_PIN_INTDIR_%s,\n' % pin.intdir.upper()
else:
strCfile += '%-25s' % ' .eIntDir' + '= %s,\n' % pin.intdir
if (pin.bIomMSPIn != strnotgiven):
if pinobj.srcver >= 0x0003:
if ((pin.bIomMSPIn[0:1].lower() != "m") and (pin.bIomMSPIn != "0")):
bIom = 1
else:
bIom = 0
strCfile += '%-25s' % ' .bIomMSPIn' + '= %d,\n' % bIom
if pin.IOMnum != strnotgiven:
strCfile += '%-25s' % ' .uIOMnum' + '= %s,\n' % str(pin.IOMnum)
if pin.CEnum != strnotgiven:
strCfile += '%-25s' % ' .uNCE' + '= %s,\n' % str(pin.CEnum)
# Create the define
strtmp = '#define AM_BSP_%s_CHNL' % (pin.name)
strHfile += '%-40s' % strtmp + '%s\n' % str((pin.CEnum))
if pin.CEpol != strnotgiven:
if (pin.CEpol.lower() == "low") or \
(pin.CEpol.lower() == "high"):
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_ACTIVE%s,\n' % pin.CEpol.upper()
elif (pin.CEpol.lower() == "activelow") or \
(pin.CEpol.lower() == "activehigh"):
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_%s,\n' % pin.CEpol.upper()
else:
strCfile += '%-25s' % ' .eCEpol' + '= %s,\n' % pin.CEpol
# Eliminate the last comma from the last structure member
strCfile = strCfile[:-2]
# Terminate the structure
strCfile += '\n};\n'
if bCreateC:
#
# Develop and print the C file
#
S = filetemplateC.format(filename='am_bsp_pins.c', pin_defs=strCfile);
print(S)
else:
#
# Develop and print the H file
#
S = filetemplateH.format(filename='am_bsp_pins.h',
pin_defs=strHfile,
headerdef='AM_BSP_PINS_H')
print(S)
# *****************************************************************************
#
# main
#
# *****************************************************************************
if __name__ == '__main__':
#
# Get arguments.
# First arg is a string for the input .src file.
# Second arg must be a C or H.
#
args = read_arguments()
if args.CorH.upper() == 'C':
bCreateC = True
else:
bCreateC = False
version = get_version(args.input)
# Redirect the script based on the version number.
if version & 0xFF == 0x03:
pinobj = get_pinobj(args.input)
#
# pinobj.pins is a list of the pins
#
write_Cfiles(pinobj, bCreateC)