Question: Mountaineer Memory

Hi, I just started with a a Mountaineer Ethernet board. The product sheet states that there is some flash Memory available - Flash: 1 MB (on chip) + 8 MB (on board). Since it seems that a SC Card is not suported the Flash Memory is the only way to persist data. I have not found Information how to do this. I’m using the Default SDK 4.2 (QEF1). The Mountaineer web site mentions that the Gadgeteer Framework is not supported with QEF2. Is it just not tested or does it not work at all? I also could not find a complete list of unsupported features (TimeServer ???). Any hint would be welcome…

Hi Peter,

not entirely sure that this is the [em]complete[/em] list of unsupported features, as there are a number of hardware-dependent or otherwise optional features in NETMF:

  • on-board Flash driver (but see the - unsupported - code given below, it could be useful as an iterim solution until a complete file system driver is available)

  • CAN bus

  • USB host (only relevant for Mountaineer USB Mainboards)

  • extended weak references (will not be supported, would waste too much Flash on the STM32F4)

  • real-time clock (only relevant if you add a battery for the RTC)

  • graphics (boards focus on headless devices, and Microsoft would have to improve some APIs to make graphics work reasonably well on microcontrollers with small memories)

  • MFUpdate / Microbooter for application and firmware updates in the field (someone in the community is working on this)

In QFE2, we have added XML support.

For a customer project, we needed analog outputs, which wasn’t supported in NETMF. So we added an analog output API, submitted it as a new NETMF standard API, had it reviewed by the NETMF core tech team, and now it is an official part of NETMF and implemented in QFE2.

For the rest of this year, we will focus on NETMF 4.3.

Afterwards, we’ll prioritize according to available resources and the needs from our service business customers.

I hope that this gives you a better idea of what is, and isn’t, currently supported for Mountaineer boards.

Best regards

Cuno

Here a simple block-level Flash driver:


// Copyright Oberon microsystems, Inc., 2012
// provisional, unsupported

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace Oberon.Netmf.Flash {
    public class Flash {

        const SPI.SPI_module SPI_MOD = SPI.SPI_module.SPI1;
        const Cpu.Pin CS_PIN = (Cpu.Pin)32; // PC0
        const int SPI_FREQ = 21000; // 21MHz         [corrected frequency]

        SPI spi;
        byte[] statusCmd = { 0x05 }; // read status command
        byte[] enableCmd = { 0x06 }; // enable write command
        byte[] readCmd = { 0x0B, 0, 0, 0 }; // fast read command
        byte[] writeCmd = new byte[260]; // page write command
        byte[] eraseCmd = { 0x20, 0, 0, 0 }; // erase block command (4kByte)
        byte[] statusBuf = new byte[1];

        /// <summary>
        /// Allocates a new object representing the external Flash chip.
        /// </summary>
        public Flash() {
            SPI.Configuration flashConfig = new SPI.Configuration(CS_PIN, false, 0, 0, true, true, SPI_FREQ, SPI_MOD);
            spi = new SPI(flashConfig);
            writeCmd[0] = 0x02; // page write
        }

        private void WaitReady() {
            spi.WriteRead(statusCmd, statusBuf, 1);
            while ((statusBuf[0] & 1) != 0) {
                Thread.Sleep(10);
                spi.WriteRead(statusCmd, statusBuf, 1);
            }
        }

        /// <summary>
        /// Reads a sequence of bytes from Flash.
        /// </summary>
        /// <param name="address">The start address to read from.</param>
        /// <param name="buffer">The buffer used to store the read bytes.</param>
        public void Read(int address, byte[] buffer) {
            readCmd[1] = (byte)(address >> 16);
            readCmd[2] = (byte)(address >> 8);
            readCmd[3] = (byte)address;
            WaitReady();
            spi.WriteRead(readCmd, buffer, 5); // read after 1 dummy byte
        }

        /// <summary>
        /// Reads a sequence of bytes from Flash.
        /// </summary>
        /// <param name="address">The start address to read from.</param>
        /// <param name="buffer">The buffer used to store the read bytes.</param>
        /// <param name="bytes">The number of bytes to read.</param>
        public void Read(int address, byte[] buffer, int bytes) {
            readCmd[1] = (byte)(address >> 16);
            readCmd[2] = (byte)(address >> 8);
            readCmd[3] = (byte)address;
            WaitReady();
            spi.WriteRead(readCmd, 0, 4, buffer, 0, bytes, 5); // read after 1 dummy byte
        }

        /// <summary>
        /// Writes a sequence of bytes to Flash.
        /// The sequence must be within a single 256 Byte sector.
        /// </summary>
        /// <param name="address">The start address to write to.</param>
        /// <param name="buffer">The buffer holding the bytes to write.</param>
        public void Write(int address, byte[] buffer) {
            writeCmd[1] = (byte)(address >> 16);
            writeCmd[2] = (byte)(address >> 8);
            writeCmd[3] = (byte)address;
            Array.Copy(buffer, 0, writeCmd, 4, buffer.Length);
            WaitReady();
            spi.Write(enableCmd);
            spi.WriteRead(writeCmd, 0, buffer.Length + 4, null, 0, 0, 0);
        }

        /// <summary>
        /// Erases a 4 KByte Page.
        /// </summary>
        /// <param name="address">An address inside the page to erase.</param>
        public void Erase(int address) {
            eraseCmd[1] = (byte)(address >> 16);
            eraseCmd[2] = (byte)(address >> 8);
            eraseCmd[3] = (byte)address;
            WaitReady();
            spi.Write(enableCmd);
            spi.Write(eraseCmd);
        }
    }
}

Thanks for the info Cuno. I will try to write a simple driver to dump application settings directly to the flash memory. Any idea when the Gadgeteer stuff will be working (Netmf 4.3) and would it make sense to try it with 4.2 QFE2? By the way what is the difference in the XML support in QFE2?

@ Cuno -

I tried the code to read and write to the Flash memory. I checked the board schematics - the flash memory is 64 MByte large. The flash size mentioned in the spec is 8MBytes. So the question is what is the address of the useable flash area where I can read and write application data?

The Flash is 64 MBit (= 8 MByte).

The Flash addresses are zero-based (0x00000000 - 0x007FFFFF).

As for NETMF 4.3, we have to see when Microsoft comes out with a release candidate, and then the final release. Hopefully the whole cycle goes through before the end of this year.

As for XML parser, we didn’t have this part of NETMF in the QFE1 firmware. It requires native code for speed reasons, thus cannot be added later by an application.

@ Cuno - Sorry, I ment 64 MBit - however, I’m not getting any data from the Flash - I’m trying to read the id (manufacturer, device, unique) but I’m always getting 0s in the data. This was the reason for the question if I would have to use a different address range. So it seems there is another issue here - Do I have to enable the Flash Memory somehow (after Startup)?

As far as the XML Support is concerned - the Gadgeteer core library is not tested / working because of the missing analog ouput support. Would the other stuff work if I upgrade now?

Cuno,

Why not the option of placing the extended weak references in the external flash? :slight_smile:

Hi Peter,

You don’t have to enable the flash memory, but the SPI bus uses a “chip select” signal in order to communicate with the chip. The chip select port is PC0 (see schematics), thus pin 32 (PA0 = 0, PA1 = 1, PA15 = 15, PB0 = 16, etc.)

The following code should allow you reading the flash ID:

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace MountaineerFlashTest
{
	class FlashTest
	{
		public static void Main()
		{
			// Check serial Flash connection
			int id;
			byte[] buf = new byte[6];

            SPI.Configuration flashConfig = new SPI.Configuration((Cpu.Pin)32, false, 1, 1, true, true, 100, SPI.SPI_module.SPI1);
			SPI flash = new SPI(flashConfig);

			while (true)
			{
				flash.WriteRead(new byte[] { 0x90 }, buf); // read device ID

				id = buf[5];
				if(buf[4] == 0xEF && buf[5] == 0x16)
				{
					Debug.Print("\r\nFlash ID read OK");
				}
				else
				{
					Debug.Print("\r\nFlash connection failed (" + id + ") !!!");
				}
			}
		}	
	}
}

Does it work?

@ GMod(Errol) -

Maybe EWR in external Flash would be an interesting community project?

For our professional projects, we avoid EWR. We want more control over the time when data is actually written to Flash.

You can use any BlockStorage device with EWR.

On the Argon R1 the EWR blocks are located in the External NAND.

const BlockRange g_M68A_1GB_NAND_BlockRange[] =
{
    { BlockRange::BLOCKTYPE_STORAGE_A,  0, 1 },   // Space for ExtendedWeakReference - Storage Section A
    { BlockRange::BLOCKTYPE_STORAGE_B,  2, 3 },   // Space for ExtendedWeakReference - Storage Section B

@ Corentin - All what I had to do was to change the frequency - You had 100 (instead of 80000) and with this it works like a charm. All the other stuff is working (read IDs, read, write etc.). I don’t know what the best value for that would be - since I’m just storing application settings performance is not really an issue.
I have no problem to quickly hack up a simple store / load for settings I but I think the best would be a simple file system Interface on top of the flash memory.

You’re right Peter, 80 MHz (80000) is somewhat excessive. I made a couple of measurements, the maximum SPI clock frequency should stay below 30MHz.

Information: the frequency set here

SPI.Configuration flashConfig = new SPI.Configuration((Cpu.Pin)32, false, 1, 1, true, true, frequency, SPI.SPI_module.SPI1);

will be rounded down to the following values: 42000, 21000, 10500, 5250, 2625, … kHz (set by the internal clock divider in the STM32). So for example, setting the clock frequency to 30000 will give an effective clock frequency of 21 MHz.

I have changed the source code on the previous page accordingly (to 21 MHz).

Can someone point me to where the community is developing a file system driver for the flash? Is there anyone working on this? I probably can’t help build it, but I could certainly help test it.

You may want to take a look at this thread:
http://www.tinyclr.com/forum/topic?id=8514

@ CUNO -
Any update on when an update may be coming out. I’m looking for RTC and watchdog for the usb model.
Thanks

@ MikeCormier -

Still aiming for Q2 2013 for the 4.3 release. RTC and watchdog are both on the wish list, but will probably come later.