AT91Boot DLL and c#

Microchip in-system programming solution: SAM-BA

Moderators: nferre, fab

brian.shankland
Posts: 2
Joined: Tue Jul 14, 2009 10:18 am

AT91Boot DLL and c#

Fri Nov 28, 2014 1:19 pm

I'm attempting to write a firmware downloader using the AT91Boot DLL and c# but have run up against a brick wall in the AT91Boot_Open command.

I searched for solutions around the unmanaged interface and discovered the way to get the list of devices with the following:

byte[] ByteArray = new byte[1040];
fixed (byte* pByteArray = ByteArray)
{
    for (int Index = 0; Index < 10; Index++)
    {
        var memoryLocation = pByteArray + 40 + Index * 100;
        var asInt = new IntPtr(memoryLocation).ToInt32();
        var asBytes = BitConverter.GetBytes(asInt);
        Buffer.BlockCopy(asBytes, 0, ByteArray, Index * 4, 4);
     }

     theSamba.AT91Boot_Scan(ref ByteArray[0]);
}

Which works and returns the name "\\USBSerial\\COM3" in the first allcated buffer which is correct.

When i try to call the open I always get a filehandle of zero:

int thePortHandle
theSamba.AT91Boot_Open(ref ByteArray[0], out thePortHandle);

Is there a c# example for the basic operation of this dll or am I stuck with having to rewrite using unmanaged c++ or writing an option to wrap around tcl scripts and sam-ba.exe?
rungholt
Posts: 4
Joined: Thu Mar 19, 2015 6:30 pm

Re: AT91Boot DLL and c#

Thu Mar 19, 2015 6:37 pm

Same problem. Any ideas?
brian.shankland
Posts: 2
Joined: Tue Jul 14, 2009 10:18 am

Re: AT91Boot DLL and c#

Thu Mar 19, 2015 7:10 pm

Afraid not, I just put the project into hibernation until perhaps a new samba release will have a proper .net wrapper.

I instead have just tidied up my original design in which I use the .tcp file scripts but these are automatically generated by the app so all I need to do is tell it my target, bootloader image and kernel image and it sorts out all the details fro each of our 5 target projects.

 
IanMcCarthy
Posts: 3
Joined: Tue Mar 31, 2015 10:22 am

Re: AT91Boot DLL and c#

Tue Apr 07, 2015 9:53 am

I can offer this 'solution' as is...

NOTE: Code appended to end of this post...

There's a few notes at the top of the file relating to adding it to a VS project.

There's a bit of trial and error in the commented out code, but this has been working reliably for a while now. It's not 100% but it's close.

It uses a few functions that are elsewhere in my code, but these should be easy to reproduce (reading applet code from embedded resources for example).

This is working for release 2.12 of the Atmel SAM-BA utility...be warned...I loaded 2.14 as well and broke it completely...couldn't open a port.

Hopefully Karma will kick in and an answer to my problem will wing it's way to me in return...

Regards,

Ian

Code: Select all

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;




using SAMBA_DLLLib;




using SAM4S_Programmer_Utility.ResourceModel;




//
// In order to use the Atmel supplied sam-ba.dll with C# projects, the following steps need to be taken:
// 
// 1. Run Visual Studio tool tlbimp against sam-ba.dll to create SAMBA_DLLLib.dll interop library.
// 2. Register the original sam-ba.dll using: c:\windows\syswow64\regsrv32 sam-ba.dll (must use 32-bit version of regsvr32)
// 3. Add a reference to SAMBA_DLLLib.dll to the Visual Studio project.
// 4. In reference's properties set Enbed Interop Types to false (otherwise you're unable to create instances of class)
// 5. Create instance (static or not) of class to use it: private static SAMBADLLClass SAMBA = new SAMBADLLClass();
// 
// If at some later date you change the project path, then the registered path to sab-ba.dll will be broken and the application
// will throw an exception when it attempts to instantiate the class. If this occurs unregister sam-ba.dll and register again
// using the new location.
// 
namespace SAM4S_Programmer_Utility.AtmelModel
{
    class Atmel : IDisposable
    {
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
        static extern IntPtr LoadLibrary(string lpFileName);
        
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)] /* unnecessary, isn't it? */
        static extern bool FreeLibrary(IntPtr hModule);
        
        [DllImport("kernel32.dll", SetLastError = true)]
        internal extern static IntPtr GetProcAddress(IntPtr hModule, string procName);




        private const string SAM_BA_DLL_NAME = "sam-ba.dll";




        private const string PORT_PREFIX_CDC = "\\USBserial\\";
        private const string PORT_PREFIX_SERIAL = "COM";
        private const string PORT_PREFIX_JLINK = "\\jlink\\";




        private const string APPLET_LOW_LEVEL_INIT = "applet-lowlevelinit-sam4s16.bin";
        private const string APPLET_FLASH = "applet-flash-sam4s16.bin";
        private const string APPLET_NAND_FLASH = "applet-nandflash-sam4s16.bin";
		private const string APPLET_RESET_AND_GO = "applet-reset_and_go-sam4s16.bin";




        public const UInt32 APPLET_ADDR                  = 0x20000800;
        private const UInt32 APPLET_MAILBOX_ADDR         = 0x20000840;
        private const UInt32 APPLET_MAILBOX_COMMAND_ADDR = 0x20000840;
        private const UInt32 APPLET_MAILBOX_STATUS_ADDR  = 0x20000844;
        public const UInt32 FLASH_ADDRESS                = 0x00400000;
        public const UInt32 RSTC_CR_ADDR                 = 0x400E1400;
        public const UInt32 RESET_CODE                   = 0xA500000D;




        [Flags] public enum EPortType
        {
            EPT_NONE = 0,
            EPT_CDC = 1,
            EPT_SERIAL = 2,
            EPT_JLINK = 4,
            EPT_ALL = EPortType.EPT_CDC | EPortType.EPT_SERIAL | EPortType.EPT_JLINK,




            // Not much use in [Flag] type enum...but hey...
            EPT_MIN = EPT_NONE,
            EPT_MAX = EPT_ALL
        }
        
        public enum EResultType
        {
            ER_SUCCESS             = 0x00,
            ER_DEV_UNKNOWN         = 0x01,
            ER_WRITE_FAIL          = 0x02,
            ER_READ_FAIL           = 0x03,
            ER_PROTECT_FAIL        = 0x04,
            ER_UNPROTECT_FAIL      = 0x05,
            ER_ERASE_FAIL          = 0x06,
            ER_NO_DEV              = 0x07,
            ER_ALIGN_ERROR         = 0x08,
            ER_BAD_BLOCK           = 0x09,
            ER_FAIL                = 0x0f,




            ER_NO_DLL              = 0x50, // Not part of Atmel code
            ER_COMPLETED           = 0x51, // Not part of Atmel code
            ER_STILL_RUNNING       = 0x52, // Not part of Atmel code
            ER_TIMEOUT             = 0x53, // Not part of Atmel code




            ER_BAD_HANDLE          = 0xF001,
            ER_ADDRESS_NOT_ALIGNED = 0xF002,
            ER_LINK_BROKEN         = 0xF005,




            ER_MIN = ER_SUCCESS,
            ER_MAX = ER_FAIL
        }
        public enum EAppletType
        {
            EA_LOW_LEVEL_INIT = 0,
            EA_FLASH,
            EA_NAND_FLASH,
			EA_RESET_AND_GO,




            EA_MIN = EA_LOW_LEVEL_INIT,
			EA_MAX = EA_RESET_AND_GO
        }




        #region SAM-BA Applet




        public enum EAppletCommandType
        {
            EAC_INIT            = 0x00,
            EAC_FULL_ERASE      = 0x01,
            EAC_WRITE           = 0x02,
            EAC_READ            = 0x03,
            EAC_LOCK            = 0x04,
            EAC_UNLOCK          = 0x05,
            EAC_GPNVM           = 0x06,
            EAC_SECURITY        = 0x07,
            EAC_BUFFER_ERASE    = 0x08,
            EAC_BINARY_PAGE     = 0x09,
            EAC_LIST_BAD_BLOCKS = 0x10,
            EAC_TAG_BLOCK       = 0x11,
            EAC_READ_UNIQUE_ID  = 0x12,
            EAC_ERASE_BLOCKS    = 0x13,
            EAC_BATCH_ERASE     = 0x14,




			EAC_RESET_AND_GO    = 0xFE,




            EAC_MIN = EAC_INIT,
			EAC_MAX = EAC_RESET_AND_GO
        }




        public enum EAppletLinkType
        {
            EAL_USB  = 0x00,
            EAL_DBGU = 0x01,
            EAL_JTAG = 0x02,




            EAL_MIN = EAL_USB,
            EAL_MAX = EAL_JTAG
        }




        public enum EInitModeType
        {
            EIM_EK                   = 0,
            EIM_USER_DEFINED_CRYSTAL = 1,
            EIM_BYPASS               = 2,




            EIM_MIN = EIM_EK,
            EIM_MAX = EIM_BYPASS
        }




        public enum ETraceLevelType
        {
            ETL_NO_TRACE = 0,
            ETL_FATAL    = 1,
            ETL_ERROR    = 2,
            ETL_WARNING  = 3,
            ETL_INFO     = 4,
            ETL_DEBUG    = 5,




            ETL_MIN = ETL_NO_TRACE,
            ETL_MAX = ETL_DEBUG
        }




        public enum EGpnvmModeType
        {
            EGM_CLEAR = 0,
            EGM_SET   = 1,




            EGM_MIN = EGM_CLEAR,
            EGM_MAX = EGM_SET
        }




        public enum EGpnvmBitIndexType
        {
            EGBI_0_SECURITY = 0,
            EGBI_1_BOOT_MODE = 1,
            EGBI_2_FLASH_SEL = 2,




            EGBI_MIN = EGBI_0_SECURITY,
            EGBI_MAX = EGBI_2_FLASH_SEL
        }




        #endregion




		#region Constructor




		public Atmel()
		{
			// dllDllHandle = LoadLibrary(@"D:\Projects_Production\207048 - dBadge2 - Programming Utility\Code\bin\x86\Debug\SAMBA_DLLLib.dll");
			// FreeLibrary(dllDllHandle);




			// dllHandle = LoadLibrary(SAM_BA_DLL_NAME);
			// dllHandle = LoadLibrary(@"D:\Projects_Production\207048 - dBadge2 - Programming Utility\Code\Atmel\sam-ba.dll");
			// FreeLibrary(dllHandle);




			samba = new SAMBADLLClass();
		}




		#endregion




        #region IDisposable Interface




        IntPtr dllHandle = IntPtr.Zero;
		IntPtr dllDllHandle = IntPtr.Zero;




        bool disposed = false;




        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }




        protected virtual void Dispose(bool disposing)
        {
            if(disposed)
            {
                return;
            }




            if(disposing)
            {
                // Free unmanaged objects here
                if(samba != null)
                {
                    samba = null;
                }




                // No...no...no...no...
                // Unloading the library will make it inaccessable the next time this class is instantiated...




				// IntPtr handleDll = LoadLibrary(@"D:\Projects_Production\207048 - dBadge2 - Programming Utility\Code\bin\x86\Debug\SAMBA_DLLLib.dll");




				// IntPtr handle = LoadLibrary(SAM_BA_DLL_NAME);
				// IntPtr handle = LoadLibrary(@"D:\Projects_Production\207048 - dBadge2 - Programming Utility\Code\Atmel\sam-ba.dll");




				/*
				while (FreeLibrary(dllHandle))
				{
					// Empty loop
				}
				*/




				/*
				while (FreeLibrary(dllDllHandle))
				{
					// Empty loop
				}
				*/




				/*
                if(dllHandle != IntPtr.Zero)
                {
                    // The call to LoadLibrary incremented the handle count by one (above the one
                    // already incremented by the PInvoke load). Calling FreeLibrary TWICE should
                    // therefore reduce the handle count to zero and free the library from memory
                    FreeLibrary(dllHandle);
                    FreeLibrary(dllHandle);
                }
				*/




                disposed = true;
            }
        }




        #endregion




        public static string AppletInternalFolder
        {
            get
            {
                return "Atmel.Applets.";
            }
        }




        private SAMBADLLClass samba = null;




        private DateTime lastGoTime = DateTime.MinValue;
        private Int32 lastGoCommand;




        public List<string> Boot_Scan(EPortType portType)
        {
            unsafe
            {
                byte[] byteArray = new byte[1040];




                fixed (byte* pByteArray = byteArray)
                {
                    for (var i = 0; i < 10; i++)
                    {
                        var memoryLocation = pByteArray + 40 + i * 100;
                        var asInt = new IntPtr(memoryLocation).ToInt32();
                        var asBytes = BitConverter.GetBytes(asInt);
                        Buffer.BlockCopy(asBytes, 0, byteArray, i * 4, 4);
                    }




                    try
                    {
                        samba.AT91Boot_Scan(ref byteArray[0]);
                    }
                    catch(Exception /* e */)
                    {
                        // Problem, so return nothing
                        return null;
                    }




                    // Convert raw data to a collection of available port names
                    List<string> ports = new List<string>();




                    for(int index = 0; index < 10; index++)
                    {
                        byte[] item = new byte[100];
                        Buffer.BlockCopy(byteArray, 40 + (index * 100), item, 0, 100);
                        string port = System.Text.Encoding.UTF8.GetString(item).TrimEnd((char)0x00);




                        // See if the current string describes a port...
                        if (port.Length > 0)
                        {
                            // Yes it does, so update list depending upon the type of port we're looking for
                            if (port.StartsWith(PORT_PREFIX_SERIAL))
                            {
                                // Are we looking for serial type ports..?
                                if ((portType & EPortType.EPT_SERIAL) == EPortType.EPT_SERIAL)
                                {
                                    ports.Add(port);
                                    continue;
                                }
                            }




                            if (port.StartsWith(PORT_PREFIX_CDC))
                            {
                                // Are we looking for serial type ports..?
                                if ((portType & EPortType.EPT_CDC) == EPortType.EPT_CDC)
                                {
                                    ports.Add(port);
                                    continue;
                                }
                            }




                            if (port.StartsWith(PORT_PREFIX_JLINK))
                            {
                                // Are we looking for serial type ports..?
                                if ((portType & EPortType.EPT_JLINK) == EPortType.EPT_JLINK)
                                {
                                    ports.Add(port);
                                    continue;
                                }
                            }
                        }
                    }




                    // Return a list of available ports
                    return ports;
                }
            }
        }




        public void Boot_Open(string portName, out Int32 handle)
        {
			try
			{
				byte[] bytes = Encoding.ASCII.GetBytes(portName + (char)0x00);




				samba.AT91Boot_Open(ref bytes[0], out handle);
			}
			catch(Exception /* e */)
			{
				handle = 0;
			}
        }




        public void Boot_Close(Int32 handle)
        {
			try
			{
				samba.AT91Boot_Close(handle);
			}
			catch(Exception /* e */)
			{
				// Nothing to do...
			}
        }




        public EResultType Boot_Read_Int(Int32 handle, Int32 address, ref int buffer)
        {
            Int32 error;




            samba.AT91Boot_Read_Int(handle, out buffer, (int)address, out error);




            return (EResultType)error;
        }




        public EResultType Boot_Write_Data(Int32 handle, Int32 address, ref byte buffer, Int32 size)
        {
            Int32 error;




            samba.AT91Boot_Write_Data(handle, (int)address, ref buffer, (int)size, out error);




            return (EResultType)error;
        }




        public EResultType Boot_Read_Data(Int32 handle, Int32 address, ref byte buffer, Int32 size)
        {
            Int32 error;




            samba.AT91Boot_Read_Data(handle, (int)address, out buffer, size, out error);




            return (EResultType)error;
        }




        public EResultType Boot_Go(Int32 handle, Int32 address)
        {
            Int32 error;




            samba.AT91Boot_Go(handle, (int)address, out error);




            return (EResultType)error;
        }




















        public byte[] LoadApplet(EAppletType applet)
        {
            string appletName;




            switch(applet)
            {
                case(EAppletType.EA_LOW_LEVEL_INIT):
                    appletName = APPLET_LOW_LEVEL_INIT;
                    break;




                case (EAppletType.EA_FLASH):
                    appletName = APPLET_FLASH;
                    break;




                case (EAppletType.EA_NAND_FLASH):
                    appletName = APPLET_NAND_FLASH;
                    break;




				case (EAppletType.EA_RESET_AND_GO):
					appletName = APPLET_RESET_AND_GO;
					break;




				default:
                    // Problem...
                    return null;
            }




            byte[] bytes = Resources.GetResourceAsBytes(AppletInternalFolder + appletName);




            return bytes;
        }




        public EResultType WriteApplet(Int32 handle, byte[] applet)
        {
            Int32 address = (Int32)APPLET_ADDR;




            return Boot_Write_Data(handle, address, ref applet[0], applet.Length);
        }




        /*
        public EResultType WriteMailBox(int handle, MailBox mailBox)
        {
            Int32 address = (Int32)APPLET_MAILBOX_ADDR;
            byte[] bytes = mailBox.ToBytes();




            return  Boot_Write_Data(handle, address, ref bytes[0], bytes.Length);
        }
        */




        /*
        public EResultType ReadMailBox(int handle, ref MailBox mailBox)
        {
            Int32 address = (Int32)APPLET_MAILBOX_ADDR;
            FlashMailBox mb = new FlashMailBox();
            byte[] bytes = mb.ToBytes();




            Boot_Read_Data(handle, address, ref bytes[0], bytes.Length);




            mailBox = new FlashMailBox(bytes);




            return EResultType.ER_SUCCESS;
        }
        */




        public EResultType Go(Int32 handle)
        {
            Int32 error;




            // Determine the command id to be executed
            samba.AT91Boot_Read_Int(handle, out lastGoCommand, (int)APPLET_MAILBOX_COMMAND_ADDR, out error);
            // ...and when...
            lastGoTime = DateTime.Now;




            samba.AT91Boot_Go(handle, (Int32)APPLET_ADDR, out error);




            return (EResultType)error;
        }




        public EResultType Test_For_Go_Completed(Int32 handle, Int32 timeoutMS)
        {
            Int32 error = 0;
            Int32 command;
            Int32 status;




            samba.AT91Boot_Read_Int(handle, out command, (int)APPLET_MAILBOX_COMMAND_ADDR, out error);




            if((EResultType)error != EResultType.ER_SUCCESS)
            {
                return (EResultType)error;
            }




            if (~command == lastGoCommand)
            {
                samba.AT91Boot_Read_Int(handle, out status, (int)APPLET_MAILBOX_STATUS_ADDR, out error);
                
                return EResultType.ER_COMPLETED;
            }




            if (DateTime.Now > lastGoTime.AddMilliseconds(timeoutMS))
            {
                return EResultType.ER_TIMEOUT;
            }




            return EResultType.ER_STILL_RUNNING;
        }




        public EResultType ForceReset(Int32 handle)
        {
            Int32 error;




            samba.AT91Boot_Write_Int(handle, unchecked((int)RESET_CODE), (int)RSTC_CR_ADDR, out error);




            return EResultType.ER_SUCCESS;
        }




        // Requires the object to be an actual Serializable object (including id/size cr*p)
        /*
        public static byte[] ObjectToByteArray(Object obj)
        {
            if (obj == null)
            {
                return null;
            }




            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);




            return ms.ToArray();
        }
        */




        // Requires the object to be an actual Serializable object (including id/size cr*p)
        /*
        public static Object ByteArrayToObject(byte[] bytes)
        {
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter binForm = new BinaryFormatter();
            memStream.Write(bytes, 0, bytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            Object obj = (Object)binForm.Deserialize(memStream);




            return obj;
        }
        */




        #region MailBox Classes




        public class MailBox
        {
            [StructLayout(LayoutKind.Explicit)]
            public struct Header
            {
                [FieldOffset(0)]
                public UInt32 command;
                [FieldOffset(4)]
                public UInt32 status;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct Parameters
            {
                [FieldOffset(0)]
                public Header header;
            }




            protected Atmel atmel = null;




            public Parameters parameters = new Parameters();




            /*
            public MailBox()
            {
            }
            */
            
            public MailBox(Atmel atmelIn)
            {
                atmel = atmelIn;
            }




            /*
            public MailBox(byte[] bytes)
            {
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(bytes, 0, pParameters.AddrOfPinnedObject(), bytes.Length);
                }
                finally
                {
                    pParameters.Free();
                }
            }
            */




            public byte[] ToBytes()
            {
                byte[] bytes = new byte[Marshal.SizeOf(typeof(Parameters))];
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(pParameters.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                    return bytes;
                }
                finally
                {
                    pParameters.Free();
                }
            }
        
            public EResultType Write(int handle)
            {
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if(atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    return atmel.Boot_Write_Data(handle, address, ref bytes[0], bytes.Length);
                }
            }




            public EResultType Read(int handle)
            {
                int size = Marshal.SizeOf(parameters);
                IntPtr ptr = Marshal.AllocHGlobal(size);
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    atmel.Boot_Read_Data(handle, address, ref bytes[0], bytes.Length);




                    try
                    {
                        Marshal.Copy(bytes, 0, ptr, size);




                        parameters = (Parameters)Marshal.PtrToStructure(ptr, parameters.GetType());
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(ptr);
                    }




                    return EResultType.ER_SUCCESS;
                }
            }
        }




        public class LowLevelInitMailBox : MailBox
        {
            [StructLayout(LayoutKind.Explicit)]
            public struct Body
            {
                [FieldOffset(0)]
                public UInt32 comType;
                [FieldOffset(4)]
                public UInt32 traceLevel;
                [FieldOffset(8)]
                public UInt32 mode;
                [FieldOffset(12)]
                public UInt32 crystalFreq;
                [FieldOffset(16)]
                public UInt32 extClk;
            }
            
            [StructLayout(LayoutKind.Explicit)]
            new public struct Parameters
            {
                [FieldOffset(0)]
                public Header header;
                [FieldOffset(8)]
                public Body body;
            }




            new public Parameters parameters = new Parameters();




            /*
            public LowLevelInitMailBox()
            {
            }
            */




            public LowLevelInitMailBox(Atmel atmelIn)
                : base(atmelIn)
            {




            }




            /*
            public LowLevelInitMailBox(byte[] bytes)
            {
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(bytes, 0, pParameters.AddrOfPinnedObject(), bytes.Length);
                }
                finally
                {
                    pParameters.Free();
                }
            }
            */




            new public byte[] ToBytes()
            {
                byte[] bytes = new byte[Marshal.SizeOf(typeof(Parameters))];
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(pParameters.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                    return bytes;
                }
                finally
                {
                    pParameters.Free();
                }
            }




            new public EResultType Write(int handle)
            {
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    return atmel.Boot_Write_Data(handle, address, ref bytes[0], bytes.Length);
                }
            }




            new public EResultType Read(int handle)
            {
                int size = Marshal.SizeOf(parameters);
                IntPtr ptr = Marshal.AllocHGlobal(size);
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    atmel.Boot_Read_Data(handle, address, ref bytes[0], bytes.Length);




                    try
                    {
                        Marshal.Copy(bytes, 0, ptr, size);




                        parameters = (Parameters)Marshal.PtrToStructure(ptr, parameters.GetType());
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(ptr);
                    }




                    return EResultType.ER_SUCCESS;
                }
            }
        }




        public class FlashMailBox : MailBox
        {
            [StructLayout(LayoutKind.Explicit)]
            public struct InitCommandIn
            {
                [FieldOffset(0)]
                public UInt32 comType;
                [FieldOffset(4)]
                public UInt32 traceLevel;
                [FieldOffset(8)]
                public UInt32 bank;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct InitCommandOut
            {
                [FieldOffset(0)]
                public UInt32 memorySize;
                [FieldOffset(4)]
                public UInt32 bufferAddress;
                [FieldOffset(8)]
                public UInt32 bufferSize;
                [FieldOffset(12)]
                public UInt16 lockRegionSize;
                [FieldOffset(14)]
                public UInt16 numbersLockBits;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct WriteCommandIn
            {
                [FieldOffset(0)]
                public UInt32 bufferAddr;
                [FieldOffset(4)]
                public UInt32 bufferSize;
                [FieldOffset(8)]
                public UInt32 memoryOffset;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct WriteCommandOut
            {
                [FieldOffset(0)]
                public UInt32 bytesWritten;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct ReadCommandIn
            {
                [FieldOffset(0)]
                public UInt32 bufferAddr;
                [FieldOffset(4)]
                public UInt32 bufferSize;
                [FieldOffset(8)]
                public UInt32 memoryOffset;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct ReadCommandOut
            {
                [FieldOffset(0)]
                public UInt32 bytesRead;
            }




            // Full Erase command (Nothing required)




            [StructLayout(LayoutKind.Explicit)]
            public struct LockCommandIn
            {
                [FieldOffset(0)]
                public UInt32 sector;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct UnlockCommandIn
            {
                [FieldOffset(0)]
                public UInt32 sector;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct GpnvmCommandIn
            {
                [FieldOffset(0)]
                public UInt32 action;
                [FieldOffset(4)]
                public UInt32 bitsOfNVM;
            }




            [StructLayout(LayoutKind.Explicit)]
            public struct ReadUniqueCommandIn
            {
                [FieldOffset(0)]
                public UInt32 bufferAddr;
            }
            
            [StructLayout(LayoutKind.Explicit)]
            new public struct Parameters
            {
                [FieldOffset(0)]
                public Header header;




                [FieldOffset(8)]
                public InitCommandIn initCommandIn;
                [FieldOffset(8)]
                public InitCommandOut initCommandOut;
                
                [FieldOffset(8)]
                public WriteCommandIn writeCommandIn;
                [FieldOffset(8)]
                public WriteCommandOut writeCommandOut;




                [FieldOffset(8)]
                public ReadCommandIn readCommandIn;
                [FieldOffset(8)]
                public ReadCommandOut readCommandOut;




                // Nothin required for Full Erase




                [FieldOffset(8)]
                public LockCommandIn lockCommandIn;




                [FieldOffset(8)]
                public UnlockCommandIn unlockCommandIn;




                [FieldOffset(8)]
                public GpnvmCommandIn gpnvmCommandIn;




                [FieldOffset(8)]
                public ReadUniqueCommandIn readUniqueCommandIn;
            }




            new public Parameters parameters = new Parameters();




            /*
            public FlashMailBox()
            {
            }
            */




            public FlashMailBox(Atmel atmelIn)
                : base(atmelIn)
            {




            }




            /*
            public FlashMailBox(byte[] bytes)
            {
                int size = Marshal.SizeOf(parameters);
                IntPtr ptr = Marshal.AllocHGlobal(size);




                try
                {
                    Marshal.Copy(bytes, 0, ptr, size);




                    parameters = (Parameters)Marshal.PtrToStructure(ptr, parameters.GetType());
                }
                finally
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
            */




            new public byte[] ToBytes()
            {
                byte[] bytes = new byte[Marshal.SizeOf(typeof(Parameters))];
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(pParameters.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                    return bytes;
                }
                finally
                {
                    pParameters.Free();
                }
            }




            new public EResultType Write(int handle)
            {
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    return atmel.Boot_Write_Data(handle, address, ref bytes[0], bytes.Length);
                }
            }




            new public EResultType Read(int handle)
            {
                int size = Marshal.SizeOf(parameters);
                IntPtr ptr = Marshal.AllocHGlobal(size);
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    atmel.Boot_Read_Data(handle, address, ref bytes[0], bytes.Length);




                    try
                    {
                        Marshal.Copy(bytes, 0, ptr, size);




                        parameters = (Parameters)Marshal.PtrToStructure(ptr, parameters.GetType());
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(ptr);
                    }




                    return EResultType.ER_SUCCESS;
                }
            }
        }




        public class NandFlashMailBox : MailBox
        {
            [StructLayout(LayoutKind.Explicit)]
            new public struct Parameters
            {
                [StructLayout(LayoutKind.Explicit)]
                public struct Header
                {
                    [FieldOffset(0)]
                    public UInt32 command;
                    [FieldOffset(4)]
                    public UInt32 status;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct InitCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 comType;
                    [FieldOffset(12)]
                    public UInt32 traceLevel;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct InitCommandOut
                {
                    [FieldOffset(8)]
                    public UInt32 memorySize;
                    [FieldOffset(12)]
                    public UInt32 bufferAddress;
                    [FieldOffset(16)]
                    public UInt32 bufferSize;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct WriteCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 bufferAddr;
                    [FieldOffset(12)]
                    public UInt32 bufferSize;
                    [FieldOffset(16)]
                    public UInt32 memoryOffset;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct WriteCommandOut
                {
                    [FieldOffset(8)]
                    public UInt32 bytesWritten;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct ReadCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 bufferAddr;
                    [FieldOffset(12)]
                    public UInt32 bufferSize;
                    [FieldOffset(16)]
                    public UInt32 memoryOffset;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct ReadCommandOut
                {
                    [FieldOffset(8)]
                    public UInt32 bytesRead;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct FullEraseCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 eraseType;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct BatchEraseCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 eraseType;
                    [FieldOffset(12)]
                    public UInt32 batch;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct BatchEraseCommandOut
                {
                    [FieldOffset(8)]
                    public UInt32 nextBatch;
                }












                [StructLayout(LayoutKind.Explicit)]
                public struct BlockEraseCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 memoryOffsetStart;
                    [FieldOffset(12)]
                    public UInt32 memoryOffsetEnd;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct ListBadBlocksCommandOut
                {
                    [FieldOffset(8)]
                    public UInt32 nbBadBlocks;
                    [FieldOffset(12)]
                    public UInt32 bufferAddress;
                }




                [StructLayout(LayoutKind.Explicit)]
                public struct TagBlockCommandIn
                {
                    [FieldOffset(8)]
                    public UInt32 blockId;
                    [FieldOffset(12)]
                    public UInt32 tag;
                }
            }




            new public Parameters parameters = new Parameters();




            /*
            public NandFlashMailBox()
            {
            }
            */




            public NandFlashMailBox(Atmel atmelIn)
                : base(atmelIn)
            {




            }




            /*
            public NandFlashMailBox(byte[] bytes)
            {
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(bytes, 0, pParameters.AddrOfPinnedObject(), bytes.Length);
                }
                finally
                {
                    pParameters.Free();
                }
            }
            */




            new public byte[] ToBytes()
            {
                byte[] bytes = new byte[Marshal.SizeOf(typeof(Parameters))];
                GCHandle pParameters = GCHandle.Alloc(parameters, GCHandleType.Pinned);




                try
                {
                    Marshal.Copy(pParameters.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                    return bytes;
                }
                finally
                {
                    pParameters.Free();
                }
            }




            new public EResultType Write(int handle)
            {
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    return atmel.Boot_Write_Data(handle, address, ref bytes[0], bytes.Length);
                }
            }




            new public EResultType Read(int handle)
            {
                int size = Marshal.SizeOf(parameters);
                IntPtr ptr = Marshal.AllocHGlobal(size);
                Int32 address = (Int32)APPLET_MAILBOX_ADDR;
                byte[] bytes = ToBytes();




                if (atmel == null)
                {
                    return EResultType.ER_NO_DLL;
                }
                else
                {
                    atmel.Boot_Read_Data(handle, address, ref bytes[0], bytes.Length);




                    try
                    {
                        Marshal.Copy(bytes, 0, ptr, size);




                        parameters = (Parameters)Marshal.PtrToStructure(ptr, parameters.GetType());
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(ptr);
                    }




                    return EResultType.ER_SUCCESS;
                }
            }
        }




        #endregion




    }
}

Return to “SAM-BA”

Who is online

Users browsing this forum: No registered users and 1 guest