Panda: Is there a device serial no or such I can access from code?

Hello!

I am rolling out some dozens of boards that need to be able to identify themselves uniquely to my server.

On the netduino, I use the ethernet mac address (which is perfect, as it is unique, and “just there” in a way that is easy to read from netmf).

On the panda, what can I use?

  • The ethernet board for panda appears not to have a burned in mac?
    — (in all the examples it seems the mac is assigned in code, e.g. http://wiki.tinyclr.com/index.php?title=Networking )
  • Can I read a system serial # or other unique value from netmf?

Thank you for any suggestions.

Wiz5100 chips do NOT come with a MAC address assigned. I understand that Wiznet have explicitly decided that their business model will not include registering a MAC for you. You can just go find yourself a MAC address generator (http://www.macvendorlookup.com/ has been suggested here before).

OK, no mac in hardware.

So if I roll out 50 boards, I have to manage the mac, board by board?

SD card reqd for config?

Or ?

You could always store the config info in SD card, or even in an eeprom (24LC256 for instance is waaaay overkill for capacity). IIRC (and don’t quote me on this :)) there isn’t an EWR equivalent on USBizi so you have to store something “config” related external to the chipset.

You also have 4k flash memory on the Panda II where you can store something like that. Then you don’t need to to get the 50 SD cards too if you’re gonna roll out 50 boards.

Thanks!
How do I read and write to flash? (is there a sample?)

Can I write to flash from mfdeploy.exe ?

don’t quote me on this either (after just having been wrong :)) http://code.tinyclr.com/project/413/saving-application-settings-to-flash/ might help you out…

@ Brett: not wrong at all but I found another class which I am using which allows you to read and write setting by their individual names.

@ samjones3: I’m not sure if you could write to flash from MFDeploy but it’s worth the try I guess.

The class I’m using save and reads the “collection” of settings as an XML string. It used to use System.XML.Legacy BUT when deploying the solution to the Panda II that class alone uses up just more than 55k! So I removed the class and changed to code a little to compensate for that.

Here’s the class:


using System.Collections;
using System.IO;
using System.Text;
//using System.Xml; //System.Xml.Legacy.dll
using GHIElectronics.NETMF.Hardware;
using Utility = Microsoft.SPOT.Hardware.Utility;


public static class InternalFlashStorageEx
{
    static Hashtable myHashtable = null;
    const byte FlashPopulatedMarker = 1;

    public static void Initialize()
    {
        Release();
        byte[] storage = new byte[InternalFlashStorage.Size];
        InternalFlashStorage.Read(storage);

        byte[] leadBytes = Utility.ExtractRangeFromArray(storage, 0, 3);
        // Check to see if our marker, "<s>", is in the first three bytes of the data. 
        if (leadBytes[0] == 60 && leadBytes[1] == 115 && leadBytes[2] == 62)
        {
            string s = new string(System.Text.Encoding.UTF8.GetChars(storage));
            storage = null;

            /// instead of building a hashtable (which is slow) to store the settings
            /// rather keep them in an xml document and later on just get the value attribute for a setting with a specific name attribute
            MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(s));
            s = null;
            myHashtable = GetHashtableFromXMLMemoryStream(ms);
        }
        else myHashtable = new Hashtable();
    }

    private static Hashtable GetHashtableFromXMLMemoryStream(MemoryStream ms)
    {
        Hashtable table = new Hashtable();

        ms.Position = 0;
        StreamReader reader = new StreamReader(ms);		

        string msLine = reader.ReadLine();
        int start = 0;
        int end = 0;

        if (msLine != "")
        {
            ArrayList kv = new ArrayList();

            while (true)
            {
                start = msLine.IndexOf("<a", end);
                if (start == -1) break;
                end = msLine.IndexOf("/>", start);
                kv.Add(msLine.Substring(start, (end + 2) - start));
            }
            foreach (string item in kv)
            {
                start = item.IndexOf(" k='") + 4;
                end = item.IndexOf("'", start);
                string key = item.Substring(start, end - start);
                start = item.IndexOf(" v='") + 4;
                end = item.IndexOf("'", start);
                string value = item.Substring(start, end - start);
                if (key != "") table.Add(key, value);
            }
            kv.Clear();
        }
        
        reader.Close();
        reader.Dispose();
        ms.Close();
        ms.Dispose();

        return table;
    }

    public static void Add(string key, string value)
    {
        if (myHashtable == null) Initialize();
        myHashtable.Add(key, value);
        Save();
    }

    public static void Update(string key, string value)
    {
        if (myHashtable == null) Initialize();
        // If you try to update a value that did not exist, I don't care, I will just add it for you.
        if (!Contains(key)) myHashtable.Add(key, value);
        else myHashtable[key] = value;
        Save();
    }

    public static bool Contains(string key)
    {
        if (myHashtable == null) Initialize();
        return myHashtable.Contains(key);
    }

    public static string GetValue(string key)
    {
        if (myHashtable == null) Initialize();
        if (Contains(key)) return (string)myHashtable[key];
        else return null;
    }

    public static void Clear()
    {
        if (myHashtable != null) myHashtable.Clear();
        Save();
    }

    private static void Save()
    {
        string xml = "<s>";
        if (myHashtable != null)
            foreach(DictionaryEntry entry  in myHashtable)
                xml += "<a k='" + entry.Key + "' v='" + entry.Value + "' />";

        xml += "</s>";
        byte[] storage = new byte[InternalFlashStorage.Size];
        Encoding.UTF8.GetBytes(xml).CopyTo(storage, 0);
        InternalFlashStorage.Write(storage);
    }

    // Calling this will free up the memory the Hash table is using up.
    public static void Release()
    {
        if (myHashtable != null) myHashtable = null;
    }
}

And here’s an example to read settings (where LOG is the setting name):


            InternalFlashStorageEx.Initialize();
            if (!InternalFlashStorageEx.Contains("LOG"))
                InternalFlashStorageEx.Add("LOG", "0");
            else 
                log_data = (InternalFlashStorageEx.GetValue("LOG") == "0" ? false : true);

            InternalFlashStorageEx.Release();

Here’s an example on updating an existing setting:


            InternalFlashStorageEx.Initialize();
            InternalFlashStorageEx.Update("Trip", data.Trip.ToString("F6"));
            InternalFlashStorageEx.Release();

Remember to do the “Release” command before powering off as I have found it to corrupt the flash if I don’t.

Hope this help for you

Also note that the USBizi has something like 8 bytes that can be written ONCE ONLY. This should be enough to store a MAC…