generator: generate device wrappers for Atmel SAM family
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
b8c326d710
коммит
8d1284cfe7
3 изменённых файлов: 111 добавлений и 39 удалений
2
.gitignore
предоставленный
2
.gitignore
предоставленный
|
@ -7,4 +7,6 @@ src/device/nrf/*.go
|
|||
src/device/nrf/*.s
|
||||
src/device/stm32/*.go
|
||||
src/device/stm32/*.s
|
||||
src/device/sam/*.go
|
||||
src/device/sam/*.s
|
||||
vendor
|
||||
|
|
7
Makefile
7
Makefile
|
@ -76,7 +76,7 @@ fmt:
|
|||
test:
|
||||
@go test -v .
|
||||
|
||||
gen-device: gen-device-avr gen-device-nrf gen-device-stm32
|
||||
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-stm32
|
||||
|
||||
gen-device-avr:
|
||||
./tools/gen-device-avr.py lib/avr/packs/atmega src/device/avr/
|
||||
|
@ -87,11 +87,14 @@ gen-device-nrf:
|
|||
./tools/gen-device-svd.py lib/nrfx/mdk/ src/device/nrf/ --source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk
|
||||
go fmt ./src/device/nrf
|
||||
|
||||
gen-device-sam:
|
||||
./tools/gen-device-svd.py lib/cmsis-svd/data/Atmel/ src/device/sam/ --source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel
|
||||
go fmt ./src/device/sam
|
||||
|
||||
gen-device-stm32:
|
||||
./tools/gen-device-svd.py lib/cmsis-svd/data/STMicro/ src/device/stm32/ --source=https://github.com/posborne/cmsis-svd/tree/master/data/STMicro
|
||||
go fmt ./src/device/stm32
|
||||
|
||||
|
||||
# Build the Go compiler.
|
||||
build/tgo: *.go compiler/*.go interp/*.go loader/*.go ir/*.go
|
||||
@mkdir -p build
|
||||
|
|
|
@ -13,6 +13,8 @@ class Device:
|
|||
pass
|
||||
|
||||
def getText(element):
|
||||
if element is None:
|
||||
return "None"
|
||||
return ''.join(element.itertext())
|
||||
|
||||
def formatText(text):
|
||||
|
@ -99,7 +101,7 @@ def readSVD(path, sourceURL):
|
|||
if len(regsEls) != 1:
|
||||
raise ValueError('expected just one <registers> in a <peripheral>')
|
||||
for register in regsEls[0].findall('register'):
|
||||
peripheral['registers'].append(parseRegister(groupName or name, register, baseAddress))
|
||||
peripheral['registers'].extend(parseRegister(groupName or name, register, baseAddress))
|
||||
for cluster in regsEls[0].findall('cluster'):
|
||||
clusterName = getText(cluster.find('name')).replace('[%s]', '')
|
||||
clusterDescription = getText(cluster.find('description'))
|
||||
|
@ -113,7 +115,8 @@ def readSVD(path, sourceURL):
|
|||
dimIncrement = int(getText(cluster.find('dimIncrement')), 0)
|
||||
clusterRegisters = []
|
||||
for regEl in cluster.findall('register'):
|
||||
clusterRegisters.append(parseRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix))
|
||||
clusterRegisters.extend(parseRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix))
|
||||
clusterRegisters.sort(key=lambda r: r['address'])
|
||||
if dimIncrement is None:
|
||||
lastReg = clusterRegisters[-1]
|
||||
lastAddress = lastReg['address']
|
||||
|
@ -161,22 +164,8 @@ def addInterrupt(interrupts, intrName, intrIndex, description):
|
|||
'description': description,
|
||||
}
|
||||
|
||||
def parseRegister(groupName, regEl, baseAddress, bitfieldPrefix=''):
|
||||
regName = getText(regEl.find('name'))
|
||||
regDescription = getText(regEl.find('description'))
|
||||
offsetEls = regEl.findall('offset')
|
||||
if not offsetEls:
|
||||
offsetEls = regEl.findall('addressOffset')
|
||||
address = baseAddress + int(getText(offsetEls[0]), 0)
|
||||
|
||||
dimEls = regEl.findall('dim')
|
||||
array = None
|
||||
if dimEls:
|
||||
array = int(getText(dimEls[0]), 0)
|
||||
regName = regName.replace('[%s]', '')
|
||||
|
||||
def parseBitfields(groupName, regName, fieldsEls, bitfieldPrefix=''):
|
||||
fields = []
|
||||
fieldsEls = regEl.findall('fields')
|
||||
if fieldsEls:
|
||||
for fieldEl in fieldsEls[0].findall('field'):
|
||||
fieldName = getText(fieldEl.find('name'))
|
||||
|
@ -216,15 +205,58 @@ def parseRegister(groupName, regEl, baseAddress, bitfieldPrefix=''):
|
|||
'description': enumDescription,
|
||||
'value': enumValue,
|
||||
})
|
||||
return fields
|
||||
|
||||
return {
|
||||
def parseRegister(groupName, regEl, baseAddress, bitfieldPrefix=''):
|
||||
regName = getText(regEl.find('name'))
|
||||
regDescription = getText(regEl.find('description'))
|
||||
offsetEls = regEl.findall('offset')
|
||||
if not offsetEls:
|
||||
offsetEls = regEl.findall('addressOffset')
|
||||
address = baseAddress + int(getText(offsetEls[0]), 0)
|
||||
|
||||
size = 4
|
||||
elSizes = regEl.findall('size')
|
||||
if elSizes:
|
||||
size = int(getText(elSizes[0]), 0) // 8
|
||||
|
||||
dimEls = regEl.findall('dim')
|
||||
fieldsEls = regEl.findall('fields')
|
||||
|
||||
array = None
|
||||
if dimEls:
|
||||
array = int(getText(dimEls[0]), 0)
|
||||
dimIncrement = int(getText(regEl.find('dimIncrement')), 0)
|
||||
if "[%s]" in regName:
|
||||
# just a normal array of registers
|
||||
regName = regName.replace('[%s]', '')
|
||||
elif "%s" in regName:
|
||||
# a "spaced array" of registers, special processing required
|
||||
# we need to generate a separate register for each "element"
|
||||
results = []
|
||||
for i in range(array):
|
||||
regAddress = address + (i * dimIncrement)
|
||||
results.append({
|
||||
'name': regName.replace('%s', str(i)),
|
||||
'address': regAddress,
|
||||
'description': regDescription.replace('\n', ' '),
|
||||
'bitfields': [],
|
||||
'array': None,
|
||||
'elementsize': size,
|
||||
})
|
||||
# set first result bitfield
|
||||
shortName = regName.replace('_%s', '').replace('%s', '')
|
||||
results[0]['bitfields'] = parseBitfields(groupName, shortName, fieldsEls, bitfieldPrefix)
|
||||
return results
|
||||
|
||||
return [{
|
||||
'name': regName,
|
||||
'address': address,
|
||||
'description': regDescription.replace('\n', ' '),
|
||||
'bitfields': fields,
|
||||
'bitfields': parseBitfields(groupName, regName, fieldsEls, bitfieldPrefix),
|
||||
'array': array,
|
||||
'elementsize': 4,
|
||||
}
|
||||
'elementsize': size,
|
||||
}]
|
||||
|
||||
def writeGo(outdir, device):
|
||||
# The Go module for this device.
|
||||
|
@ -243,11 +275,17 @@ package {pkgName}
|
|||
|
||||
import "unsafe"
|
||||
|
||||
// Special type that causes loads/stores to be volatile (necessary for
|
||||
// Special types that cause loads/stores to be volatile (necessary for
|
||||
// memory-mapped registers).
|
||||
//go:volatile
|
||||
type RegValue uint32
|
||||
|
||||
//go:volatile
|
||||
type RegValue16 uint16
|
||||
|
||||
//go:volatile
|
||||
type RegValue8 uint8
|
||||
|
||||
// Some information about this device.
|
||||
const (
|
||||
DEVICE = "{name}"
|
||||
|
@ -277,38 +315,67 @@ const (
|
|||
address = peripheral['baseAddress']
|
||||
padNumber = 0
|
||||
for register in peripheral['registers']:
|
||||
if address > register['address']:
|
||||
if address > register['address'] and 'registers' not in register :
|
||||
# In Nordic SVD files, these registers are deprecated or
|
||||
# duplicates, so can be ignored.
|
||||
#print('skip: %s.%s' % (peripheral['name'], register['name']))
|
||||
#print('skip: %s.%s %s - %s %s' % (peripheral['name'], register['name'], address, register['address'], register['elementsize']))
|
||||
continue
|
||||
eSize = register['elementsize']
|
||||
if eSize == 4:
|
||||
regType = 'RegValue'
|
||||
elif eSize == 2:
|
||||
regType = 'RegValue16'
|
||||
elif eSize == 1:
|
||||
regType = 'RegValue8'
|
||||
else:
|
||||
eSize = 4
|
||||
regType = 'RegValue'
|
||||
|
||||
# insert padding, if needed
|
||||
if address < register['address']:
|
||||
numSkip = (register['address'] - address) // 4
|
||||
if numSkip == 1:
|
||||
out.write('\t_padding{padNumber} RegValue\n'.format(padNumber=padNumber))
|
||||
bytesNeeded = register['address'] - address
|
||||
if bytesNeeded == 1:
|
||||
out.write('\t_padding{padNumber} {regType}\n'.format(padNumber=padNumber, regType='RegValue8'))
|
||||
elif bytesNeeded == 2:
|
||||
out.write('\t_padding{padNumber} {regType}\n'.format(padNumber=padNumber, regType='RegValue16'))
|
||||
else:
|
||||
out.write('\t_padding{padNumber} [{num}]RegValue\n'.format(padNumber=padNumber, num=numSkip))
|
||||
numSkip = (register['address'] - address) // eSize
|
||||
if numSkip == 1:
|
||||
out.write('\t_padding{padNumber} {regType}\n'.format(padNumber=padNumber, regType=regType))
|
||||
else:
|
||||
out.write('\t_padding{padNumber} [{num}]{regType}\n'.format(padNumber=padNumber, num=numSkip, regType=regType))
|
||||
padNumber += 1
|
||||
address = register['address']
|
||||
|
||||
regType = 'RegValue'
|
||||
lastCluster = False
|
||||
if 'registers' in 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['elementsize'] == 4:
|
||||
subregType = 'RegValue'
|
||||
elif subregister['elementsize'] == 2:
|
||||
subregType = 'RegValue16'
|
||||
else:
|
||||
subregType = 'RegValue8'
|
||||
|
||||
if subregister['array']:
|
||||
subregType = '[{}]{}'.format(subregister['array'], subregType)
|
||||
if subaddress != subregister['address']:
|
||||
numSkip = (subregister['address'] - subaddress) // 4
|
||||
if numSkip == 1:
|
||||
regType += '\t\t_padding{padNumber} RegValue\n'.format(padNumber=padNumber)
|
||||
bytesNeeded = subregister['address'] - subaddress
|
||||
if bytesNeeded == 1:
|
||||
regType += '\t\t_padding{padNumber} {subregType}\n'.format(padNumber=padNumber, subregType='RegValue8')
|
||||
elif bytesNeeded == 2:
|
||||
regType += '\t\t_padding{padNumber} {subregType}\n'.format(padNumber=padNumber, subregType='RegValue16')
|
||||
else:
|
||||
regType += '\t\t_padding{padNumber} [{num}]RegValue\n'.format(padNumber=padNumber, num=numSkip)
|
||||
numSkip = (subregister['address'] - subaddress)
|
||||
if numSkip == 1:
|
||||
regType += '\t\t_padding{padNumber} {subregType}\n'.format(padNumber=padNumber, subregType='RegValue8')
|
||||
else:
|
||||
regType += '\t\t_padding{padNumber} [{num}]{subregType}\n'.format(padNumber=padNumber, num=numSkip, subregType='RegValue8')
|
||||
padNumber += 1
|
||||
subaddress += bytesNeeded
|
||||
if subregister['array'] is not None:
|
||||
subaddress += subregister['elementsize'] * subregister['array']
|
||||
else:
|
||||
|
@ -317,10 +384,10 @@ const (
|
|||
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)
|
||||
if numSkip <= 1:
|
||||
regType += '\t\t_padding{padNumber} {subregType}\n'.format(padNumber=padNumber, subregType=subregType)
|
||||
else:
|
||||
regType += '\t\t_padding{padNumber} [{num}]RegValue\n'.format(padNumber=padNumber, num=numSkip)
|
||||
regType += '\t\t_padding{padNumber} [{num}]{subregType}\n'.format(padNumber=padNumber, num=numSkip, subregType=subregType)
|
||||
else:
|
||||
lastCluster = True
|
||||
regType += '\t}'
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче