Thursday, August 28, 2014

Flash Memory Library


Flash Memory Library



This library provides routines for accessing microcontroller's (internal) Flash memory.

On the dsPIC30/33 and PIC24, Flash memory is mapped to address space 3:2, which means that every 3 consecutive bytes of Flash have 2 consecutive address locations available. That is why mikroE's library allows data to be written to flash in two ways: "regular" and "compact". In the "regular" mode, which is used for word(16-bit) variables, the 3rd (un-addressable) flash memory byte remains unused. In the "compact" mode, which can be used for 1 byte-sized variables/arrays, all flash bytes are being used.

All dsPIC30/33 and PIC24 MCUs use the RTSP module to perform Read/Erase/Write operations on Flash memory. This, together with the internal structure of the Flash, imposes certain rules to be followed when working with Flash memory:

dsPIC30:


  • Erasing can be done only in 32-instructions (64 addresses, 96 bytes) memory blocks. This means that the block start address should be a multiply of 64 (i.e. have 6 lower bits set to zero).
  • Data is read and written in 4-instructions (8 addresses, 12 bytes) blocks.This means that the block start address should be a multiply of 8 (i.e. have 3 lower bits set to zero).
  • On the dsPIC30s, 2 address locations are assigned on every 3 bytes of (flash) program memory. Due to this specific and non-one-to-one address mapping, the mikroC PRO for dsPIC30/33 and PIC24 offers two sets of Flash handling functions: "regular" and "compact".
    Using the "regular" set, the user can write one byte of data to a single address, which means that each byte of written data has its own address, but on every 2 written bytes one byte of Flash memory remains empty.
    Using the "compact" set, every byte of Flash memory, including those non-addressable, is filled with data; this method can only be used for data organized in bytes.
    The "compact" functions have _Compact as name suffix.
  • For run-time FLASH read/write, the dsPIC30's RTSP module is being used. It organizes data into rows and panels. Each row contains write latches that can hold 4 instructions (12 bytes). The number of panels varies from one dsPIC30 MCU model to another. Because of that, the flash write sequence has been split into several operations (_Write_Init(), _Write_LoadLatch4(), _Write_DoWrite()), in order to be usable on all dsPICs.

PIC24 and dsPIC33:


  • Erasing can be done only in 512-instructions (1024 addresses, 1536 bytes) memory blocks, which means that the block start address should be a multiply of 1024 (i.e. have 10 lower bits set to zero).
  • Data is read and written in 64-instructions (128 addresses, 192 bytes) blocks.This means that the block start address should be a multiply of 128 (i.e. have 7 lower bits set to zero).
  • On the dsPIC33 and PIC24s, 2 address locations are assigned on every 3 bytes of (flash) program memory. Due to this specific and non-one-to-one address mapping, the mikroC PRO for dsPIC30/33 and PIC24 offers two sets of Flash handling functions: "regular" and "compact".
    Using the "regular" set, the user can write one byte of data to a single address, which means that each byte of written data has its own address, but on every 2 written bytes one byte of Flash memory remains empty.
    Using the "compact" set, every byte of Flash memory, including those non-addressable, is filled with data; this method can only be used for data organized in bytes.
    The "compact" functions have _Compact as name suffix.

24F04KA201 and 24F16KA102 Family Specifics :


  • These MCU's have their Flash memory organized into memory blocks of 32 instructions (96 bytes), unlike other PIC24 devices.
  • Erasing can be done only in 32-instructions (64 addresses, 96 bytes) memory blocks, which means that the block start address should be a multiply of 64 (i.e. have 6 lower bits set to zero).
  • Data is read and written in 32-instructions (64 addresses, 96 bytes) blocks. This means that the block start address should be a multiply of 64 (i.e. have 6 lower bits set to zero).
  • Unlike other PIC24 devices, writing or erasing one block of data (32 instructions), is followed by erasing the memory block of the same size (32 instructions).

Library Routines


dsPIC30 Functions





PIC24 and dsPIC33 Functions



dsPIC30 Functions


FLASH_Erase32


Prototype void FLASH_Erase32(unsigned long address);
Description Erases one block (32 instructions, 64 addresses, 96 bytes)from the program FLASH memory.
Parameters
  • address: starting address of the FLASH memory block
Returns Nothing.
Requires Nothing.
Example
//--- erase the 32-instruction block, starting from address 0x006000
FLASH_Erase32(0x006000);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write_Block


Prototype void FLASH_Write_Block(unsigned long address, unsigned int *data_);
Description Fills one writeable block of Flash memory (4 instructions, 8 addresses, 12 bytes) in the "regular" mode. Addresses and data are being mapped 1-on-1. This also means that 3rd byte of each program location remains unused.
Parameters
  • address: starting address of the FLASH memory block
  • data_: data to be written
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code (through the RTSP), or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
Example
unsigned long flash_address = 0x006000;
unsigned int Buffer[4] = {'A', 'B', 'C', 'D'};
...
FLASH_Write_Block(flash_address, Buffer);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write_Compact


Prototype void FLASH_Write_Compact(unsigned long address, void *data_, unsigned bytes);
Description Fills a portion of Flash memory using the dsPIC30 RTSP module, in the "compact" manner. In this way, several blocks of RTSP's latch can be written in one pass. One latch block contains 4 instructions (8 addresses, 12 bytes). Up to 8 latch blocks can be written in one round, resulting in a total of 8*12 = 96 bytes. This method uses all available bytes of the program FLASH memory, including those that are not mapped to address space (every 3rd byte).
Parameters
  • address: starting address of the FLASH memory block
  • data_: data to be written
  • bytes: number of bytes to be written. The amount of bytes to be written must be a multiply of 12, since this is the size of the RTSP's write latch(es).
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code FLASH_Erase32, or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
Example
unsigned long flash_address = 0x006000;
char Buffer[] = "supercalifragillisticexpialidotious";
...
FLASH_Write_Compact(flash_address, Buffer, 36);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write_Init


Prototype void FLASH_Write_Init(unsigned long address, void *data_);
Description Initializes RTSP for write-to-FLASH operation.
Parameters
  • address: starting address of the FLASH memory block
  • data_: data to be written
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code FLASH_Erase32, or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
Example
//--- Initializes the Flash to be written, starting from address 0x006100, the data is located at *pv1
void *pv1;
...
FLASH_Write_Init(0x006100, pv1);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write_Loadlatch4


Prototype void FLASH_Write_Loadlatch4();
Description Loads the current RTSP write latch with data (4 instructions, 8 addresses, 12 bytes). The data is filled in the "regular" mode.
Parameters None.
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code FLASH_Erase32, or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
This function is used as a part of the Flash write sequence, therefore the FLASH_Write_Init function must be called before this one.
This function can be called several times before commiting the actual write-to-Flash operation FLASH_Write_DoWrite. This depends on the organization of the RTSP module for the certain dsPIC30. Please consult the Datasheet for particular dsPIC30 on this subject.
Example
//--- writes data from an array, in "regular" manner
unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k'};
void * pv1;
...
pv1 = iArr;
FLASH_Write_Init(0x006100, pv1);
FLASH_Write_Loadlatch4();
FLASH_Write_Loadlatch4();
FLASH_Write_DoWrite();
Notes None.

FLASH_Write_Loadlatch4_Compact


Prototype void FLASH_Write_Loadlatch4_Compact();
Description Loads the current RTSP write latch with data (4 instructions, 8 addresses, 12 bytes). The data is filled in the "compact" mode.
Parameters None.
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code FLASH_Erase32, or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
This function is used as a part of the Flash write sequence, therefore the FLASH_Write_Init function must be called before this one.
This function can be called several times before committing actual write-to-Flash operation FLASH_Write_DoWrite. This depends on the organization of the RTSP module for the certain dsPIC30. Please consult the Datasheet for particular dsPIC30 on this subject.
Example
//--- writes data from an array of char, in "compact" manner
char cArr[] = "supercalifragillisticexpialidotious"; //35+1 bytes
void * pv1;
...
pv1 = cArr;
FLASH_Write_Init(0x006000, pv1);                     //init
FLASH_Write_Loadlatch4_Compact();                    //12 bytes
FLASH_Write_Loadlatch4_Compact();                    //12 bytes
FLASH_Write_Loadlatch4_Compact();                    //12 bytes
FLASH_Write_DoWrite();                               //commit write
 
Notes None.

FLASH_Write_DoWrite


Prototype void FLASH_Write_DoWrite();
Description Commits the FLASH write operation.
Parameters None.
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code FLASH_Erase32, or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
This function is used as a part of the Flash write sequence, therefore FLASH_Write_Init and certain number of FLASH_Write_Loadlatch4 or FLASH_Write_Loadlatch4_Compact function calls must be made before this one.
This function is to be called once, at the and of the FLASH write sequence.
Example
//--- writes data from an array, in "regular" manner
unsigned int iArr[16] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k'};
void * pv1;
...
pv1 = iArr;
FLASH_Write_Init(0x006100, pv1);
FLASH_Write_Loadlatch4();
FLASH_Write_Loadlatch4();
FLASH_Write_DoWrite();
Notes None.

FLASH_Read4


Prototype unsigned int* FLASH_Read4(unsigned long address, unsigned int *write_to);
Description Reads one latch row (4 instructions, 8 addresses) in the "regular" mode.

Parameters
  • address: starting address of the FLASH memory block to be read
  • write_to: starting address of RAM buffer for storing read data
Returns Starting address of RAM buffer for storing read data.
Requires Nothing.
Example
//--- reads 8 bytes (4 words) from location 0x006000 and stores it to *pv1;
unsigned int *pv1;
...
FLASH_Read4(0x006000, pv1);
Notes The user should take care of the address alignment (see the explanation at the beginning of this page).

FLASH_Read4_Compact


Prototype void* FLASH_Read4_Compact(unsigned long address, void *write_to);
Description Reads one latch row (4 instructions, 8 addresses) in the "compact" mode.
Parameters
  • address: starting address of the FLASH memory block to be read
  • write_to: starting address of RAM buffer for storing read data
Returns Starting address of RAM buffer for storing read data.
Requires Nothing.
Example
//--- reads 12 bytes (4 words) from location 0x006000 and stores it to *pv1;
unsigned int *pv1;
...
FLASH_Read4_Compact(0x006000, pv1);
Notes The user should take care of the address alignment (see the explanation at the beginning of this page).

PIC24 and dsPIC33 Functions


FLASH_Erase


Prototype void FLASH_Erase(unsigned long address);
Description Erases one block (512 instructions, 1024 addresses, 1536 bytes) from the program FLASH memory.
Parameters
  • address: starting address of the FLASH memory block
Returns Nothing.
Requires Nothing.
Example
//--- erase the flash memory block, starting from address 0x006400
unsigned long flash_address = 0x006400;
...
FLASH_Erase(flash_address);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write


Prototype void FLASH_Write(unsigned long address, unsigned int *data_);
Description Fills one writeable block of Flash memory (64 instructions, 128 addresses, 192 bytes) in the "regular" mode. Addresses and data are being mapped 1-on-1. This also means that 3rd byte of each program location remains unused.
Parameters
  • address: starting address of the FLASH memory block
  • data_: data to be written
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code (through the RTSP), or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
Example
unsigned int iArr[64] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e', 'k', 't', 'r', 'o', 'n', 'i', 'k', 'a'};
void * pv1;
...
pv1 = iArr;
FLASH_Write(0x006500, pv1);
Notes The user should take care about the address alignment (see the explanation at the beginning of this page).

FLASH_Write_Compact


Prototype void FLASH_Write_Compact(unsigned long address, char *data_);
Description Fills a portion of Flash memory (64 instructions, 128 addresses, 192 bytes) using the dsPIC33 and PIC24s RTSP (Run Time Self Programming) module, in the "compact" manner. This method uses all available bytes of the program FLASH memory, including those that are not mapped to address space (every 3rd byte).
Parameters
  • address: starting address of the FLASH memory block
  • data_: data to be written
Returns Nothing.
Requires The block to be written to must be erased first, either from the user code (FLASH_Erase), or during the programming of MCU. Please note that block size that is to be erased is different from the one that can be written with this function!
Example
char cArr[] = "supercalifragillisticexpialidotiousABCDEFGHIJKLMNOPRSTUVWXYZ1234";
void * pv1;
...
pv1 = cArr;
FLASH_Write_Compact(0x006400, pv1);
Notes The user should take care of the address alignment (see the explanation at the beginning of this page).

FLASH_Read


Prototype unsigned int* FLASH_Read(unsigned long address, unsigned int *write_to, unsigned NoWords);
Description Reads required number of words from the flash memory in the "regular" mode.
Parameters
  • address: starting address of the FLASH memory block to be read
  • write_to: starting address of RAM buffer for storing read data
  • NoWords: number of words to be read
Returns Address of RAM buffer for storing read data.
Requires
Example
unsigned Buffer[64];
unsigned long start_address = 0x6500;
...
FLASH_Read(start_address, Buffer, 10);
Notes The user should take care of the address alignment (see the explanation at the beginning of this page).

FLASH_Read_Compact


Prototype void *FLASH_Read_Compact(unsigned long address, void *write_to, unsigned NoBytes);
Description Reads required number of bytes from the flash memory in the "compact" mode.
Parameters
  • address: starting address of the FLASH memory block to be read
  • write_to: starting address of RAM buffer for storing read data
  • NoBytes: number of bytes to be read
Returns Address of RAM buffer for storing read data.
Requires
Example
char Buffer[64];
unsigned long start_address = 0x6500;
...
FLASH_Read_Compact(start_address, Buffer, 10);
Notes The user should take care of the address alignment (see the explanation at the beginning of this page).

Library Example


In this example written for dsPIC30F4013, various read/write tecniques to/from the on-chip FLASH memory are shown. Flash memory is mapped to address space 3:2, meaning every 3 consecutive bytes of Flash have 2 consecutive address locations available.
That is why mikroE's library allows data to be written to Flash in two ways: 'regular' and 'compact'. In 'regular' mode, which is used for variables that are size of 2 bytes and more, the 3rd (un-addressable) byte remains unused.
In 'compact' mode, which can be used for 1 byte-sized variables/arrays, all bytes of flash are being used.

unsigned int iArr[8] = {'m', 'i', 'k', 'r', 'o', 'E', 'l', 'e'};
char cArr[] = "mikroElektronika Flash example";
char cArr2[40];

void * pv1;
unsigned bb;

void main() {
  unsigned i;

  pv1 = cArr;

/*
  This is what FLASH_Write_Compact() does 'beneath the hood'
 *
  FLASH_Write_Init(0x006000, pv1);
  FLASH_Write_Loadlatch4_Compact();
  FLASH_Write_Loadlatch4_Compact();
  FLASH_Write_Loadlatch4_Compact();
  FLASH_Write_DoWrite();
 */

  //--- erase the block first
  FLASH_Erase32(0x006000);

  //--- write compact format to flash
  FLASH_Write_Compact(0x006000, pv1, 36);

  //--- read compact format
  pv1 = cArr2;
  FLASH_Read4_Compact(0x006000, pv1);
  pv1 += 12;
  FLASH_Read4_Compact(0x006008, pv1);
  pv1 += 12;
  FLASH_Read4_Compact(0x006010, pv1);
  pv1 += 12;
  *pv1 = 0;  //termination
  
  //--- show what has been written
  i = 0;
  UART1_Init(9600);
//  UART1_Write_Text("Start");
  UART1_Write(10);
  UART1_Write(13);
  while(cArr2[i]) {
    bb = cArr2[i++];
    UART1_Write(bb);
  }

  //--- now for some non-compact flash-write
  pv1 = iArr;
  //--- erase the block first
  FLASH_Erase32(0x006100);
  FLASH_Write_Init(0x006100, pv1);
  FLASH_Write_Loadlatch4();
  FLASH_Write_Loadlatch4();
  FLASH_Write_DoWrite();
}

No comments:

Post a Comment