Main Site Documentation

Driver of Flash Shield


#1

Hi,

I’m trying to use Atmel AT45DB161D Dataflash (bare chip) with FEZ Domino.
Driver for Flash Shield http://www.tinyclr.com/downloads/Component/FEZ_Shields_Flash.cs worked fine. However, I found page write method write SRAM buffer only, but not writing buffer to the flash memory cell.
To write buffer to memory cell, It is necessary to send additional command.

So, I updated Flash Shield driver as the following.
[ulist]

  • Add “Buffer to Main Memory Page Program with Built-in Erase” operation to WritePage method
  • Modify format to specify page address bytes
  • Use Continuous Array Read (Low Frequency) instead of Buffer 1 Read for ReadPage method
    [/ulist]

Updated driver code:


using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;

namespace GHIElectronics.NETMF.FEZ
{
    public static partial class FEZ_Shields
    {
        public static class FlashShield
        {
            const byte Status_Register_Read = 0xD7;
            const byte Continuous_Array_Read = 0x03;    // Continuous Array Read (Low Frequency). Changed from Legacy command (0xE8)
            const byte Buffer_1_Read = 0xD1;            // Buffer 1 Read (Low Frequency)
            const byte Buffer_1_Write = 0x84;           // Buffer 1 Write
            const byte DB_BUF1_PAGE_ERASE_PGM = 0x83;   // Buffer to Main Memory Page Program with Built-in Erase
            const byte AT45DB161D_density = 0x2C;
            static private uint pageSize = 0;
            static private SPI Spi = null;

            static public void Initialize()
            {

                SPI.Configuration SPICfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di10, 
                    false, 0, 0, false, true, 16000, SPI.SPI_module.SPI1);
                Spi = new SPI(SPICfig);
                byte status = ReadStatusRegister();
                if ((status & 0x3C) != AT45DB161D_density)
                    throw new Exception("Not Supported Device or DataFlash");
                if ((status & 0x01) == 0x01)
                {
                    pageSize = 512;
                }
                else
                {
                    pageSize = 528;
                }
            }

            static public uint PageSize
            {
                get
                {
                    return pageSize;
                }
            }

            static private void SendCommandAndData(byte[] command, byte[] data)
            {
                if (command != null && data != null)
                {
                    byte[] temp = new byte[command.Length + data.Length];
                    for (int i = 0; i < command.Length; i++)
                    {
                        temp[i] = command[i];
                    }
                    for (int i = 0; i < data.Length; i++)
                    {
                        temp[i + command.Length] = data[i];
                    }
                    Spi.WriteRead(temp, temp);
                    for (int i = 0; i < command.Length; i++)
                    {
                        command[i] = temp[i];
                    }
                    for (int i = 0; i < data.Length; i++)
                    {
                        data[i] = temp[i + command.Length];
                    }


                }
                else
                {
                    if (command != null)
                        Spi.WriteRead(command, command);
                    if (data != null)
                        Spi.WriteRead(data, data);
                }
            }

            static private byte ReadStatusRegister()
            {
                byte[] cmd = new byte[2] { Status_Register_Read, 0 };
                SendCommandAndData(cmd, null);
                return cmd[1];
            }

            static public void ReadPage(uint PageNumber, byte[] buffer)
            {
                if (buffer.Length < PageSize)
                    throw new Exception("Buffer Size is smaller than Page Size");

                byte[] cmd = new byte[4];

                cmd[0] = Continuous_Array_Read;
                /*
                 * 3 address bytes consist of :
                 *  - 2 don't care bits
                 *  - 12 page address bits (PA11 - PA0) that specify the page in 
                 *    the main memory to be written
                 *  - 10 buffer address bits (BA9 - BA0) --> Allways set to 0
                 */
                cmd[1] = (byte)(PageNumber >> 6);
                cmd[2] = (byte)(PageNumber << 2);
                cmd[3] = 0;
                SendCommandAndData(cmd, buffer);
                for (int timeout = 0; timeout < 100; timeout++)
                    if ((ReadStatusRegister() & 0x80) > 0)
                        return;
                throw new Exception("Error reading data");

            }

            static public void WritePage(uint PageNumber, byte[] buffer)
            {
                if (buffer.Length < PageSize)
                    throw new Exception("Buffer Size is smaller than Page Size");
                byte[] cmd = new byte[4];

                // Write data to buffer 1
                cmd[0] = Buffer_1_Write;
                /*
                 * 3 address bytes consist of :
                 *  - 14 don't care bits
                 *  - 10 buffer address bits (BA9 - BA0) --> Allways set to 0
                 */
                cmd[1] = 0;
                cmd[2] = 0;
                cmd[3] = 0;
                SendCommandAndData(cmd, buffer);

                cmd[0] = DB_BUF1_PAGE_ERASE_PGM;
                /*
                 * 3 address bytes consist of :
                 *  - 2 don't care bits
                 *  - 12 page address bits (PA11 - PA0) that specify the page in 
                 *    the main memory to be written
                 *  - 10 don't care bits
                 */
                cmd[1] = (byte)(PageNumber >> 6);
                cmd[2] = (byte)(PageNumber << 2);
                cmd[3] = 0;
                SendCommandAndData(cmd, null);
                for (int timeout = 0; timeout < 100; timeout++)
                    if ((ReadStatusRegister() & 0x80) > 0)
                        return;
                throw new Exception("Error writeing data");

            }
        }
    }
}


#2

Nice work. When code share is out, you (or anyone) can even update our code right on the website.


#3

We will test the changes and update our driver.
Also your full name will be added to the license header rgiht after. Is it OK with you?


#4

[quote]We will test the changes and update our driver.
Also your full name will be added to the license header rgiht after. Is it OK with you?[/quote]

Wow, I have no problem to add my name. I think you can find it from my profile data.
Please take note that address composition part of modification is derived from Arduino driver code. http://blog.blockos.org/?p=27


#5

Just a small remark: you should use Array.Copy() when copying arrays (in SendCommandAndData())


#6

Hi randoom,

Thank you for your comments.
I rewrote SendCommandAndData() method using Array.copy() as follows:

static private void SendCommandAndData(byte[] command, byte[] data)
{
    if (command != null && data != null)
    {
        byte[] temp = new byte[command.Length + data.Length];
        Array.Copy(command, temp, command.Length);
        Array.Copy(data, 0, temp, command.Length, data.Length);
        Spi.WriteRead(temp, temp);
        Array.Copy(temp, command, command.Length);
        Array.Copy(temp, command.Length, data, 0, data.Length);

        //for (int i = 0; i < command.Length; i++)
        //{
        //    temp[i] = command[i];
        //}
        //for (int i = 0; i < data.Length; i++)
        //{
        //    temp[i + command.Length] = data[i];
        //}
        //Spi.WriteRead(temp, temp);
        //for (int i = 0; i < command.Length; i++)
        //{
        //    command[i] = temp[i];
        //}
        //for (int i = 0; i < data.Length; i++)
        //{
        //    data[i] = temp[i + command.Length];
        //}
    }
    else
    {
        if (command != null)
            Spi.WriteRead(command, command);
        if (data != null)
            Spi.WriteRead(data, data);
    }
}

This code is simpler and more efficient.