FEZ Cerberus - InternalFlash

Hi,

I would like to store few kB (application settings) in internal flash region of STM32F4 chip it self. I know I can access flash address space via base address 0x08000000, problem is to find some reserved space that is safe to be used for this purpose.

I was diggin in source NETMF_for_STM32, file STM32F4_BlConfig.cpp and found out this configuration of blockstorage:


const BlockRange g_STM32F4_BlockRange3[] =
{
    { BlockRange::BLOCKTYPE_CODE      ,   0, 2 },  // 08020000 CLR         384k
    { BlockRange::BLOCKTYPE_DEPLOYMENT,   3, 6 },  // 08080000 deployment  512k
    //{ BlockRange::BLOCKTYPE_STORAGE_A ,   5, 5 },  // 080C0000 storage A   128k
    //{ BlockRange::BLOCKTYPE_STORAGE_B ,   6, 6 },  // 080E0000 storage B   128k
};

What are regions storage A, and B for ?

Thanks for any reply.

Jan

Both of these areas are used by ExtendedWeakReference storage subsystem.

@ Architect - I tought that ExtendedWeakReference storage doesn’t work on Cerberus familly ? Or I’m wrong ? And if this place is dedicated to EWR that If i’m not using it I can use storage B without any trouble ? Or not ?

Yes and that is why they are commented out :slight_smile:

It is commented out - not used.

Then expect InternalStorage class from me on Codeshare :slight_smile:

Thanks guys a lot! :slight_smile:

Looking forward to it! :slight_smile:

You are welcome!

Hi all,

Johny have you made any progress on the InternalStorage class? If not , can you share whatever code you have so we can start from there? Is it possible to implement it in managed code?

Regards.

Please see http://wiki.tinyclr.com/index.php?title=FEZ_Cerberus_Developer#Why_EWR_is_not_available_on_cerb-family.3F

Adding EEPROM is the preferred option.

Ok, is clear that EWR would be overkill for the cerberus architecture, but I just need 1kb or so to store configuration parameters, and I wonder if I can use the unused flash segments in the chip and it seems that Johny has a point there.

Well currenty have trouble unlocking flash for write operation. My current code is:


using System;
using Microsoft.SPOT;
using GHI.OSHW.Hardware;
using GHI.OSHW.Hardware.LowLevel;

namespace STM32F4.IO
{
    public static class InternalStorage
    {
        private const uint StorageAddressBase = 0x080C0000;
        private const uint StorageSize = 0x40000;
        private const uint StorageAddressMax = StorageAddressBase + StorageSize - 1;

        //definitions taken from http://www.keil.com/dd/docs/arm/st/stm32f4xx/stm32f4xx.h
        //#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
        //#define FLASH_BASE            ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */
        //#define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)
        //#define FLASH_R_BASE          (AHB1PERIPH_BASE + 0x3C00)
        //#define FLASH               ((FLASH_TypeDef *) FLASH_R_BASE)
        //typedef struct
        //{
        //  __IO uint32_t ACR;      /*!< FLASH access control register, Address offset: 0x00 */
        //  __IO uint32_t KEYR;     /*!< FLASH key register,            Address offset: 0x04 */
        //  __IO uint32_t OPTKEYR;  /*!< FLASH option key register,     Address offset: 0x08 */
        //  __IO uint32_t SR;       /*!< FLASH status register,         Address offset: 0x0C */
        //  __IO uint32_t CR;       /*!< FLASH control register,        Address offset: 0x10 */
        //  __IO uint32_t OPTCR;    /*!< FLASH option control register, Address offset: 0x14 */
        //} FLASH_TypeDef;

        private const UInt32 Flash_ACR = 0x8023C00;
        private const UInt32 Flash_KEYR = 0x8023C04;
        private const UInt32 Flash_OPTKEYR = 0x8023C08;
        private const UInt32 Flash_SR = 0x8023C0C;
        private const UInt32 Flash_CR = 0x8023C10;
        private const UInt32 Flash_OPTCR = 0x8023C14;

                /*******************  Bits definition for FLASH_SR register  ******************/
        private const UInt32 FLASH_SR_EOP = 0x00000001;
        private const UInt32 FLASH_SR_SOP = 0x00000002;
        private const UInt32 FLASH_SR_WRPERR = 0x00000010;
        private const UInt32 FLASH_SR_PGAERR = 0x00000020;
        private const UInt32 FLASH_SR_PGPERR = 0x00000040;
        private const UInt32 FLASH_SR_PGSERR = 0x00000080;
        private const UInt32 FLASH_SR_BSY = 0x00010000;

        /*******************  Bits definition for FLASH_CR register  ******************/
        private const UInt32 FLASH_CR_PG = 0x00000001;
        private const UInt32 FLASH_CR_SER = 0x00000002;
        private const UInt32 FLASH_CR_MER = 0x00000004;
        private const UInt32 FLASH_CR_SNB_0 = 0x00000008;
        private const UInt32 FLASH_CR_SNB_1 = 0x00000010;
        private const UInt32 FLASH_CR_SNB_2 = 0x00000020;
        private const UInt32 FLASH_CR_SNB_3 = 0x00000040;
        private const UInt32 FLASH_CR_PSIZE_0 = 0x00000100;
        private const UInt32 FLASH_CR_PSIZE_1 = 0x00000200;
        private const UInt32 FLASH_CR_STRT = 0x00010000;
        private const UInt32 FLASH_CR_EOPIE = 0x01000000;
        private const UInt32 FLASH_CR_LOCK = 0x80000000;

        private const UInt32 FLASH_KEY1 = 0x45670123;
        private const UInt32 FLASH_KEY2 = 0xCDEF89AB;
        private const UInt32 FLASH_OPT_KEY1 = 0x08192A3B;
        private const UInt32 FLASH_OPT_KEY2 = 0x4C5D6E7F;

        private const UInt32 FLASH_PSIZE_BYTE = 0x00000000;
        private const UInt32 FLASH_PSIZE_HALF_WORD = 0x00000100;
        private const UInt32 FLASH_PSIZE_WORD = 0x00000200;
        private const UInt32 FLASH_PSIZE_DOUBLE_WORD = 0x00000300;
        private const UInt32 CR_PSIZE_MASK = 0xFFFFFCFF;

        private static Register ACR, KEYR, OPTKEYR, SR, CR, OPTCR;
        /// <summary>
        /// Static construtor to check right platform
        /// </summary>
        static InternalStorage()
        {
            CheckPlatform();
            ACR = new Register(Flash_ACR);
            KEYR = new Register(Flash_KEYR);
            OPTKEYR = new Register(Flash_OPTKEYR);
            SR = new Register(Flash_SR);
            CR = new Register(Flash_CR);
            OPTCR = new Register(Flash_OPTCR);
        }
        /// <summary>
        /// Check if code is running on CERB
        /// </summary>
        private static void CheckPlatform()
        {
            if (DeviceInfo.GetDeviceID() != DeviceID.FEZ_CERB)
            {
                throw new NotSupportedException();
            }
        }

        /// <summary>
        /// An internal flash size bytes for storage.
        /// </summary>
        public static uint Length
        {
            get
            {
                return StorageSize;
            }
        }

        //void FLASH_Unlock(void)
        //{
        //  if((FLASH->CR & FLASH_CR_LOCK) != RESET)
        //  {
        //    /* Authorize the FLASH Registers access */
        //    FLASH->KEYR = FLASH_KEY1;
        //    FLASH->KEYR = FLASH_KEY2;
        //  }  
        //}
        private static void UnlockFlash()
        {
            if((CR.Read() & FLASH_CR_LOCK) != 0)
            {
                KEYR.Write(FLASH_KEY1);
                KEYR.Write(FLASH_KEY2);
            }
        }
//void FLASH_Lock(void)
//{
//  /* Set the LOCK Bit to lock the FLASH Registers access */
//  FLASH->CR |= FLASH_CR_LOCK;
//}
        private static void LockFlash()
        {
            CR.Write(CR.Read() | FLASH_CR_LOCK);
        }
        /// <summary>
        /// Reading bytes from internal storage
        /// </summary>
        /// <param name="buffer">An initialized byte buffer, where data will be stored from flash.</param>
        /// <param name="storageAddress">An address of storage</param>
        /// <param name="bufferIndex"></param>
        /// <param name="lenght"></param>
        public static void Read(byte[] buffer, uint storageAddress, int bufferIndex, int lenght)
        {
            uint address = storageAddress + StorageAddressBase;
            uint addressEnd = storageAddress + StorageAddressBase + (uint)lenght;
            if (address > StorageAddressMax)
            {
                throw new IndexOutOfRangeException();
            }

            AddressSpace.Read(address, buffer, bufferIndex, lenght);
        }

        public static void Write(byte[] buffer, uint storageAddress, int bufferIndex, int lenght)
        {
            uint address = storageAddress + StorageAddressBase;
            if (address > StorageAddressMax)
            {
                throw new IndexOutOfRangeException();
            }

            try
            {
                UnlockFlash();
                /*
                 *      FLASH->CR &= CR_PSIZE_MASK;
                        FLASH->CR |= FLASH_PSIZE_BYTE;
                        FLASH->CR |= FLASH_CR_PG;
                 * */
                CR.Write(CR.Read() & CR_PSIZE_MASK);
                CR.Write(CR.Read() | FLASH_PSIZE_BYTE);
                CR.Write(CR.Read() | FLASH_CR_PG);
                AddressSpace.Write(address, buffer, bufferIndex, lenght);
                CR.Write(CR.Read() & (~FLASH_CR_PG));
            }
            finally
            {
                LockFlash();
            }
        }
    }
}

We posted a version of this in Codeshare : see http://www.tinyclr.com/forum/topic?id=8477

1 Like

Hi vqp,

glad you finished it, you save me few hours of diggin in.

Thanks :slight_smile:

Jan