Implement Burn Bootloader
This commit is contained in:
parent
533471fba8
commit
e13c7f5757
|
@ -57,25 +57,19 @@ class ASBuilder {
|
||||||
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
||||||
var args = [NSString]()
|
var args = [NSString]()
|
||||||
let boardProp = ASHardware.instance().boards[board]!
|
let boardProp = ASHardware.instance().boards[board]!
|
||||||
var corePath = ""
|
let library = boardProp["library"]!
|
||||||
|
var corePath = library+"/cores/"+boardProp["build.core"]!
|
||||||
var variantPath : NSString?
|
var variantPath : NSString?
|
||||||
for hw in ASHardware.instance().directories {
|
if fileManager.fileExistsAtPath(corePath) {
|
||||||
corePath = hw+"/cores/"+boardProp["build.core"]!
|
if let variantName = boardProp["build.variant"] {
|
||||||
if fileManager.fileExistsAtPath(corePath) {
|
variantPath = library+"/variants/"+variantName
|
||||||
if let variantName = boardProp["build.variant"] {
|
if fileManager.fileExistsAtPath(variantPath!) {
|
||||||
variantPath = hw+"/variants/"+variantName
|
args.append("variant="+variantName)
|
||||||
if fileManager.fileExistsAtPath(variantPath!) {
|
} else {
|
||||||
args.append("variant="+variantName)
|
variantPath = nil
|
||||||
} else {
|
|
||||||
variantPath = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break
|
|
||||||
} else {
|
|
||||||
corePath = ""
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if corePath == "" {
|
|
||||||
NSLog("Unable to find core %s\n", boardProp["build.core"]!)
|
NSLog("Unable to find core %s\n", boardProp["build.core"]!)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -98,8 +92,16 @@ class ASBuilder {
|
||||||
task!.arguments = args;
|
task!.arguments = args;
|
||||||
task!.launch()
|
task!.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadProject(board: String, programmer: String, port: String, terminal: Bool = false) {
|
enum Mode {
|
||||||
|
case Upload
|
||||||
|
case BurnBootloader
|
||||||
|
case Interactive
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadProject(board: String, programmer: String, port: String, mode: Mode = .Upload) {
|
||||||
|
let useProgrammer = mode != .Upload
|
||||||
|
let interactive = mode == .Interactive
|
||||||
let portPath = ASSerial.fileNameForPort(port)
|
let portPath = ASSerial.fileNameForPort(port)
|
||||||
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
|
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
|
||||||
task = NSTask()
|
task = NSTask()
|
||||||
|
@ -108,7 +110,7 @@ class ASBuilder {
|
||||||
|
|
||||||
let fileManager = NSFileManager.defaultManager()
|
let fileManager = NSFileManager.defaultManager()
|
||||||
var logOut : NSFileHandle
|
var logOut : NSFileHandle
|
||||||
if terminal {
|
if interactive {
|
||||||
let inputPipe = NSPipe()
|
let inputPipe = NSPipe()
|
||||||
let outputPipe = NSPipe()
|
let outputPipe = NSPipe()
|
||||||
logOut = outputPipe.fileHandleForWriting
|
logOut = outputPipe.fileHandleForWriting
|
||||||
|
@ -116,6 +118,7 @@ class ASBuilder {
|
||||||
task!.standardOutput = outputPipe
|
task!.standardOutput = outputPipe
|
||||||
task!.standardError = outputPipe
|
task!.standardError = outputPipe
|
||||||
} else {
|
} else {
|
||||||
|
ASSerialWin.portNeededForUpload(port)
|
||||||
let logURL = dir.URLByAppendingPathComponent("build/upload.log")
|
let logURL = dir.URLByAppendingPathComponent("build/upload.log")
|
||||||
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
|
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
|
||||||
logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
|
logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
|
||||||
|
@ -126,7 +129,7 @@ class ASBuilder {
|
||||||
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
||||||
let boardProp = ASHardware.instance().boards[board]!
|
let boardProp = ASHardware.instance().boards[board]!
|
||||||
let progProp = ASHardware.instance().programmers[programmer]
|
let progProp = ASHardware.instance().programmers[programmer]
|
||||||
let hasBootloader = boardProp["upload.protocol"] != nil
|
let hasBootloader = !useProgrammer && boardProp["upload.protocol"] != nil
|
||||||
let leonardish = hasBootloader && (boardProp["bootloader.path"] ?? "").hasPrefix("caterina")
|
let leonardish = hasBootloader && (boardProp["bootloader.path"] ?? "").hasPrefix("caterina")
|
||||||
let proto = hasBootloader ? boardProp["upload.protocol"] : progProp?["protocol"]
|
let proto = hasBootloader ? boardProp["upload.protocol"] : progProp?["protocol"]
|
||||||
let speed = hasBootloader ? boardProp["upload.speed"] : progProp?["speed"]
|
let speed = hasBootloader ? boardProp["upload.speed"] : progProp?["speed"]
|
||||||
|
@ -135,10 +138,59 @@ class ASBuilder {
|
||||||
args += [
|
args += [
|
||||||
"-C", toolChain+"/etc/avrdude.conf",
|
"-C", toolChain+"/etc/avrdude.conf",
|
||||||
"-p", boardProp["build.mcu"]!, "-c", proto!, "-P", portPath]
|
"-p", boardProp["build.mcu"]!, "-c", proto!, "-P", portPath]
|
||||||
if terminal {
|
switch mode {
|
||||||
args += ["-t"]
|
case .Upload:
|
||||||
} else {
|
if hasBootloader {
|
||||||
|
args += ["-D"]
|
||||||
|
}
|
||||||
args += ["-U", "flash:w:build/"+board+"/"+dir.lastPathComponent+".hex:i"]
|
args += ["-U", "flash:w:build/"+board+"/"+dir.lastPathComponent+".hex:i"]
|
||||||
|
continuation = {
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2*NSEC_PER_SEC)), dispatch_get_main_queue(), {
|
||||||
|
ASSerialWin.portAvailableAfterUpload(port)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case .BurnBootloader:
|
||||||
|
var loaderArgs = args
|
||||||
|
args += ["-e"]
|
||||||
|
if let unlock = boardProp["bootloader.unlock_bits"] {
|
||||||
|
args += ["-Ulock:w:"+unlock+":m"]
|
||||||
|
}
|
||||||
|
if let efuse = boardProp["bootloader.extended_fuses"] {
|
||||||
|
args += ["-Uefuse:w:"+efuse+":m"]
|
||||||
|
}
|
||||||
|
let hfuse = boardProp["bootloader.high_fuses"]!
|
||||||
|
let lfuse = boardProp["bootloader.low_fuses"]!
|
||||||
|
args += ["-Uhfuse:w:"+hfuse+":m", "-Ulfuse:w:"+lfuse+":m"]
|
||||||
|
var needPhase2 = false
|
||||||
|
if let loaderPath = boardProp["bootloader.path"] {
|
||||||
|
let loader = boardProp["library"]!+"/bootloaders/"+loaderPath+"/"+boardProp["bootloader.file"]!
|
||||||
|
loaderArgs += ["-Uflash:w:"+loader+":i"]
|
||||||
|
needPhase2 = true
|
||||||
|
}
|
||||||
|
if let lock = boardProp["bootloader.lock_bits"] {
|
||||||
|
loaderArgs += ["-Ulock:w:"+lock+":m"]
|
||||||
|
needPhase2 = true
|
||||||
|
}
|
||||||
|
if needPhase2 {
|
||||||
|
let task2 = NSTask()
|
||||||
|
task2.currentDirectoryPath = dir.path!
|
||||||
|
task2.launchPath = toolChain+"/bin/avrdude"
|
||||||
|
task2.arguments = loaderArgs
|
||||||
|
task2.standardOutput = logOut
|
||||||
|
task2.standardError = logOut
|
||||||
|
continuation = {
|
||||||
|
let cmdLine = task2.launchPath+" "+(loaderArgs as NSArray).componentsJoinedByString(" ")+"\n"
|
||||||
|
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
||||||
|
task2.launch()
|
||||||
|
self.continuation = {
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2*NSEC_PER_SEC)), dispatch_get_main_queue(), {
|
||||||
|
ASSerialWin.portAvailableAfterUpload(port)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .Interactive:
|
||||||
|
args += ["-t"]
|
||||||
}
|
}
|
||||||
if speed != nil {
|
if speed != nil {
|
||||||
args.append("-b")
|
args.append("-b")
|
||||||
|
@ -171,7 +223,7 @@ class ASBuilder {
|
||||||
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
||||||
task!.arguments = args;
|
task!.arguments = args;
|
||||||
task!.launch()
|
task!.launch()
|
||||||
if terminal {
|
if interactive {
|
||||||
let intSpeed = speed?.toInt() ?? 19200
|
let intSpeed = speed?.toInt() ?? 19200
|
||||||
ASSerialWin.showWindowWithPort(port, task:task!, speed:intSpeed)
|
ASSerialWin.showWindowWithPort(port, task:task!, speed:intSpeed)
|
||||||
task = nil
|
task = nil
|
||||||
|
|
|
@ -72,6 +72,7 @@ class ASHardware {
|
||||||
if seen.updateValue(true, forKey: board) == nil {
|
if seen.updateValue(true, forKey: board) == nil {
|
||||||
boards[board] = ASPropertyEntry()
|
boards[board] = ASPropertyEntry()
|
||||||
boards[board]!["provenience"] = provenience
|
boards[board]!["provenience"] = provenience
|
||||||
|
boards[board]!["library"] = dir
|
||||||
}
|
}
|
||||||
boards[board]![property] = value
|
boards[board]![property] = value
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,12 +468,6 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
|
||||||
@IBAction func uploadProject(sender: AnyObject) {
|
@IBAction func uploadProject(sender: AnyObject) {
|
||||||
builder.continuation = {
|
builder.continuation = {
|
||||||
self.selectNodeInOutline(self.files.uploadLog)
|
self.selectNodeInOutline(self.files.uploadLog)
|
||||||
ASSerialWin.portNeededForUpload(self.port)
|
|
||||||
self.builder.continuation = {
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2*NSEC_PER_SEC)), dispatch_get_main_queue(), {
|
|
||||||
ASSerialWin.portAvailableAfterUpload(self.port)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
dispatch_async(dispatch_get_main_queue(), {
|
dispatch_async(dispatch_get_main_queue(), {
|
||||||
self.builder.uploadProject(self.board, programmer:self.programmer, port:self.port)
|
self.builder.uploadProject(self.board, programmer:self.programmer, port:self.port)
|
||||||
})
|
})
|
||||||
|
@ -482,7 +476,12 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func uploadTerminal(sender: AnyObject) {
|
@IBAction func uploadTerminal(sender: AnyObject) {
|
||||||
builder.uploadProject(board, programmer:programmer, port:port, terminal:true)
|
builder.uploadProject(board, programmer:programmer, port:port, mode:.Interactive)
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func burnBootloader(sender: AnyObject) {
|
||||||
|
self.selectNodeInOutline(self.files.uploadLog)
|
||||||
|
builder.uploadProject(board, programmer:programmer, port:port, mode:.BurnBootloader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func disassembleProject(sender: AnyObject) {
|
@IBAction func disassembleProject(sender: AnyObject) {
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="751" height="403"/>
|
<rect key="frame" x="0.0" y="0.0" width="751" height="403"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rIR-2b-lAh">
|
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rIR-2b-lAh">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="651" height="22"/>
|
<rect key="frame" x="0.0" y="2" width="601" height="22"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="EBj-i4-UsA">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="EBj-i4-UsA">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -39,10 +39,10 @@
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MOe-eO-fyb">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MOe-eO-fyb">
|
||||||
<rect key="frame" x="651" y="0.0" width="50" height="20"/>
|
<rect key="frame" x="601" y="0.0" width="75" height="20"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="20" id="eLx-yy-gCn"/>
|
<constraint firstAttribute="height" constant="20" id="eLx-yy-gCn"/>
|
||||||
<constraint firstAttribute="width" constant="50" id="vaT-Kd-3pn"/>
|
<constraint firstAttribute="width" constant="75" id="vaT-Kd-3pn"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<buttonCell key="cell" type="square" title="Send" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Xt6-lT-b4z">
|
<buttonCell key="cell" type="square" title="Send" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Xt6-lT-b4z">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
@ -58,9 +58,9 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H05-Rp-UzR">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H05-Rp-UzR">
|
||||||
<rect key="frame" x="701" y="0.0" width="50" height="20"/>
|
<rect key="frame" x="676" y="0.0" width="75" height="20"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="50" id="FWw-BQ-WKa"/>
|
<constraint firstAttribute="width" constant="75" id="FWw-BQ-WKa"/>
|
||||||
<constraint firstAttribute="height" constant="20" id="s7i-ZT-S7W"/>
|
<constraint firstAttribute="height" constant="20" id="s7i-ZT-S7W"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<buttonCell key="cell" type="square" title="Now" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vZ4-fd-aE8">
|
<buttonCell key="cell" type="square" title="Now" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vZ4-fd-aE8">
|
||||||
|
|
|
@ -395,6 +395,12 @@
|
||||||
<action selector="uploadProject:" target="-1" id="Un4-q1-nWg"/>
|
<action selector="uploadProject:" target="-1" id="Un4-q1-nWg"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Burn Bootloader/Fuses" id="vvl-LN-SXu">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="burnBootloader:" target="-1" id="FYp-at-8g4"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
<menuItem title="Upload Terminal" keyEquivalent="U" id="jAF-od-ZFb">
|
<menuItem title="Upload Terminal" keyEquivalent="U" id="jAF-od-ZFb">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="uploadTerminal:" target="-1" id="hth-ZZ-S3I"/>
|
<action selector="uploadTerminal:" target="-1" id="hth-ZZ-S3I"/>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user