tools/gen-device-svd: generate code for cluster arrays
This should make it possible to add support for PWM on nrf devices.
Этот коммит содержится в:
родитель
9b4a6dcc14
коммит
5c79a93c85
1 изменённых файлов: 78 добавлений и 27 удалений
|
@ -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 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:
|
if register['array'] is not None:
|
||||||
regType = '[{}]RegValue'.format(register['array'])
|
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,21 +324,25 @@ 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'])
|
||||||
if register['description']:
|
for subregister in register.get('registers', []):
|
||||||
out.write(': {description}'.format(**register))
|
writeGoRegisterBitfields(out, subregister, register['name'] + '.' + subregister['name'])
|
||||||
out.write('\n')
|
|
||||||
for bitfield in register['bitfields']:
|
|
||||||
out.write('\t{name} = 0x{value:x}'.format(**bitfield))
|
|
||||||
if bitfield['description']:
|
|
||||||
out.write(' // {description}'.format(**bitfield))
|
|
||||||
out.write('\n')
|
|
||||||
out.write(')\n')
|
out.write(')\n')
|
||||||
|
|
||||||
|
def writeGoRegisterBitfields(out, register, name):
|
||||||
|
out.write('\n\t// {}'.format(name))
|
||||||
|
if register['description']:
|
||||||
|
out.write(': {description}'.format(**register))
|
||||||
|
out.write('\n')
|
||||||
|
for bitfield in register['bitfields']:
|
||||||
|
out.write('\t{name} = 0x{value:x}'.format(**bitfield))
|
||||||
|
if bitfield['description']:
|
||||||
|
out.write(' // {description}'.format(**bitfield))
|
||||||
|
out.write('\n')
|
||||||
|
|
||||||
|
|
||||||
def writeAsm(outdir, device):
|
def writeAsm(outdir, device):
|
||||||
# The interrupt vector, which is hard to write directly in Go.
|
# The interrupt vector, which is hard to write directly in Go.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче