SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By winhaven
#226476
I do development for Artemis Nano boards in a win-10 64-bit environment. Some of the sites that will be using our product will be under win-7 32-bit.

Our application on the PC is able to update the firmware on the Nano when it detects it is out of date by using SVL.exe.

The 64-bit version of SVL that was installed with the Arduino IDE on my PC will not run on win-7 32-bit.

How can I get a copy of SVL.exe that is 32-bit and will run under win-7. Does someone have it and can make it available to me? Or is there a URL I can goto to get it?
User avatar
By TS-Russell
#226479
Unfortunately a 32-bit version of the SVL bootloader does not currently exist - and as Win7 has been unsupported since Jan 2020, I would not expect much incentive for someone to port it over anytime soon :-(

We will leave this topic open in case someone has an outside solution :-)
User avatar
By winhaven
#226508
OK, well I need to support ancient stuff a little bit longer...
I started out as an Imagineer in the early 80's working for Disney writing assembly and C for Intel 8080s to control their robots at Disneyland and EPCOT.
Currently I write all the firmware for the Coinstar kiosk, primarily the coin counter where there are still CPUs running Intel 80188, Power PC and the latest is ARM based.

Is SVL open source? Can I get the source code? I still have the compilers to create 32-bit x86 code if its written in C or C#. I'll take a wack at it.
User avatar
By winhaven
#226511
I found the git repository for the Apollo3 board support. SVL is written in Python...sigh...

It looks like VS2019 only supports 64-bit Python. I don't have an older compiler for that.

Thanks for the help.
User avatar
By winhaven
#227090
Using the source for SVL in git, I translated the Python to C#. With that I can still compile for 32-bit windows.
It's part of our application rather than being a stand alone executable (and it goes from a 6 megabyte EXE to an incremental 4K in our application size).

If anyone wants to use it, here is the contents of the class that implements it:

#region Using

using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Diagnostics;

#endregion

namespace Artemis
{
#region Enumerations

/// <summary>
/// Packet command types
/// </summary>
public enum SVL_Command
{
Error,
Version,
EnterBootloader,
NextFrame,
FirmwareFrame,
ResendFrame,
Done
}

#endregion

/// <summary>
/// Artemis firmware download
/// </summary>
public class FirmwareDownload : IDisposable
{
#region Variables

/// <summary>
/// Which COM port to use
/// </summary>
public static string ComPort = null;

/// <summary>
/// The serial port
/// </summary>
private SerialPort _port = null;

/// <summary>
/// Name of file to download
/// </summary>
private string firmwareFile = string.Empty;

public const int OneSecond = 1000;

/// <summary>
/// Maximum amount of data to send per frame
/// </summary>
public const int frameSize = 2048;

#endregion

#region Startup/Shutdown

/// <summary>
/// Protocol constructor
/// </summary>
private FirmwareDownload(string binary, string comPort)
{
ComPort = comPort;
firmwareFile = binary;
}

/// <summary>
/// Destructor for Protocol
/// </summary>
~FirmwareDownload()
{
Dispose();
}

/// <summary>
/// Perform download
/// </summary>
public static bool Start(string binary, string comPort)
{
bool rc = false;
FirmwareDownload instance = new FirmwareDownload(binary, comPort);

if (!File.Exists(binary))
Log("Firmware file does not exist");
else
rc = instance.Execute();

instance.Dispose();
return rc;
}

/// <summary>
/// Dispose the object
/// </summary>
public void Dispose()
{
if (_port != null)
{
_port.RtsEnable = false;
_port.Close();
}
}

#endregion

#region Send/Receive

/// <summary>
/// Send a message to the Stealth IO boot loader
/// </summary>
public void SendPacket(SVL_Command cmd, byte[] data = null, int offset = 0, int length = 0)
{
ushort crc;
int off = 0, dLen = length + 3;
byte[] packet = new byte[length + 5];

packet[off++] = (byte)(dLen >> 8);
packet[off++] = (byte)dLen;
packet[off++] = (byte)cmd;

Log(string.Format("Sending {0} Length {1}", cmd, length));

if (data != null)
for (int i = 0; i < length; i++)
packet[off++] = data[offset++];

crc = CalcCRC(packet, 2, length + 1);
packet[off++] = (byte)(crc >> 8);
packet[off++] = (byte)crc;

_port.Write(packet, 0, packet.Length);
}

/// <summary>
/// Receive a packet from Stealth IO boot loader
/// </summary>
/// <param name="bytesExpected">Number of bytes in packet being received</param>
/// <returns>Type of packet</returns>
public SVL_Command ReceivePacket(int bytesExpected)
{
try
{
DateTime start = DateTime.Now;
byte[] packet = new byte[bytesExpected];

while (_port.BytesToRead < bytesExpected)
if ((DateTime.Now - start).TotalSeconds > .5)
return SVL_Command.Error;
else
Thread.Sleep(5);

_port.Read(packet, 0, bytesExpected);

int length = (packet[0] << 8) + packet[1];
if (length < 2)
return SVL_Command.Error;

if (CalcCRC(packet, 2, length) != 0)
Log("CRC Error");
else
return (SVL_Command)packet[2];
}
catch (Exception e)
{
Log("ReceivePacket exception " + e.Message);
}
return SVL_Command.Error;
}

#endregion

#region Execute

private bool Execute()
{
byte[] baudDetect = { (byte)'U' };
byte[] firmware = File.ReadAllBytes(firmwareFile);

for (int attempt = 0; attempt < 3; attempt++)
{
if (!InitializePort())
{
Log("Can't open COM port");
continue;
}

Thread.Sleep(150);
_port.Write(baudDetect, 0, 1);
Log("Port open, sending baud char");

if (ReceivePacket(6) != SVL_Command.Version)
{
Log("No/Invalid response from loader");
continue;
}

SendPacket(SVL_Command.EnterBootloader);

int offset = 0, resendCount = 0;
bool succeeding = true, first = true;
while (succeeding)
{
switch (ReceivePacket(5))
{
case SVL_Command.Error:
succeeding = false;
break;

case SVL_Command.NextFrame:
resendCount = 0;
if (first)
first = false; // On first receipt, don't move forward
else
offset += frameSize;
break;

case SVL_Command.ResendFrame:
if (++resendCount > 3)
{
succeeding = false;
Log("Too many frame retries");
}
else
Log("Frame REJECTED, retry");
break;
}
// If no error, send next frame (or done)
if (succeeding)
if (offset < firmware.Length)
SendPacket(SVL_Command.FirmwareFrame, firmware, offset, (firmware.Length - offset > frameSize) ? frameSize : firmware.Length - offset);
else
{
SendPacket(SVL_Command.Done);
return true;
}
}
}
return false;
}

#endregion

#region Tools

/// <summary>
/// Initialize COM port
/// </summary>
public bool InitializePort()
{
if (_port != null)
{
_port.RtsEnable = false;
_port.Close();
Thread.Sleep(OneSecond);
}

_port = (ComPort != null) ? new SerialPort(ComPort, 921600, Parity.None, 8, StopBits.One) : null;

if (_port != null)
{
try
{
_port.RtsEnable = true;
_port.DtrEnable = false;
_port.Handshake = Handshake.None;
_port.Open();
_port.DiscardInBuffer();

return true;
}
catch
{
}
_port.Close();
_port = null;
}
return false;
}

/// <summary>
/// Log some text
/// </summary>
/// <param name="text">Text to log</param>
private static void Log(string text)
{
if (StealthIO.Instance != null)
StealthIO.Instance.SendEvent(StealthEventType.Log, string.Format("Firmware Download: {0}", text));
}

private static ushort[] crctab =
{
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
};

private ushort CalcCRC(byte[] data, int offset = 0, int length = -1)
{
ushort crc = 0, t;

if (length < 0)
length = data.Length;

for (int i = 0; i < length; i++)
{
t = crctab[data[offset + i] ^ (crc >> 8)];
crc = (ushort)((((t >> 8) ^ (byte)crc) << 8) | (byte)t);
}

return crc;
}

#endregion
}
}
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum