Skip to content
Permalink
Browse files

generator: generate device wrappers for Atmel SAM family

Signed-off-by: Ron Evans <ron@hybridgroup.com>
  • Loading branch information...
deadprogram authored and aykevl committed Jan 9, 2019
1 parent b8c326d commit 8d1284cfe77b59b628f2756ed3998aa4ecab393c
Showing with 111 additions and 39 deletions.
  1. +2 −0 .gitignore
  2. +5 −2 Makefile
  3. +104 −37 tools/gen-device-svd.py
@@ -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
@@ -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

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 {
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 @@ def writeGo(outdir, device):
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 @@ def writeGo(outdir, device):
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 @@ def writeGo(outdir, device):
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}'

0 comments on commit 8d1284c

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.