172 lines
5.2 KiB
Python
172 lines
5.2 KiB
Python
|
from string import Template
|
||
|
import textwrap
|
||
|
import re
|
||
|
|
||
|
|
||
|
def fix_startup_file(config, filename):
|
||
|
|
||
|
# Get the stack size from the config file. Note that the startup file
|
||
|
# measures in words, not bytes.
|
||
|
stack_size = config['STACK']['size']
|
||
|
|
||
|
# Read in every line of the given file
|
||
|
input_lines = None
|
||
|
with open(filename) as f:
|
||
|
input_lines = [line for line in f]
|
||
|
|
||
|
# Perform a search-and-replace with the new stack size.
|
||
|
def fix_line(line):
|
||
|
return re.sub(r'(Stack EQU )0x[0-9a-fA-F]*',
|
||
|
r'\g<1>' + '0x{:08X}'.format(stack_size),
|
||
|
line)
|
||
|
|
||
|
output_lines = map(fix_line, input_lines)
|
||
|
output_text = ''.join(output_lines)
|
||
|
|
||
|
# Write the new file back to the input
|
||
|
with open(filename, 'w') as f:
|
||
|
f.write(output_text)
|
||
|
|
||
|
|
||
|
def generate_link_script(config):
|
||
|
|
||
|
mapping = dict()
|
||
|
mapping['ro_base'] = format_number(config['ROMEM']['start'])
|
||
|
mapping['ro_size'] = format_number(config['ROMEM']['size'])
|
||
|
mapping['rw_base'] = format_number(config['RWMEM']['start'])
|
||
|
mapping['rw_size'] = format_number(config['RWMEM']['size'])
|
||
|
mapping['stack_base'] = format_number(config['STACK']['start'])
|
||
|
mapping['stack_size'] = format_number(config['STACK']['size'])
|
||
|
mapping['tcm_base'] = format_number(config['TCM']['start'])
|
||
|
mapping['tcm_size'] = format_number(config['TCM']['size'])
|
||
|
mapping['additional_sections'] = generate_sections(config)
|
||
|
|
||
|
link_script = link_script_template.substitute(**mapping)
|
||
|
debug_file = debug_file_template.substitute(**mapping)
|
||
|
|
||
|
return (link_script, debug_file)
|
||
|
|
||
|
|
||
|
def generate_sections(config):
|
||
|
# If there aren't any custom sections in the config file, we don't need to
|
||
|
# add anything to the linker scripts.
|
||
|
if 'custom_sections' not in config:
|
||
|
return ''
|
||
|
elif not config['custom_sections']:
|
||
|
return ''
|
||
|
|
||
|
L = []
|
||
|
for mem_section in config['custom_sections']:
|
||
|
D = dict()
|
||
|
D['name'] = mem_section['blockname']
|
||
|
D['start'] = format_number(mem_section['start'])
|
||
|
D['length'] = format_number(mem_section['length'])
|
||
|
D['sections'] = '\n'.join(' * ({})'.format(x) for x in mem_section['sections'])
|
||
|
|
||
|
S = extra_section_template.substitute(**D)
|
||
|
L.append(textwrap.indent(S, 4 * ' '))
|
||
|
|
||
|
return '\n' + '\n'.join(L)
|
||
|
|
||
|
|
||
|
def format_number(n):
|
||
|
return '0x{:08X}'.format(n)
|
||
|
|
||
|
|
||
|
link_script_template = Template('''\
|
||
|
;******************************************************************************
|
||
|
;
|
||
|
; Scatter file for Keil linker configuration.
|
||
|
;
|
||
|
;******************************************************************************
|
||
|
LR_1 ${ro_base}
|
||
|
{
|
||
|
ROMEM ${ro_base} ${ro_size}
|
||
|
{
|
||
|
*.o (RESET, +First)
|
||
|
* (+RO)
|
||
|
}
|
||
|
|
||
|
RWMEM ${rw_base} ${rw_size}
|
||
|
{
|
||
|
* (+RW, +ZI)
|
||
|
}
|
||
|
|
||
|
TCM ${tcm_base} ${tcm_size}
|
||
|
{
|
||
|
* (.tcm)
|
||
|
}
|
||
|
|
||
|
STACKMEM ${stack_base} ${stack_size}
|
||
|
{
|
||
|
startup_keil.o (STACK)
|
||
|
}
|
||
|
}
|
||
|
''')
|
||
|
|
||
|
extra_section_template = Template('''\
|
||
|
${name} ${start} ${length}
|
||
|
{
|
||
|
${sections}
|
||
|
}
|
||
|
''')
|
||
|
|
||
|
debug_file_template = Template('''\
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Name: Dbg_RAM.ini
|
||
|
* Purpose: RAM Debug Initialization File
|
||
|
* Note(s):
|
||
|
*----------------------------------------------------------------------------
|
||
|
* This file is part of the uVision/ARM development tools.
|
||
|
* This software may only be used under the terms of a valid, current,
|
||
|
* end user licence from KEIL for a compatible version of KEIL software
|
||
|
* development tools. Nothing else gives you the right to use this software.
|
||
|
*
|
||
|
* This software is supplied "AS IS" without warranties of any kind.
|
||
|
*
|
||
|
* Copyright (c) 2008-2013 Keil - An ARM Company. All rights reserved.
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
TraceSetup() Turn on ITM clocks, etc.
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
FUNC void TraceSetup (void)
|
||
|
{
|
||
|
// turn on the ITM/TPIU clock
|
||
|
//_WDWORD(0x40020250, 0x00000201); // TPIU clock enabled at 3MHz
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
Setup() configure PC & SP for RAM Debug
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
FUNC void Setup (void) {
|
||
|
SP = _RDWORD(${ro_base}+0x0); // Setup Stack Pointer
|
||
|
PC = _RDWORD(${ro_base}+0x4); // Setup Program Counter
|
||
|
_WDWORD(0xE000ED08, ${ro_base}+0x0); // Setup Vector Table Offset Register (done in system file)
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
OnResetExec() executed after reset via uVision's 'Reset'-button
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
FUNC void OnResetExec (void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
LOAD %L INCREMENTAL // load the application
|
||
|
Setup(); // Setup for Running
|
||
|
|
||
|
BS main
|
||
|
g
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
''')
|
||
|
|
||
|
extra_section_template = Template('''\
|
||
|
${name} ${start} ${length}
|
||
|
{
|
||
|
${sections}
|
||
|
}
|
||
|
''')
|