tools/gen-device-svd: generate code for cluster arrays

This should make it possible to add support for PWM on nrf devices.
Этот коммит содержится в:
Ayke van Laethem 2018-09-30 14:54:42 +02:00
родитель 9b4a6dcc14
коммит 5c79a93c85
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED

Просмотреть файл

@ -104,14 +104,34 @@ def readSVD(path, sourceURL):
for register in regsEls[0].findall('register'): for register in regsEls[0].findall('register'):
peripheral['registers'].append(parseRegister(groupName or name, register, baseAddress)) peripheral['registers'].append(parseRegister(groupName or name, register, baseAddress))
for cluster in regsEls[0].findall('cluster'): for cluster in regsEls[0].findall('cluster'):
if cluster.find('dim') is not None: clusterName = getText(cluster.find('name')).replace('[%s]', '')
continue # TODO clusterDescription = getText(cluster.find('description'))
clusterPrefix = getText(cluster.find('name')) + '_' clusterPrefix = clusterName + '_'
clusterOffset = int(getText(cluster.find('addressOffset')), 0) clusterOffset = int(getText(cluster.find('addressOffset')), 0)
for regEl in cluster.findall('register'): if cluster.find('dim') is None:
peripheral['registers'].append(parseRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix)) dim = None
dimIncrement = None
else: else:
continue dim = int(getText(cluster.find('dim')))
dimIncrement = int(getText(cluster.find('dimIncrement')), 0)
clusterRegisters = []
for regEl in cluster.findall('register'):
clusterRegisters.append(parseRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix))
if dimIncrement is None:
lastReg = clusterRegisters[-1]
lastAddress = lastReg['address']
if lastReg['array'] is not None:
lastAddress = lastReg['address'] + lastReg['array'] * lastReg['elementsize']
firstAddress = clusterRegisters[0]['address']
dimIncrement = lastAddress - firstAddress
peripheral['registers'].append({
'name': clusterName,
'address': baseAddress + clusterOffset,
'description': clusterDescription,
'registers': clusterRegisters,
'array': dim,
'elementsize': dimIncrement,
})
device.interrupts = sorted(interrupts.values(), key=lambda v: v['index']) device.interrupts = sorted(interrupts.values(), key=lambda v: v['index'])
licenseBlock = '' licenseBlock = ''
@ -129,7 +149,7 @@ def readSVD(path, sourceURL):
return device return device
def parseRegister(groupName, regEl, baseAddress, namePrefix=''): def parseRegister(groupName, regEl, baseAddress, bitfieldPrefix=''):
regName = getText(regEl.find('name')) regName = getText(regEl.find('name'))
regDescription = getText(regEl.find('description')) regDescription = getText(regEl.find('description'))
offsetEls = regEl.findall('offset') offsetEls = regEl.findall('offset')
@ -160,18 +180,18 @@ def parseRegister(groupName, regEl, baseAddress, namePrefix=''):
else: else:
msb = int(getText(fieldEl.find('bitWidth'))) + lsb - 1 msb = int(getText(fieldEl.find('bitWidth'))) + lsb - 1
fields.append({ fields.append({
'name': '{}_{}{}_{}_Pos'.format(groupName, namePrefix, regName, fieldName), 'name': '{}_{}{}_{}_Pos'.format(groupName, bitfieldPrefix, regName, fieldName),
'description': 'Position of %s field.' % fieldName, 'description': 'Position of %s field.' % fieldName,
'value': lsb, 'value': lsb,
}) })
fields.append({ fields.append({
'name': '{}_{}{}_{}_Msk'.format(groupName, namePrefix, regName, fieldName), 'name': '{}_{}{}_{}_Msk'.format(groupName, bitfieldPrefix, regName, fieldName),
'description': 'Bit mask of %s field.' % fieldName, 'description': 'Bit mask of %s field.' % fieldName,
'value': (0xffffffff >> (31 - (msb - lsb))) << lsb, 'value': (0xffffffff >> (31 - (msb - lsb))) << lsb,
}) })
if lsb == msb: # single bit if lsb == msb: # single bit
fields.append({ fields.append({
'name': '{}_{}{}_{}'.format(groupName, namePrefix, regName, fieldName), 'name': '{}_{}{}_{}'.format(groupName, bitfieldPrefix, regName, fieldName),
'description': 'Bit %s.' % fieldName, 'description': 'Bit %s.' % fieldName,
'value': 1 << lsb, 'value': 1 << lsb,
}) })
@ -180,17 +200,18 @@ def parseRegister(groupName, regEl, baseAddress, namePrefix=''):
enumDescription = getText(enumEl.find('description')) enumDescription = getText(enumEl.find('description'))
enumValue = int(getText(enumEl.find('value')), 0) enumValue = int(getText(enumEl.find('value')), 0)
fields.append({ fields.append({
'name': '{}_{}{}_{}_{}'.format(groupName, namePrefix, regName, fieldName, enumName), 'name': '{}_{}{}_{}_{}'.format(groupName, bitfieldPrefix, regName, fieldName, enumName),
'description': enumDescription, 'description': enumDescription,
'value': enumValue, 'value': enumValue,
}) })
return { return {
'name': namePrefix + regName, 'name': regName,
'address': address, 'address': address,
'description': regDescription.replace('\n', ' '), 'description': regDescription.replace('\n', ' '),
'bitfields': fields, 'bitfields': fields,
'array': array, 'array': array,
'elementsize': 4,
} }
def writeGo(outdir, device): def writeGo(outdir, device):
@ -260,15 +281,41 @@ const (
padNumber += 1 padNumber += 1
regType = 'RegValue' regType = 'RegValue'
if 'registers' in register:
import pprint
#pprint.pprint(register)
# This is a cluster, not a register. Create the cluster type.
regType = 'struct {\n'
subaddress = register['address']
for subregister in register['registers']:
subregType = 'RegValue'
if subregister['array']:
subregType = '[{}]{}'.format(subregister['array'], subregType)
#raise NotImplementedError('array in cluster register')
if subaddress != subregister['address']:
raise NotImplementedError('gaps in cluster register')
if subregister['array'] is not None:
subaddress += subregister['elementsize'] * subregister['array']
else:
subaddress += subregister['elementsize']
regType += '\t\t{name} {subregType}\n'.format(**subregister, subregType=subregType)
if register['array'] is not None: if register['array'] is not None:
regType = '[{}]RegValue'.format(register['array']) if subaddress != register['address'] + register['elementsize']:
numSkip = ((register['address'] + register['elementsize']) - subaddress) // 4
if numSkip == 1:
regType += '\t\t_padding{padNumber} RegValue\n'.format(padNumber=padNumber)
else:
regType += '\t\t_padding{padNumber} [{num}]RegValue\n'.format(padNumber=padNumber, num=numSkip)
regType += '\t}'
if register['array'] is not None:
regType = '[{}]{}'.format(register['array'], regType)
out.write('\t{name} {regType}\n'.format(**register, regType=regType)) out.write('\t{name} {regType}\n'.format(**register, regType=regType))
# next address # next address
if register['array'] is not None: if register['array'] is not None:
address = register['address'] + 4 * register['array'] address = register['address'] + register['elementsize'] * register['array']
else: else:
address = register['address'] + 4 address = register['address'] + register['elementsize']
out.write('}\n') out.write('}\n')
# Define bitfields. # Define bitfields.
@ -277,11 +324,16 @@ const (
# This peripheral was derived from another peripheral. Bitfields are # This peripheral was derived from another peripheral. Bitfields are
# already defined. # already defined.
continue continue
if not sum(map(lambda r: len(r['bitfields']), peripheral['registers'])): continue
out.write('\n// Bitfields for {name}: {description}\nconst('.format(**peripheral)) out.write('\n// Bitfields for {name}: {description}\nconst('.format(**peripheral))
for register in peripheral['registers']: for register in peripheral['registers']:
if not register['bitfields']: continue if register.get('bitfields'):
out.write('\n\t// {name}'.format(**register)) writeGoRegisterBitfields(out, register, register['name'])
for subregister in register.get('registers', []):
writeGoRegisterBitfields(out, subregister, register['name'] + '.' + subregister['name'])
out.write(')\n')
def writeGoRegisterBitfields(out, register, name):
out.write('\n\t// {}'.format(name))
if register['description']: if register['description']:
out.write(': {description}'.format(**register)) out.write(': {description}'.format(**register))
out.write('\n') out.write('\n')
@ -290,7 +342,6 @@ const (
if bitfield['description']: if bitfield['description']:
out.write(' // {description}'.format(**bitfield)) out.write(' // {description}'.format(**bitfield))
out.write('\n') out.write('\n')
out.write(')\n')
def writeAsm(outdir, device): def writeAsm(outdir, device):