之前写过一篇文章《STM32(在F051上调试通过)配置从SDRAM上启动》https://mp.youkuaiyun.com/mp_blog/creation/editor/127169382,参考该文章可以手工配置从SDRAM上运行程序,但是学习过程中配置起来有些麻烦,每次需要一项项修改一些数据,而且还需要手工计算SDRAM的大小分配,挺麻烦的。开发板的配套光盘都是从Flash上运行,每次学习调试都需要重新配置。希望可以自动配置从Flash还是从SDRAM上运行程序。猜想Keil的工程配置应该在会以文本的方式保存下来,直接修改配置文件应该能达到效果。
经过修改配置,用Beyond Compare工具比对修改前后的文件夹,终于找到了相关配置项保存的位置。main.uvproj和main.uvopt这两个XML文件都会保存,而且有些恶心的是有些配置修改后两个文件都有保存,经过N次尝试后,终于都找到相关配置了。
本程序使用Python实现,通过xml.dom.minidom库修改XML文件,本人第一次使用这个库,不怎么会用,也没那么多时间去查资料,写的代码比较水,勉强能用,需要的可以自己更新。
使用说明,配置如下三个选项即可
SizeInfoStr是KEIL的编译结果内容拷贝 XMLFilePath1:工程文件路径 DownLoadRunConfig :配置 从SDRAM上还是Flash上运行
主要工作量是在找到配置文件修改点,代码很简单自己查看,总体思路:解析编译结果,计算SDRAM分配,解析XML,修改XML,保存文件,计算SDRAM的时候先优先按整K字节分配,满足不了才使用精确字节数分配
直接上代码了,随便拷贝
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from xml.dom.minidom import parse
import xml.dom.minidom
#
SizeInfoStr="Program Size: Code=3368 RO-data=224 RW-data=36 ZI-data=1636"
#SizeInfoStr="Program Size: Code=6844 RO-data=224 RW-data=44 ZI-data=1668"
XMLFilePath1=r'D:\code\GreenWind\实验一:led闪烁(库函数)\user\main.uvproj'
DownLoadRunConfig="SDRAM" # Flash 在Flash上运行 SDRAM 在SDRAM上运行
##################################################
def AddFlag(ProcessStr):
ProcessStr = ProcessStr.replace('''<?xml version="1.0" ?>''',
'''<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n''')
ProcessStr = ProcessStr.replace('''"''', '''"''')
ProcessStrList = ProcessStr.split("\n")
for i in range(0, len(ProcessStrList)):
if "/>" in ProcessStrList[i]:
TempFlag = ProcessStrList[i].strip(" ")
LeftStr = TempFlag.replace("/>", ">")
RightStr = LeftStr.replace("<", "</")
ProcessStrList[i]=ProcessStrList[i].replace(TempFlag, LeftStr + RightStr)
#print(i,ProcessStrList[i])
ReturnStr=""
for i in range(0, len(ProcessStrList)):
ReturnStr=ReturnStr+ProcessStrList[i]+"\n"
return ReturnStr
def SetNodeValue(RootNode,UpdateNode,Value):
try:
#print("节点已存在")
UpdateNode[0].childNodes[0].data = Value
except:
print("节点不存在",Value)
temp_text_value = RootNode.createTextNode(Value)
UpdateNode[0].appendChild(temp_text_value)
# Utilities
XMLFilePath2=XMLFilePath1[:-6]+"uvopt"
print(XMLFilePath2)
OutPutXML1=XMLFilePath1
OutPutXML2=XMLFilePath2
SDRAMSize=1024*8 # 8 Kbytes of SRAM with HW parity checking
SDRAMBaseAddr=0x20000000
SizeInfoStrList=SizeInfoStr.split(" ")
Code=SizeInfoStrList[2][5:]
ROdata=SizeInfoStrList[3][8:]
RWdata=SizeInfoStrList[4][8:]
ZIdata=SizeInfoStrList[5][8:]
print("Code=",Code)
print("ROdata=",ROdata)
print("RWdata=",RWdata)
print("ZIdata=",ZIdata)
ROMSize=int(Code)+int(ROdata)
RAMSize=int(RWdata)+int(ZIdata)
print("ROMSize=%d 0x%x Old " %(ROMSize,ROMSize))
print("RAMSize=%d 0x%x Old " %(RAMSize,RAMSize))
if(SDRAMSize<ROMSize+RAMSize):
print("SDRAM 空间不足,无法使用SDRAM调试 SDRAMSize=%d ROMSize+RAMSize=%d" %(SDRAMSize,ROMSize+RAMSize))
exit(0)
else:
print("SDRAM 空间满足,可以使用SDRAM调试 SDRAMSize=%d ROMSize+RAMSize=%d" %(SDRAMSize,ROMSize+RAMSize))
bIntKSize=0 #内存按整K分配
ExtraSize=0 #对于ROM多评估一些字节
ROMInt=0
RAMInt=0
SDRAMMapList=[[7,1],[6,2],[5,3],[4,4],[3,5],[2,6]]
for i in range(0,len(SDRAMMapList)):
ROMInt=SDRAMMapList[i][0]
RAMInt=SDRAMMapList[i][1]
if (ROMInt*1024>=ROMSize and RAMInt*1024>=RAMSize):
print("选择方案 ",i+1," ",SDRAMMapList[i])
bIntKSize=1
break
if bIntKSize:
ROMSize=ROMInt*1024
RAMSize=RAMInt*1024
else:
ROMSize=ROMSize+ExtraSize
RAMSize=SDRAMSize-ROMSize
print("ROMSize=%d 0x%x" %(ROMSize,ROMSize))
print("RAMSize=%d 0x%x" %(RAMSize,RAMSize))
IROM1_Addr=SDRAMBaseAddr
IROM1_Size=ROMSize
IRAM1_Addr=SDRAMBaseAddr +ROMSize
IRAM1_Size=RAMSize
print("IROM1:0x%X 0x%X" %(IROM1_Addr,IROM1_Size))
print("IRAM1:0x%X 0x%X" %(IRAM1_Addr,IRAM1_Size))
RamForAlgorithmStart=IRAM1_Addr
print("RamForAlgorithm Start:0x%X Size:0x%X" %(IRAM1_Addr,IRAM1_Size)) #需要调试看是否需要修改为0x0800
print("Programming Algorithm Start:0x%0.8X Size:0x%0.8X" %(SDRAMBaseAddr,SDRAMSize)) #需要调试看是否需要修改为0x0800
#'''-U-O206 -O206 -S3 -C-1 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO14 -FD20001800 -FC800 -FN1 -FF0STM32F0xx_64 -FS020000000 -FL02000'''
if(DownLoadRunConfig=="Flash"):
SetRegEntryNameStr = (
'''-U-O206 -O206 -S3 -C-1 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD%0.8X -FC%X-FN1 -FF0STM32F0xx_64 -FS0%X -FL0%X''' % (
0x20000000, 0x0800, 0x8000000, 0x10000))
else:
SetRegEntryNameStr=('''-U-O206 -O206 -S3 -C-1 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO14 -FD%0.8X -FC%X-FN1 -FF0STM32F0xx_64 -FS0%X -FL0%X''' %(IRAM1_Addr,IRAM1_Size,SDRAMBaseAddr,SDRAMSize))
#print("SetRegEntryName=",SetRegEntryNameStr)
# if RAMSize<0x0800:
# print("内存分配不足 %x" %RAMSize)
# exit(0)
#后面代码是修改XML文件
# 使用minidom解析器打开 XML 文档
DOMTree1 = xml.dom.minidom.parse(XMLFilePath1)
DOMTree2= xml.dom.minidom.parse(XMLFilePath2)
Project = DOMTree1.documentElement
ProjectOpt= DOMTree2.documentElement
# if Project.hasAttribute("xmlns:xsi"):
# print("Root element : %s" % Project.getAttribute("xmlns:xsi"))
# 在集合中获取所有
Targets = Project.getElementsByTagName("Targets")
print("len(Targets)=",len(Targets))
Target=Targets[0]
#Target
TargetName = Target.getElementsByTagName('TargetName')
OutputName=Target.getElementsByTagName('OutputName')
CreateHexFile=Target.getElementsByTagName('CreateHexFile')
DebugOption=Target.getElementsByTagName('DebugOption')
DebugOptionTarget=DebugOption[0].getElementsByTagName('Target')
UseTarget=DebugOptionTarget[0].getElementsByTagName('UseTarget')
UseTargetLoadApplicationAtStartup=DebugOptionTarget[0].getElementsByTagName('LoadApplicationAtStartup')
UseTargetRunToMain=DebugOptionTarget[0].getElementsByTagName('RunToMain')
useUlib=Target.getElementsByTagName('useUlib')
TargetDlls=Target.getElementsByTagName('TargetDlls')
TargetDllsInitializationFile=TargetDlls[0].getElementsByTagName('InitializationFile')
OCR_RVCT4=Target.getElementsByTagName('OCR_RVCT4')
OCR_RVCT4_Type=OCR_RVCT4[0].getElementsByTagName('Type')
OCR_RVCT4_StartAddress=OCR_RVCT4[0].getElementsByTagName('StartAddress')
OCR_RVCT4_Size=OCR_RVCT4[0].getElementsByTagName('Size')
OCR_RVCT9=Target.getElementsByTagName('OCR_RVCT9')
OCR_RVCT9_Type=OCR_RVCT9[0].getElementsByTagName('Type')
OCR_RVCT9_StartAddress=OCR_RVCT9[0].getElementsByTagName('StartAddress')
OCR_RVCT9_Size=OCR_RVCT9[0].getElementsByTagName('Size')
UseSimulator=Target.getElementsByTagName('UseSimulator')
Utilities=Target.getElementsByTagName('Utilities')
bUseTDR=Utilities[0].getElementsByTagName('bUseTDR')
if(len(bUseTDR)==0):
temp_node = DOMTree1.createElement("bUseTDR")
Utilities[0].appendChild(temp_node)
bUseTDR = Utilities[0].getElementsByTagName('bUseTDR')
pass
UpdateFlashBeforeDebugging=Utilities[0].getElementsByTagName('UpdateFlashBeforeDebugging')
#####main.uvopt文件
OptSetRegEntry=ProjectOpt.getElementsByTagName('SetRegEntry')
for i in range(0,len(OptSetRegEntry)):
if OptSetRegEntry[i].getElementsByTagName('Key')[0].childNodes[0].data=="ST-LINKIII-KEIL_SWO":
OptSetRegEntryName=OptSetRegEntry[i].getElementsByTagName('Name')
break
OptTargets=ProjectOpt.getElementsByTagName('Target')
OptTarget=OptTargets[0]
OptTargetName=OptTarget.getElementsByTagName('TargetName')
OptDebugOpt=OptTarget.getElementsByTagName('OptDebugOpt')
OptuSim=OptTarget.getElementsByTagName('uSim')
OptuTrg=OptTarget.getElementsByTagName('uTrg')
OpttIfile=OptTarget.getElementsByTagName('tIfile')
OpttLdApp=OptTarget.getElementsByTagName('tLdApp')
OpttGomain=OptTarget.getElementsByTagName('tGomain')
if(DownLoadRunConfig=="Flash"):
# Project- File Extensions
SetNodeValue(DOMTree1, TargetName, "FlashOut")
SetNodeValue(DOMTree2, OptTargetName, "FlashOut")
# Target页面配置
# Use Micro LIB
SetNodeValue(DOMTree1, useUlib, "1")
##IROM1
SetNodeValue(DOMTree1, OCR_RVCT4_Type, "1")
SetNodeValue(DOMTree1, OCR_RVCT4_StartAddress, ("0x%X" % 0x8000000))
SetNodeValue(DOMTree1, OCR_RVCT4_Size, ("0x%X" % 0x10000))
##IRAM1
SetNodeValue(DOMTree1, OCR_RVCT9_Type, "0")
SetNodeValue(DOMTree1, OCR_RVCT9_StartAddress, ("0x%X" % 0x20000000))
SetNodeValue(DOMTree1, OCR_RVCT9_Size, ("0x%X" % 0x2000))
# Output页面配置
##Name of Executable
SetNodeValue(DOMTree1, OutputName, "main")
##Create HEX File
SetNodeValue(DOMTree1, CreateHexFile, "1")
# Debug页面配置
##Use Simulator
SetNodeValue(DOMTree1, UseSimulator, "0")
SetNodeValue(DOMTree2, OptuSim, "0")
##DebugOptionTarget
SetNodeValue(DOMTree1, UseTarget, "1")
SetNodeValue(DOMTree1, UseTargetLoadApplicationAtStartup, "1")
SetNodeValue(DOMTree1, UseTargetRunToMain, "1")
SetNodeValue(DOMTree2, OptuTrg, "1")
SetNodeValue(DOMTree2, OpttLdApp, "1")
SetNodeValue(DOMTree2, OpttGomain, "1")
# ##TargetDlls
# TargetDllsInitializationFile[0]
# 创建phone节点,并设置textValue
SetNodeValue(DOMTree1, TargetDllsInitializationFile, "")
SetNodeValue(DOMTree2, OpttIfile, "")
# Utilities
SetNodeValue(DOMTree1, bUseTDR, "0")
SetNodeValue(DOMTree1, UpdateFlashBeforeDebugging, "1")
# Flash Download
SetNodeValue(DOMTree2, OptSetRegEntryName, SetRegEntryNameStr)
else:
#Project- File Extensions
SetNodeValue(DOMTree1,TargetName,"RamOut")
SetNodeValue(DOMTree2,OptTargetName,"RamOut")
#Target页面配置
#Use Micro LIB
SetNodeValue(DOMTree1,useUlib,"1")
##IROM1
SetNodeValue(DOMTree1,OCR_RVCT4_Type,"1")
SetNodeValue(DOMTree1,OCR_RVCT4_StartAddress,("0x%X" % SDRAMBaseAddr))
SetNodeValue(DOMTree1,OCR_RVCT4_Size,("0x%X" % IROM1_Size))
##IRAM1
SetNodeValue(DOMTree1,OCR_RVCT9_Type,"0")
SetNodeValue(DOMTree1,OCR_RVCT9_StartAddress,("0x%X" % IRAM1_Addr))
SetNodeValue(DOMTree1,OCR_RVCT9_Size,("0x%X" % IRAM1_Size))
#Output页面配置
##Name of Executable
SetNodeValue(DOMTree1,OutputName,"main")
##Create HEX File
SetNodeValue(DOMTree1,CreateHexFile,"1")
#Debug页面配置
##Use Simulator
SetNodeValue(DOMTree1,UseSimulator,"0")
SetNodeValue(DOMTree2,OptuSim,"0")
##DebugOptionTarget
SetNodeValue(DOMTree1,UseTarget,"1")
SetNodeValue(DOMTree1,UseTargetLoadApplicationAtStartup,"0")
SetNodeValue(DOMTree1,UseTargetRunToMain,"0")
SetNodeValue(DOMTree2,OptuTrg,"1")
SetNodeValue(DOMTree2,OpttLdApp,"0")
SetNodeValue(DOMTree2,OpttGomain,"0")
# ##TargetDlls
#TargetDllsInitializationFile[0]
# 创建phone节点,并设置textValue
SetNodeValue(DOMTree1,TargetDllsInitializationFile,"..\\..\\RAM2.ini")
SetNodeValue(DOMTree2,OpttIfile,"..\\..\\RAM2.ini")
#Utilities
SetNodeValue(DOMTree1,bUseTDR,"0")
SetNodeValue(DOMTree1,UpdateFlashBeforeDebugging,"1")
#Flash Download
SetNodeValue(DOMTree2,OptSetRegEntryName,SetRegEntryNameStr)
#保存文件
fw = open(OutPutXML1, 'w',encoding="utf-8")
fw.write(AddFlag(DOMTree1.toxml()))
fw.close()
fw = open(OutPutXML2, 'w',encoding="utf-8")
fw.write(AddFlag(DOMTree2.toxml()))
fw.close()
exit(1)