Skip to content

Commit

Permalink
Issue #2 - Add support for Micro (ATMega32U4 / AVR109 protocol)
Browse files Browse the repository at this point in the history
  • Loading branch information
christophediericx committed Jan 11, 2017
1 parent a328558 commit 46054f5
Show file tree
Hide file tree
Showing 63 changed files with 737 additions and 187 deletions.
Binary file added Documentation/AVR109.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion Source/ArduinoSketchUploader/CommandLineOptions.cs
Expand Up @@ -12,7 +12,7 @@ internal class CommandLineOptions
[Option('p', "port", Required = true, HelpText = "Name of the COM port where the Arduino is attached (e.g. 'COM1', 'COM2', 'COM3'...).")]
public string PortName { get; set; }

[Option('m', "model", Required = true, HelpText = "Arduino model. Valid parameters are any of the following: [Mega2560, NanoR3, UnoR3].")]
[Option('m', "model", Required = true, HelpText = "Arduino model. Valid parameters are any of the following: [Mega2560, Micro, NanoR3, UnoR3].")]
public ArduinoModel ArduinoModel { get; set; }

[ParserState]
Expand Down
2 changes: 1 addition & 1 deletion Source/ArduinoSketchUploader/NLog.config
Expand Up @@ -8,7 +8,7 @@
</targets>

<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
<logger name="*" minlevel="Debug" writeTo="console" />
</rules>
</nlog>
89 changes: 24 additions & 65 deletions Source/ArduinoUploader/ArduinoSketchUploader.cs
@@ -1,23 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using ArduinoUploader.BootloaderProgrammers;
using ArduinoUploader.Hardware;
using IntelHexFormatReader;
using IntelHexFormatReader.Model;
using NLog;
using RJCP.IO.Ports;

namespace ArduinoUploader
{
public class ArduinoSketchUploader
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private readonly ArduinoSketchUploaderOptions options;
private UploaderSerialPort serialPort;

private const int SerialPortTimeOut = 1000;

public ArduinoSketchUploader(ArduinoSketchUploaderOptions options)
{
Expand All @@ -37,55 +34,61 @@ public void UploadSketch(IEnumerable<string> hexFileContents)
{
var serialPortName = options.PortName;

var ports = SerialPort.GetPortNames();
var ports = SerialPortStream.GetPortNames();

if (!ports.Any() || ports.Distinct().SingleOrDefault(
x => x.Equals(serialPortName, StringComparison.OrdinalIgnoreCase)) == null)
{
UploaderLogger.LogAndThrowError<ArgumentException>(
UploaderLogger.LogErrorAndQuit(
string.Format("Specified COM port name '{0}' is not valid.", serialPortName));
}

logger.Trace("Creating serial port '{0}'...", serialPortName);
SerialPortBootloaderProgrammer programmer = null;

IMCU mcu = null;
SerialPortConfig serialPortConfig;

switch (options.ArduinoModel)
{
case ArduinoModel.Mega2560:
{
mcu = new ATMega2560();
serialPort = new UploaderSerialPort(serialPortName, 115200);
programmer = new WiringBootloaderProgrammer(serialPort, mcu);
serialPortConfig = new SerialPortConfig(serialPortName, 115200);
programmer = new WiringBootloaderProgrammer(serialPortConfig, mcu);
break;
}
case ArduinoModel.Micro:
{
mcu = new ATMega32U4();
serialPortConfig = new SerialPortConfig(serialPortName, 57600);
programmer = new ButterflyBootloaderProgrammer(serialPortConfig, mcu);
break;
}
case ArduinoModel.NanoR3:
{
mcu = new ATMega328P();
serialPort = new UploaderSerialPort(serialPortName, 57600);
programmer = new OptibootBootloaderProgrammer(serialPort, mcu);
serialPortConfig = new SerialPortConfig(serialPortName, 57600);
programmer = new OptibootBootloaderProgrammer(serialPortConfig, mcu);
break;
}
case ArduinoModel.UnoR3:
{
mcu = new ATMega328P();
serialPort = new UploaderSerialPort(serialPortName, 115200);
programmer = new OptibootBootloaderProgrammer(serialPort, mcu);
serialPortConfig = new SerialPortConfig(serialPortName, 115200);
programmer = new OptibootBootloaderProgrammer(serialPortConfig, mcu);
break;
}
default:
{
UploaderLogger.LogAndThrowError<IOException>(
UploaderLogger.LogErrorAndQuit(
string.Format("Unsupported model: {0}!", options.ArduinoModel));
break;
}
}

try
{
TryToOpenSerialPort();
ConfigureSerialPort();

programmer.Open();

logger.Info("Establishing sync...");
Expand All @@ -108,11 +111,13 @@ public void UploadSketch(IEnumerable<string> hexFileContents)
programmer.ProgramDevice(ReadHexFile(hexFileContents, mcu.Flash.Size));
logger.Info("Device programmed.");

programmer.Close();
logger.Info("Leaving programming mode...");
programmer.LeaveProgrammingMode();
logger.Info("Left programming mode!");
}
finally
{
CloseSerialPort();
programmer.Close();
}
logger.Info("All done, shutting down!");
}
Expand All @@ -128,57 +133,11 @@ private static MemoryBlock ReadHexFile(IEnumerable<string> hexFileContents, int
}
catch (Exception ex)
{
UploaderLogger.LogAndThrowError<IOException>(ex.Message);
UploaderLogger.LogErrorAndQuit(ex.Message);
}
return null;
}

private void TryToOpenSerialPort()
{
logger.Trace("Opening serial port...");
try
{
serialPort.Open();
}
catch (UnauthorizedAccessException)
{
UploaderLogger.LogAndThrowError<UnauthorizedAccessException>(
"Access to the port is denied. This or another process is currently using this port.");
}
catch (ArgumentOutOfRangeException)
{
UploaderLogger.LogAndThrowError<ArgumentOutOfRangeException>(
"The configuration parameters for the port are invalid (e.g. baud rate, parity, databits).");
}
catch (IOException)
{
UploaderLogger.LogAndThrowError<IOException>("The port is in an invalid state.");
}
logger.Trace("Opened serial port {0} with baud rate {1}!", serialPort.PortName, serialPort.BaudRate);
}

private void CloseSerialPort()
{
logger.Info("Closing serial port...");
serialPort.DtrEnable = false;
serialPort.RtsEnable = false;
try
{
serialPort.Close();
}
catch (Exception)
{
// Ignore
}
}

private void ConfigureSerialPort()
{
logger.Trace("Setting Read/Write Timeout on serial port to '{0}'.", SerialPortTimeOut);
serialPort.ReadTimeout = SerialPortTimeOut;
serialPort.WriteTimeout = SerialPortTimeOut;
}

#endregion
}
}
29 changes: 26 additions & 3 deletions Source/ArduinoUploader/ArduinoUploader.csproj
Expand Up @@ -37,16 +37,22 @@
<Reference Include="NLog">
<HintPath>..\packages\NLog.4.3.9\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="RJCP.SerialPortStream">
<HintPath>..\packages\SerialPortStream.2.0.2\lib\net45\RJCP.SerialPortStream.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="BootloaderProgrammers\ButterflyBootloaderProgrammer.cs" />
<Compile Include="BootloaderProgrammers\SerialPortConfig.cs" />
<Compile Include="Hardware\ArduinoModel.cs" />
<Compile Include="ArduinoSketchUploader.cs" />
<Compile Include="ArduinoSketchUploaderOptions.cs" />
<Compile Include="BootloaderProgrammers\BootloaderProgrammer.cs" />
<Compile Include="Hardware\ATMega2560.cs" />
<Compile Include="Hardware\ATMega328P.cs" />
<Compile Include="Hardware\ATMega32U4.cs" />
<Compile Include="Hardware\MCU.cs" />
<Compile Include="Hardware\Command.cs" />
<Compile Include="Hardware\Memory\EEPROMMemory.cs" />
Expand All @@ -55,6 +61,26 @@
<Compile Include="Hardware\Memory\IMemory.cs" />
<Compile Include="Hardware\Memory\Memory.cs" />
<Compile Include="Hardware\Memory\MemoryType.cs" />
<Compile Include="Protocols\AVR109\Constants.cs" />
<Compile Include="Protocols\AVR109\Messages\CheckBlockSupportRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\CheckBlockSupportResponse.cs" />
<Compile Include="Protocols\AVR109\Messages\EnterProgrammingModeRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ExitBootLoaderRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\LeaveProgrammingModeRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ReadSignatureBytesRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ReadSignatureBytesResponse.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnProgrammerTypeRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnProgrammerTypeResponse.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnSoftwareIdentifierRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnSoftwareIdentifierResponse.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnSoftwareVersionRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnSoftwareVersionResponse.cs" />
<Compile Include="Protocols\AVR109\Messages\ReturnSupportedDeviceCodesRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\SelectDeviceTypeRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\SetAddressRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\StartBlockLoadRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\StartBlockReadRequest.cs" />
<Compile Include="Protocols\AVR109\Messages\StartBlockReadResponse.cs" />
<Compile Include="Protocols\STK500v1\Constants.cs" />
<Compile Include="Protocols\STK500v1\Messages\EnableProgrammingModeRequest.cs" />
<Compile Include="Protocols\STK500v1\Messages\ExecuteProgramPageRequest.cs" />
Expand Down Expand Up @@ -86,9 +112,6 @@
<Compile Include="Protocols\STK500v2\Messages\LeaveProgrammingModeResponse.cs" />
<Compile Include="Protocols\STK500v2\Messages\LoadAddressRequest.cs" />
<Compile Include="Protocols\STK500v2\Messages\LoadAddressResponse.cs" />
<Compile Include="UploaderSerialPort.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="BootloaderProgrammers\ArduinoBootloaderProgrammer.cs" />
<Compile Include="BootloaderProgrammers\IBootloaderProgrammer.cs" />
<Compile Include="BootloaderProgrammers\OptibootBootloaderProgrammer.cs" />
Expand Down
Expand Up @@ -8,19 +8,21 @@ internal abstract class ArduinoBootloaderProgrammer : SerialPortBootloaderProgra

protected abstract void Reset();

protected ArduinoBootloaderProgrammer(UploaderSerialPort serialPort, IMCU mcu)
: base(serialPort, mcu)
protected ArduinoBootloaderProgrammer(SerialPortConfig serialPortConfig, IMCU mcu)
: base(serialPortConfig, mcu)
{
}

public override void Open()
{
base.Open();
Reset();
}

public override void Close()
{
Reset();
base.Close();
}
}
}
@@ -1,5 +1,5 @@
using System.IO;
using System.Linq;
using System.Linq;
using System.Threading;
using ArduinoUploader.Hardware;
using ArduinoUploader.Hardware.Memory;
using IntelHexFormatReader.Model;
Expand All @@ -25,8 +25,9 @@ protected BootloaderProgrammer(IMCU mcu)
public abstract void InitializeDevice();
public abstract void EnableProgrammingMode();
public abstract void LeaveProgrammingMode();
public abstract void LoadAddress(IMemory memory, int offset);
public abstract void ExecuteWritePage(IMemory memory, int offset, byte[] bytes);
public abstract byte[] ExecuteReadPage(IMemory memory, int offset);
public abstract byte[] ExecuteReadPage(IMemory memory);

public virtual void ProgramDevice(MemoryBlock memoryBlock)
{
Expand All @@ -52,20 +53,24 @@ public virtual void ProgramDevice(MemoryBlock memoryBlock)
var bytesToCopy = memoryBlock.Cells.Skip(offset).Take(pageSize).Select(x => x.Value).ToArray();

logger.Trace("Checking if bytes at offset {0} need to be overwritten...", offset);
var bytesAlreadyPresent = ExecuteReadPage(flashMem, offset);
LoadAddress(flashMem, offset);
var bytesAlreadyPresent = ExecuteReadPage(flashMem);
if (bytesAlreadyPresent.SequenceEqual(bytesToCopy))
{
logger.Trace("Bytes to be written are identical to bytes already present - skipping actual write!");
continue;
}
logger.Trace("Writing page at offset {0}.", offset);
LoadAddress(flashMem, offset);
ExecuteWritePage(flashMem, offset, bytesToCopy);
logger.Trace("Page written, now verifying...");

var verify = ExecuteReadPage(flashMem, offset);
logger.Trace("Page written, now verifying...");
Thread.Sleep(10);
LoadAddress(flashMem, offset);
var verify = ExecuteReadPage(flashMem);
var succeeded = verify.SequenceEqual(bytesToCopy);
if (!succeeded)
UploaderLogger.LogAndThrowError<IOException>(
UploaderLogger.LogErrorAndQuit(
"Difference encountered during verification, write failed!");
}
else
Expand Down

0 comments on commit 46054f5

Please sign in to comment.