Need 32-bit (x86) version of SVL.exe

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?

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 :frowning:

We will leave this topic open in case someone has an outside solution :slight_smile:

Nobody runs win-10 32-bit? Or is it just not supported for SVL?

Nobody runs 32-bit anymore - https://gadgets.ndtv.com/laptops/news/m … ed-2228632 Google, Apple, Microsoft are all un-supporting 32-bit software

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.

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.

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

///

/// Packet command types

///

public enum SVL_Command

{

Error,

Version,

EnterBootloader,

NextFrame,

FirmwareFrame,

ResendFrame,

Done

}

#endregion

///

/// Artemis firmware download

///

public class FirmwareDownload : IDisposable

{

#region Variables

///

/// Which COM port to use

///

public static string ComPort = null;

///

/// The serial port

///

private SerialPort _port = null;

///

/// Name of file to download

///

private string firmwareFile = string.Empty;

public const int OneSecond = 1000;

///

/// Maximum amount of data to send per frame

///

public const int frameSize = 2048;

#endregion

#region Startup/Shutdown

///

/// Protocol constructor

///

private FirmwareDownload(string binary, string comPort)

{

ComPort = comPort;

firmwareFile = binary;

}

///

/// Destructor for Protocol

///

~FirmwareDownload()

{

Dispose();

}

///

/// Perform download

///

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;

}

///

/// Dispose the object

///

public void Dispose()

{

if (_port != null)

{

_port.RtsEnable = false;

_port.Close();

}

}

#endregion

#region Send/Receive

///

/// Send a message to the Stealth IO boot loader

///

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);

}

///

/// Receive a packet from Stealth IO boot loader

///

/// Number of bytes in packet being received

/// Type of packet

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

///

/// Initialize COM port

///

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;

}

///

/// Log some text

///

/// Text to log

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

}

}